diff options
Diffstat (limited to 'apps')
98 files changed, 1516 insertions, 473 deletions
diff --git a/apps/admin_audit/appinfo/info.xml b/apps/admin_audit/appinfo/info.xml index 98862554090..e5ec9db0689 100644 --- a/apps/admin_audit/appinfo/info.xml +++ b/apps/admin_audit/appinfo/info.xml @@ -2,9 +2,7 @@ <info> <id>admin_audit</id> <name>Auditing / Logging</name> - <description>Provides logging abilities for Nextcloud such as logging file - accesses or otherwise sensitive actions. - </description> + <description>Provides logging abilities for Nextcloud such as logging file accesses or otherwise sensitive actions.</description> <licence>AGPL</licence> <author>Nextcloud</author> <version>1.2.0</version> diff --git a/apps/comments/l10n/fr.js b/apps/comments/l10n/fr.js index 21641df269b..588f429babc 100644 --- a/apps/comments/l10n/fr.js +++ b/apps/comments/l10n/fr.js @@ -9,7 +9,7 @@ OC.L10N.register( "Cancel" : "Annuler", "Edit comment" : "Modifier le commentaire", "[Deleted user]" : "[Utilisateur supprimé]", - "No comments yet, start the conversation!" : "Il n'y a aucun commentaire, démarrer la conversation!", + "No comments yet, start the conversation!" : "Aucun commentaire actuellement, débutez une conversation !", "More comments …" : "Plus de commentaires ...", "Save" : "Enregistrer", "Allowed characters {count} of {max}" : "{count} sur {max} caractères autorisés", diff --git a/apps/comments/l10n/fr.json b/apps/comments/l10n/fr.json index c8aa168fc3c..71e3823b84a 100644 --- a/apps/comments/l10n/fr.json +++ b/apps/comments/l10n/fr.json @@ -7,7 +7,7 @@ "Cancel" : "Annuler", "Edit comment" : "Modifier le commentaire", "[Deleted user]" : "[Utilisateur supprimé]", - "No comments yet, start the conversation!" : "Il n'y a aucun commentaire, démarrer la conversation!", + "No comments yet, start the conversation!" : "Aucun commentaire actuellement, débutez une conversation !", "More comments …" : "Plus de commentaires ...", "Save" : "Enregistrer", "Allowed characters {count} of {max}" : "{count} sur {max} caractères autorisés", diff --git a/apps/comments/l10n/nb_NO.js b/apps/comments/l10n/nb_NO.js index a73cdd768f4..d6ac9a2b7b6 100644 --- a/apps/comments/l10n/nb_NO.js +++ b/apps/comments/l10n/nb_NO.js @@ -26,6 +26,8 @@ OC.L10N.register( "%1$s commented on %2$s" : "%1$s kommenterte %2$s", "{author} commented on {file}" : "{author} kommenterte på {file}", "<strong>Comments</strong> for files" : "<strong>Kommentarer</strong> for filer", + "A (now) deleted user mentioned you in a comment on “%s”" : "En (now) slettet bruker nevnte deg i en kommentar til “%s”", + "A (now) deleted user mentioned you in a comment on “{file}”" : "A (now) slettet bruker nevnte deg i en kommentar til “{file}”", "%1$s mentioned you in a comment on “%2$s”" : "%1$s nevnte deg i en kommentar på “%2$s”", "{user} mentioned you in a comment on “{file}”" : "{user} nevnte deg i en kommentar på “{file}”", "Type in a new comment..." : "Skriv inn en ny kommentar...", diff --git a/apps/comments/l10n/nb_NO.json b/apps/comments/l10n/nb_NO.json index 84f83315f25..293eca39e84 100644 --- a/apps/comments/l10n/nb_NO.json +++ b/apps/comments/l10n/nb_NO.json @@ -24,6 +24,8 @@ "%1$s commented on %2$s" : "%1$s kommenterte %2$s", "{author} commented on {file}" : "{author} kommenterte på {file}", "<strong>Comments</strong> for files" : "<strong>Kommentarer</strong> for filer", + "A (now) deleted user mentioned you in a comment on “%s”" : "En (now) slettet bruker nevnte deg i en kommentar til “%s”", + "A (now) deleted user mentioned you in a comment on “{file}”" : "A (now) slettet bruker nevnte deg i en kommentar til “{file}”", "%1$s mentioned you in a comment on “%2$s”" : "%1$s nevnte deg i en kommentar på “%2$s”", "{user} mentioned you in a comment on “{file}”" : "{user} nevnte deg i en kommentar på “{file}”", "Type in a new comment..." : "Skriv inn en ny kommentar...", diff --git a/apps/comments/l10n/zh_CN.js b/apps/comments/l10n/zh_CN.js index a2eb29f322f..9a459c92b6e 100644 --- a/apps/comments/l10n/zh_CN.js +++ b/apps/comments/l10n/zh_CN.js @@ -8,7 +8,7 @@ OC.L10N.register( "Post" : "发布", "Cancel" : "取消", "Edit comment" : "编辑评论", - "[Deleted user]" : "[Deleted user]", + "[Deleted user]" : "[已删除用户]", "No comments yet, start the conversation!" : "还没有评论,开始对话吧!", "More comments …" : "更多评论 ...", "Save" : "保存", @@ -22,18 +22,18 @@ OC.L10N.register( "%1$s commented" : "%1$s 已评论", "{author} commented" : "{author} 评论了", "You commented on %1$s" : "您在 %1$s 的评论", - "You commented on {file}" : "您对 {file} 的注释", + "You commented on {file}" : "您对 {file} 的评论", "%1$s commented on %2$s" : "%1$s 评论了 %2$s", - "{author} commented on {file}" : "{author} 对 {file} 的注释", - "<strong>Comments</strong> for files" : "显示文件的<strong>注释</strong>", - "A (now) deleted user mentioned you in a comment on “%s”" : "一个(正)被删除的用户提醒您注释 “%s”", - "A (now) deleted user mentioned you in a comment on “{file}”" : "一个(正)被删除的用户提醒您注释 “{file}”", - "%1$s mentioned you in a comment on “%2$s”" : "%1$s 提醒您注释 “%2$s”", - "{user} mentioned you in a comment on “{file}”" : "{user} 提醒您注释 “{file}”", + "{author} commented on {file}" : "{author} 对 {file} 的评论", + "<strong>Comments</strong> for files" : "文件的<strong>评论</strong>", + "A (now) deleted user mentioned you in a comment on “%s”" : "一个(已)被删除的用户在 “%s” 的评论中提到了您", + "A (now) deleted user mentioned you in a comment on “{file}”" : "一个(已)被删除的用户在 “{file}” 的评论中提到了您", + "%1$s mentioned you in a comment on “%2$s”" : "%1$s 在 “%2$s” 的评论中提到了您", + "{user} mentioned you in a comment on “{file}”" : "{user} 在 “{file}” 的评论中提到了您", "Type in a new comment..." : "添加新评论...", "No other comments available" : "没有其他评论", "More comments..." : "更多评论...", "{count} unread comments" : "{count} 条未读评论", - "You commented on %2$s" : "你评论了 %2$s" + "You commented on %2$s" : "您评论了 %2$s" }, "nplurals=1; plural=0;"); diff --git a/apps/comments/l10n/zh_CN.json b/apps/comments/l10n/zh_CN.json index cbc878d898c..be867c5b856 100644 --- a/apps/comments/l10n/zh_CN.json +++ b/apps/comments/l10n/zh_CN.json @@ -6,7 +6,7 @@ "Post" : "发布", "Cancel" : "取消", "Edit comment" : "编辑评论", - "[Deleted user]" : "[Deleted user]", + "[Deleted user]" : "[已删除用户]", "No comments yet, start the conversation!" : "还没有评论,开始对话吧!", "More comments …" : "更多评论 ...", "Save" : "保存", @@ -20,18 +20,18 @@ "%1$s commented" : "%1$s 已评论", "{author} commented" : "{author} 评论了", "You commented on %1$s" : "您在 %1$s 的评论", - "You commented on {file}" : "您对 {file} 的注释", + "You commented on {file}" : "您对 {file} 的评论", "%1$s commented on %2$s" : "%1$s 评论了 %2$s", - "{author} commented on {file}" : "{author} 对 {file} 的注释", - "<strong>Comments</strong> for files" : "显示文件的<strong>注释</strong>", - "A (now) deleted user mentioned you in a comment on “%s”" : "一个(正)被删除的用户提醒您注释 “%s”", - "A (now) deleted user mentioned you in a comment on “{file}”" : "一个(正)被删除的用户提醒您注释 “{file}”", - "%1$s mentioned you in a comment on “%2$s”" : "%1$s 提醒您注释 “%2$s”", - "{user} mentioned you in a comment on “{file}”" : "{user} 提醒您注释 “{file}”", + "{author} commented on {file}" : "{author} 对 {file} 的评论", + "<strong>Comments</strong> for files" : "文件的<strong>评论</strong>", + "A (now) deleted user mentioned you in a comment on “%s”" : "一个(已)被删除的用户在 “%s” 的评论中提到了您", + "A (now) deleted user mentioned you in a comment on “{file}”" : "一个(已)被删除的用户在 “{file}” 的评论中提到了您", + "%1$s mentioned you in a comment on “%2$s”" : "%1$s 在 “%2$s” 的评论中提到了您", + "{user} mentioned you in a comment on “{file}”" : "{user} 在 “{file}” 的评论中提到了您", "Type in a new comment..." : "添加新评论...", "No other comments available" : "没有其他评论", "More comments..." : "更多评论...", "{count} unread comments" : "{count} 条未读评论", - "You commented on %2$s" : "你评论了 %2$s" + "You commented on %2$s" : "您评论了 %2$s" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/apps/dav/appinfo/v1/webdav.php b/apps/dav/appinfo/v1/webdav.php index f04bf406334..5ad11ceada8 100644 --- a/apps/dav/appinfo/v1/webdav.php +++ b/apps/dav/appinfo/v1/webdav.php @@ -25,6 +25,7 @@ // no php execution timeout for webdav set_time_limit(0); +ignore_user_abort(true); // Turn off output buffering to prevent memory problems \OC_Util::obEnd(); diff --git a/apps/dav/appinfo/v2/remote.php b/apps/dav/appinfo/v2/remote.php index ab05e376503..b4a6578a41a 100644 --- a/apps/dav/appinfo/v2/remote.php +++ b/apps/dav/appinfo/v2/remote.php @@ -21,6 +21,7 @@ */ // no php execution timeout for webdav set_time_limit(0); +ignore_user_abort(true); // Turn off output buffering to prevent memory problems \OC_Util::obEnd(); diff --git a/apps/dav/l10n/sq.js b/apps/dav/l10n/sq.js new file mode 100644 index 00000000000..e84a2e2354f --- /dev/null +++ b/apps/dav/l10n/sq.js @@ -0,0 +1,40 @@ +OC.L10N.register( + "dav", + { + "Calendar" : "Kalendar", + "{actor} created calendar {calendar}" : "{actor} krijoj kalendarin {calendar}", + "You created calendar {calendar}" : "Ju krijuat kalendarin {calendar}", + "{actor} deleted calendar {calendar}" : "{actor} fshiu kalendarin {calendar}", + "You deleted calendar {calendar}" : "Ju fshit kalendarin {calendar}", + "{actor} updated calendar {calendar}" : "{actor} përditësoi kalendarin {calendar}", + "You updated calendar {calendar}" : "Ju përditësuat kalendarin {calendar}", + "{actor} shared calendar {calendar} with you" : " {actor} ndau kalendarin {calendar} me ju", + "You shared calendar {calendar} with {user}" : "Ju ndat kalendarin {calendar} me {user}", + "{actor} shared calendar {calendar} with {user}" : "{actor} ndau kalendarin {calendar} me {user}", + "{actor} unshared calendar {calendar} from you" : "{actor} ndaloj së ndari kalendarin {calendar} me ju", + "You unshared calendar {calendar} from {user}" : "Ju ndaluat së ndari kalendarin {calendar} me {user}", + "{actor} unshared calendar {calendar} from {user}" : "{actor} ndaloj së ndari kalendarin {calendar} me {user}", + "{actor} unshared calendar {calendar} from themselves" : "{actor} ndaloj së ndari kalendarin {calendar} me veten", + "You shared calendar {calendar} with group {group}" : "Ju ndat kalendarin {calendar} me grupin {group}", + "{actor} shared calendar {calendar} with group {group}" : "{actor} ndau kalendarin {calendar} me grupin {group}", + "You unshared calendar {calendar} from group {group}" : "Ju ndaluat së ndari kalendarin {calendar} me grupin {group}", + "{actor} unshared calendar {calendar} from group {group}" : "{actor} ndaloj së ndari kalendarin {calendar} me grupin {group}", + "{actor} created event {event} in calendar {calendar}" : "{actor} krijoj eventin {event} në kalendarin {calendar}", + "You created event {event} in calendar {calendar}" : "Ju krijuat eventin {event} në kalendarin {calendar}", + "{actor} deleted event {event} from calendar {calendar}" : "{actor} fshiu eventin {event} nga kalendari {calendar}", + "You deleted event {event} from calendar {calendar}" : "Ju fshit eventin {event} nga kalndari {calendar}", + "{actor} updated event {event} in calendar {calendar}" : "{actor} përditsoi eventin {event} në kalndarin {calendar}", + "You updated event {event} in calendar {calendar}" : "Ju përditësuat eventin {event} në kalndarin {calendar}", + "{actor} created todo {todo} in list {calendar}" : "{actor} u krijua todo{todo} në listën {calendar}", + "You created todo {todo} in list {calendar}" : "Ju krijuat todo {todo} në listën {calendar}", + "{actor} deleted todo {todo} from list {calendar}" : "{actor} u fshi todo{ todo} nga lista{calendar}", + "{actor} updated todo {todo} in list {calendar}" : "{actor} u përditësua todo{todo} në listën{calendar}", + "A <strong>calendar</strong> was modified" : "Një <strong>kalendar</strong> u modifikua", + "A calendar <strong>event</strong> was modified" : "Një <strong>event</strong> në kalendar u modifikua", + "Personal" : "Personale", + "Contacts" : "Kontaktet", + "Technical details" : "Detaje teknike", + "Remote Address: %s" : "Adresa remote: %s", + "Request ID: %s" : "ID e kërkesës: %s" +}, +"nplurals=2; plural=(n != 1);"); diff --git a/apps/dav/l10n/sq.json b/apps/dav/l10n/sq.json new file mode 100644 index 00000000000..922e7122069 --- /dev/null +++ b/apps/dav/l10n/sq.json @@ -0,0 +1,38 @@ +{ "translations": { + "Calendar" : "Kalendar", + "{actor} created calendar {calendar}" : "{actor} krijoj kalendarin {calendar}", + "You created calendar {calendar}" : "Ju krijuat kalendarin {calendar}", + "{actor} deleted calendar {calendar}" : "{actor} fshiu kalendarin {calendar}", + "You deleted calendar {calendar}" : "Ju fshit kalendarin {calendar}", + "{actor} updated calendar {calendar}" : "{actor} përditësoi kalendarin {calendar}", + "You updated calendar {calendar}" : "Ju përditësuat kalendarin {calendar}", + "{actor} shared calendar {calendar} with you" : " {actor} ndau kalendarin {calendar} me ju", + "You shared calendar {calendar} with {user}" : "Ju ndat kalendarin {calendar} me {user}", + "{actor} shared calendar {calendar} with {user}" : "{actor} ndau kalendarin {calendar} me {user}", + "{actor} unshared calendar {calendar} from you" : "{actor} ndaloj së ndari kalendarin {calendar} me ju", + "You unshared calendar {calendar} from {user}" : "Ju ndaluat së ndari kalendarin {calendar} me {user}", + "{actor} unshared calendar {calendar} from {user}" : "{actor} ndaloj së ndari kalendarin {calendar} me {user}", + "{actor} unshared calendar {calendar} from themselves" : "{actor} ndaloj së ndari kalendarin {calendar} me veten", + "You shared calendar {calendar} with group {group}" : "Ju ndat kalendarin {calendar} me grupin {group}", + "{actor} shared calendar {calendar} with group {group}" : "{actor} ndau kalendarin {calendar} me grupin {group}", + "You unshared calendar {calendar} from group {group}" : "Ju ndaluat së ndari kalendarin {calendar} me grupin {group}", + "{actor} unshared calendar {calendar} from group {group}" : "{actor} ndaloj së ndari kalendarin {calendar} me grupin {group}", + "{actor} created event {event} in calendar {calendar}" : "{actor} krijoj eventin {event} në kalendarin {calendar}", + "You created event {event} in calendar {calendar}" : "Ju krijuat eventin {event} në kalendarin {calendar}", + "{actor} deleted event {event} from calendar {calendar}" : "{actor} fshiu eventin {event} nga kalendari {calendar}", + "You deleted event {event} from calendar {calendar}" : "Ju fshit eventin {event} nga kalndari {calendar}", + "{actor} updated event {event} in calendar {calendar}" : "{actor} përditsoi eventin {event} në kalndarin {calendar}", + "You updated event {event} in calendar {calendar}" : "Ju përditësuat eventin {event} në kalndarin {calendar}", + "{actor} created todo {todo} in list {calendar}" : "{actor} u krijua todo{todo} në listën {calendar}", + "You created todo {todo} in list {calendar}" : "Ju krijuat todo {todo} në listën {calendar}", + "{actor} deleted todo {todo} from list {calendar}" : "{actor} u fshi todo{ todo} nga lista{calendar}", + "{actor} updated todo {todo} in list {calendar}" : "{actor} u përditësua todo{todo} në listën{calendar}", + "A <strong>calendar</strong> was modified" : "Një <strong>kalendar</strong> u modifikua", + "A calendar <strong>event</strong> was modified" : "Një <strong>event</strong> në kalendar u modifikua", + "Personal" : "Personale", + "Contacts" : "Kontaktet", + "Technical details" : "Detaje teknike", + "Remote Address: %s" : "Adresa remote: %s", + "Request ID: %s" : "ID e kërkesës: %s" +},"pluralForm" :"nplurals=2; plural=(n != 1);" +}
\ No newline at end of file diff --git a/apps/dav/l10n/sv.js b/apps/dav/l10n/sv.js index 28eea0c5867..25cd0d797c8 100644 --- a/apps/dav/l10n/sv.js +++ b/apps/dav/l10n/sv.js @@ -2,7 +2,7 @@ OC.L10N.register( "dav", { "Calendar" : "Kalender", - "Todos" : "Att göra", + "Todos" : "Uppgifter", "{actor} created calendar {calendar}" : "{actor} skapade kalender {calendar}", "You created calendar {calendar}" : "Du skapade kalender {calendar}", "{actor} deleted calendar {calendar}" : "{actor} raderade kalender {calendar}", @@ -26,20 +26,20 @@ OC.L10N.register( "You deleted event {event} from calendar {calendar}" : "Du raderade händelse {event} från kalender {calendar}", "{actor} updated event {event} in calendar {calendar}" : "{actor} uppdaterade händelse {event} i kalender {calendar}", "You updated event {event} in calendar {calendar}" : "Du uppdaterade händelse {event} i kalender {calendar}", - "{actor} created todo {todo} in list {calendar}" : "{actor} skapade att-göra {todo} i listan {calendar}", - "You created todo {todo} in list {calendar}" : "Du skapade att-göra {todo} i listan {calendar}", - "{actor} deleted todo {todo} from list {calendar}" : "{actor} raderade att-göra {todo} från listan {calendar}", - "You deleted todo {todo} from list {calendar}" : "Du raderade att-göra {todo} från listan {calendar}", - "{actor} updated todo {todo} in list {calendar}" : "{actor} uppdaterade att-göra {todo} i listan {calendar}", - "You updated todo {todo} in list {calendar}" : "Du uppdaterade att-göra {todo} i listan {calendar}", - "{actor} solved todo {todo} in list {calendar}" : "{actor} löste att-göra {todo} i listan {calendar}", - "You solved todo {todo} in list {calendar}" : "Du löste att-göra {todo} i listan {calendar}", - "{actor} reopened todo {todo} in list {calendar}" : "{actor} återupptog att-göra {todo} i listan {calendar}", - "You reopened todo {todo} in list {calendar}" : "Du återupptog att-göra {todo} i listan {calendar}", + "{actor} created todo {todo} in list {calendar}" : "{actor} skapade uppgift {todo} i listan {calendar}", + "You created todo {todo} in list {calendar}" : "Du skapade uppgift {todo} i listan {calendar}", + "{actor} deleted todo {todo} from list {calendar}" : "{actor} raderade uppgift {todo} från listan {calendar}", + "You deleted todo {todo} from list {calendar}" : "Du raderade uppgift {todo} från listan {calendar}", + "{actor} updated todo {todo} in list {calendar}" : "{actor} uppdaterade uppgift {todo} i listan {calendar}", + "You updated todo {todo} in list {calendar}" : "Du uppdaterade uppgift {todo} i listan {calendar}", + "{actor} solved todo {todo} in list {calendar}" : "{actor} löste uppgift {todo} i listan {calendar}", + "You solved todo {todo} in list {calendar}" : "Du löste uppgift {todo} i listan {calendar}", + "{actor} reopened todo {todo} in list {calendar}" : "{actor} återupptog uppgift {todo} i listan {calendar}", + "You reopened todo {todo} in list {calendar}" : "Du återupptog uppgift {todo} i listan {calendar}", "A <strong>calendar</strong> was modified" : "En <strong>kalender</strong> modifierades", "A calendar <strong>event</strong> was modified" : "En kalender-<strong>händelse</strong> modifierades", - "A calendar <strong>todo</strong> was modified" : "En kalender <strong>att-göra</strong> modifierades", - "Contact birthdays" : "Kontakters födelsedagar", + "A calendar <strong>todo</strong> was modified" : "En kalender <strong>uppgift</strong> modifierades", + "Contact birthdays" : "Födelsedagar", "Personal" : "Privat", "Contacts" : "Kontakter", "Technical details" : "Tekniska detaljer", diff --git a/apps/dav/l10n/sv.json b/apps/dav/l10n/sv.json index 8dfb9e4e6ba..ba76ca55329 100644 --- a/apps/dav/l10n/sv.json +++ b/apps/dav/l10n/sv.json @@ -1,6 +1,6 @@ { "translations": { "Calendar" : "Kalender", - "Todos" : "Att göra", + "Todos" : "Uppgifter", "{actor} created calendar {calendar}" : "{actor} skapade kalender {calendar}", "You created calendar {calendar}" : "Du skapade kalender {calendar}", "{actor} deleted calendar {calendar}" : "{actor} raderade kalender {calendar}", @@ -24,20 +24,20 @@ "You deleted event {event} from calendar {calendar}" : "Du raderade händelse {event} från kalender {calendar}", "{actor} updated event {event} in calendar {calendar}" : "{actor} uppdaterade händelse {event} i kalender {calendar}", "You updated event {event} in calendar {calendar}" : "Du uppdaterade händelse {event} i kalender {calendar}", - "{actor} created todo {todo} in list {calendar}" : "{actor} skapade att-göra {todo} i listan {calendar}", - "You created todo {todo} in list {calendar}" : "Du skapade att-göra {todo} i listan {calendar}", - "{actor} deleted todo {todo} from list {calendar}" : "{actor} raderade att-göra {todo} från listan {calendar}", - "You deleted todo {todo} from list {calendar}" : "Du raderade att-göra {todo} från listan {calendar}", - "{actor} updated todo {todo} in list {calendar}" : "{actor} uppdaterade att-göra {todo} i listan {calendar}", - "You updated todo {todo} in list {calendar}" : "Du uppdaterade att-göra {todo} i listan {calendar}", - "{actor} solved todo {todo} in list {calendar}" : "{actor} löste att-göra {todo} i listan {calendar}", - "You solved todo {todo} in list {calendar}" : "Du löste att-göra {todo} i listan {calendar}", - "{actor} reopened todo {todo} in list {calendar}" : "{actor} återupptog att-göra {todo} i listan {calendar}", - "You reopened todo {todo} in list {calendar}" : "Du återupptog att-göra {todo} i listan {calendar}", + "{actor} created todo {todo} in list {calendar}" : "{actor} skapade uppgift {todo} i listan {calendar}", + "You created todo {todo} in list {calendar}" : "Du skapade uppgift {todo} i listan {calendar}", + "{actor} deleted todo {todo} from list {calendar}" : "{actor} raderade uppgift {todo} från listan {calendar}", + "You deleted todo {todo} from list {calendar}" : "Du raderade uppgift {todo} från listan {calendar}", + "{actor} updated todo {todo} in list {calendar}" : "{actor} uppdaterade uppgift {todo} i listan {calendar}", + "You updated todo {todo} in list {calendar}" : "Du uppdaterade uppgift {todo} i listan {calendar}", + "{actor} solved todo {todo} in list {calendar}" : "{actor} löste uppgift {todo} i listan {calendar}", + "You solved todo {todo} in list {calendar}" : "Du löste uppgift {todo} i listan {calendar}", + "{actor} reopened todo {todo} in list {calendar}" : "{actor} återupptog uppgift {todo} i listan {calendar}", + "You reopened todo {todo} in list {calendar}" : "Du återupptog uppgift {todo} i listan {calendar}", "A <strong>calendar</strong> was modified" : "En <strong>kalender</strong> modifierades", "A calendar <strong>event</strong> was modified" : "En kalender-<strong>händelse</strong> modifierades", - "A calendar <strong>todo</strong> was modified" : "En kalender <strong>att-göra</strong> modifierades", - "Contact birthdays" : "Kontakters födelsedagar", + "A calendar <strong>todo</strong> was modified" : "En kalender <strong>uppgift</strong> modifierades", + "Contact birthdays" : "Födelsedagar", "Personal" : "Privat", "Contacts" : "Kontakter", "Technical details" : "Tekniska detaljer", diff --git a/apps/encryption/css/settings-personal.css b/apps/encryption/css/settings-personal.css index 8eb5bedcb06..4bab1a8d46b 100644 --- a/apps/encryption/css/settings-personal.css +++ b/apps/encryption/css/settings-personal.css @@ -8,3 +8,8 @@ , #recoveryEnabledSuccess { display: none; } + +/* icons for sidebar */ +.nav-icon-basic-encryption-module { + background-image: url('../img/app.svg?v=1'); +}
\ No newline at end of file diff --git a/apps/encryption/l10n/fr.js b/apps/encryption/l10n/fr.js index 77a433ef58d..14b693baa28 100644 --- a/apps/encryption/l10n/fr.js +++ b/apps/encryption/l10n/fr.js @@ -12,7 +12,7 @@ OC.L10N.register( "Please provide the old recovery password" : "Veuillez entrer l'ancien mot de passe de récupération", "Please provide a new recovery password" : "Veuillez entrer un nouveau mot de passe de récupération", "Please repeat the new recovery password" : "Veuillez répéter le nouveau mot de passe de récupération", - "Password successfully changed." : "Mot de passe changé avec succès.", + "Password successfully changed." : "Mot de passe modifié avec succès.", "Could not change the password. Maybe the old password was not correct." : "Erreur lors du changement de mot de passe. L'ancien mot de passe est peut-être incorrect.", "Recovery Key disabled" : "Clé de récupération désactivée", "Recovery Key enabled" : "Clef de récupération activée", diff --git a/apps/encryption/l10n/fr.json b/apps/encryption/l10n/fr.json index 2129bd43828..74c0b7492a8 100644 --- a/apps/encryption/l10n/fr.json +++ b/apps/encryption/l10n/fr.json @@ -10,7 +10,7 @@ "Please provide the old recovery password" : "Veuillez entrer l'ancien mot de passe de récupération", "Please provide a new recovery password" : "Veuillez entrer un nouveau mot de passe de récupération", "Please repeat the new recovery password" : "Veuillez répéter le nouveau mot de passe de récupération", - "Password successfully changed." : "Mot de passe changé avec succès.", + "Password successfully changed." : "Mot de passe modifié avec succès.", "Could not change the password. Maybe the old password was not correct." : "Erreur lors du changement de mot de passe. L'ancien mot de passe est peut-être incorrect.", "Recovery Key disabled" : "Clé de récupération désactivée", "Recovery Key enabled" : "Clef de récupération activée", diff --git a/apps/encryption/l10n/id.js b/apps/encryption/l10n/id.js index c48146d1df8..41a6cfd74a7 100644 --- a/apps/encryption/l10n/id.js +++ b/apps/encryption/l10n/id.js @@ -34,6 +34,7 @@ OC.L10N.register( "The share will expire on %s." : "Pembagian akan berakhir pada %s.", "Cheers!" : "Horee!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Hai,<br><br>admin mengaktifkan server-side-encryption. Berkas-berkas Anda dienkripsi menggunakan sandi <strong>%s</strong>.<br><br>Silakan masuk di antarmuka web, pergi ke bagian 'modul enkripsi dasar' pada pengaturan pribadi Anda dan perbarui sandi enkripsi Anda dengan memasukkan sandi ini kedalam kolom 'sandi masuk yang lama' dan sandi masuk yang baru.<br><br>", + "Default encryption module" : "Modul bawaan enkripsi", "Encrypt the home storage" : "Enkripsi penyimpanan rumah", "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Mengaktifkan opsi ini akan mengenkripsi semua berkas yang disimpan pada penyimpanan utama, jika tidak diaktifkan maka hanya berkas pada penyimpanan eksternal saja yang akan dienkripsi.", "Enable recovery key" : "Aktifkan kunci pemulihan", diff --git a/apps/encryption/l10n/id.json b/apps/encryption/l10n/id.json index 536f4616ddc..e653db4f950 100644 --- a/apps/encryption/l10n/id.json +++ b/apps/encryption/l10n/id.json @@ -32,6 +32,7 @@ "The share will expire on %s." : "Pembagian akan berakhir pada %s.", "Cheers!" : "Horee!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Hai,<br><br>admin mengaktifkan server-side-encryption. Berkas-berkas Anda dienkripsi menggunakan sandi <strong>%s</strong>.<br><br>Silakan masuk di antarmuka web, pergi ke bagian 'modul enkripsi dasar' pada pengaturan pribadi Anda dan perbarui sandi enkripsi Anda dengan memasukkan sandi ini kedalam kolom 'sandi masuk yang lama' dan sandi masuk yang baru.<br><br>", + "Default encryption module" : "Modul bawaan enkripsi", "Encrypt the home storage" : "Enkripsi penyimpanan rumah", "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Mengaktifkan opsi ini akan mengenkripsi semua berkas yang disimpan pada penyimpanan utama, jika tidak diaktifkan maka hanya berkas pada penyimpanan eksternal saja yang akan dienkripsi.", "Enable recovery key" : "Aktifkan kunci pemulihan", diff --git a/apps/encryption/l10n/sv.js b/apps/encryption/l10n/sv.js index 0b8530bf006..2a5893af8bf 100644 --- a/apps/encryption/l10n/sv.js +++ b/apps/encryption/l10n/sv.js @@ -34,7 +34,7 @@ OC.L10N.register( "The share will expire on %s." : "Utdelningen kommer att upphöra %s.", "Cheers!" : "Ha de fint!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Hallå där, <br> Administratören aktiverade serverkryptering. Alla dina filer har blivit krypterade med lösenordet: <strong>%s</ strong>. <br> Gå till i din profil för att ändra krypteringslösenordet till ditt egna lösenord. Ange lösenordet ovan som \"Gammalt lösenord\" och ange sedan ditt egna lösenord.<br>", - "Default encryption module" : "Standard krypteringsfunktion", + "Default encryption module" : "Krypteringsfunktion", "Encrypt the home storage" : "Kryptera alla filer i molnet", "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Aktivering av det här alternativet krypterar alla filer som är lagrade på huvudlagringsplatsen, annars kommer bara filer på extern lagringsplats att krypteras", "Enable recovery key" : "Aktivera återställningsnyckel", @@ -47,7 +47,7 @@ OC.L10N.register( "New recovery key password" : "Nytt lösenord", "Repeat new recovery key password" : "Repetera lösenord", "Change Password" : "Byt lösenord", - "Basic encryption module" : "Krypteringsmodul", + "Basic encryption module" : "Kryptering", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Krypteringsprogrammet är aktiverat men dina nycklar är inte initierade. Vänligen logga ut och in igen", "Your private key password no longer matches your log-in password." : "Ditt lösenord för din privata nyckel matchar inte längre ditt inloggningslösenord.", "Set your old private key password to your current log-in password:" : "Sätt ditt gamla privatnyckellösenord till ditt aktuella inloggningslösenord:", diff --git a/apps/encryption/l10n/sv.json b/apps/encryption/l10n/sv.json index 976336ae068..f0e64f2c807 100644 --- a/apps/encryption/l10n/sv.json +++ b/apps/encryption/l10n/sv.json @@ -32,7 +32,7 @@ "The share will expire on %s." : "Utdelningen kommer att upphöra %s.", "Cheers!" : "Ha de fint!", "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Hallå där, <br> Administratören aktiverade serverkryptering. Alla dina filer har blivit krypterade med lösenordet: <strong>%s</ strong>. <br> Gå till i din profil för att ändra krypteringslösenordet till ditt egna lösenord. Ange lösenordet ovan som \"Gammalt lösenord\" och ange sedan ditt egna lösenord.<br>", - "Default encryption module" : "Standard krypteringsfunktion", + "Default encryption module" : "Krypteringsfunktion", "Encrypt the home storage" : "Kryptera alla filer i molnet", "Enabling this option encrypts all files stored on the main storage, otherwise only files on external storage will be encrypted" : "Aktivering av det här alternativet krypterar alla filer som är lagrade på huvudlagringsplatsen, annars kommer bara filer på extern lagringsplats att krypteras", "Enable recovery key" : "Aktivera återställningsnyckel", @@ -45,7 +45,7 @@ "New recovery key password" : "Nytt lösenord", "Repeat new recovery key password" : "Repetera lösenord", "Change Password" : "Byt lösenord", - "Basic encryption module" : "Krypteringsmodul", + "Basic encryption module" : "Kryptering", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Krypteringsprogrammet är aktiverat men dina nycklar är inte initierade. Vänligen logga ut och in igen", "Your private key password no longer matches your log-in password." : "Ditt lösenord för din privata nyckel matchar inte längre ditt inloggningslösenord.", "Set your old private key password to your current log-in password:" : "Sätt ditt gamla privatnyckellösenord till ditt aktuella inloggningslösenord:", diff --git a/apps/federatedfilesharing/l10n/fr.js b/apps/federatedfilesharing/l10n/fr.js index 4a1d7767965..092b87fb9e8 100644 --- a/apps/federatedfilesharing/l10n/fr.js +++ b/apps/federatedfilesharing/l10n/fr.js @@ -29,7 +29,7 @@ OC.L10N.register( "File is already shared with %s" : "Le fichier est déjà partagé avec %s", "Sharing %s failed, could not find %s, maybe the server is currently unreachable or uses a self-signed certificate." : "Le partage de %s a échoué, impossible de trouver %s, le serveur est peut-être momentanément injoignable ou utilise un certificat auto-signé.", "Could not find share" : "Impossible de trouver le partage", - "You received \"%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "Vous avez reçu \"%3$s\" en tant que partage distant de %1$s (de la part de %2$s)", + "You received \"%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "Vous avez reçu \"%3$s\" en tant que partage distant de %1$s (de la part de %2$s)", "You received {share} as a remote share from {user} (on behalf of {behalf})" : "Vous avez reçu {share} comme partage distant de la part de {user} (de la part de {behalf})", "You received \"%3$s\" as a remote share from %1$s" : "Vous avez reçu \"%3$s\" comme partage distant de %1$s", "You received {share} as a remote share from {user}" : "Vous avez reçu {share} comme partage distant de la part de {user}", diff --git a/apps/federatedfilesharing/l10n/fr.json b/apps/federatedfilesharing/l10n/fr.json index 670a3bd043c..f90620b940d 100644 --- a/apps/federatedfilesharing/l10n/fr.json +++ b/apps/federatedfilesharing/l10n/fr.json @@ -27,7 +27,7 @@ "File is already shared with %s" : "Le fichier est déjà partagé avec %s", "Sharing %s failed, could not find %s, maybe the server is currently unreachable or uses a self-signed certificate." : "Le partage de %s a échoué, impossible de trouver %s, le serveur est peut-être momentanément injoignable ou utilise un certificat auto-signé.", "Could not find share" : "Impossible de trouver le partage", - "You received \"%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "Vous avez reçu \"%3$s\" en tant que partage distant de %1$s (de la part de %2$s)", + "You received \"%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "Vous avez reçu \"%3$s\" en tant que partage distant de %1$s (de la part de %2$s)", "You received {share} as a remote share from {user} (on behalf of {behalf})" : "Vous avez reçu {share} comme partage distant de la part de {user} (de la part de {behalf})", "You received \"%3$s\" as a remote share from %1$s" : "Vous avez reçu \"%3$s\" comme partage distant de %1$s", "You received {share} as a remote share from {user}" : "Vous avez reçu {share} comme partage distant de la part de {user}", diff --git a/apps/federatedfilesharing/l10n/sq.js b/apps/federatedfilesharing/l10n/sq.js index ae500204ce4..4e55e171b81 100644 --- a/apps/federatedfilesharing/l10n/sq.js +++ b/apps/federatedfilesharing/l10n/sq.js @@ -2,13 +2,26 @@ OC.L10N.register( "federatedfilesharing", { "Federated sharing" : "Ndarje e federuar", + "Do you want to add the remote share {name} from {owner}@{remote}?" : "Doni që të shtoni ndarjen në remote {name} nga {owner}@{remote}?", + "Remote share" : "Ndarje në largësi", + "Remote share password" : "Fjalëkalim ndarjeje të largët", + "Cancel" : "Anulo", + "Copy" : "Kopjo", + "Copied!" : "U kopjua!", + "Not supported!" : "Nuk mbështetet!", + "Press ⌘-C to copy." : "Shtyp ⌘-C për të kopjuar.", + "Press Ctrl-C to copy." : "Shtypni Ctrl-C për të kopjuar", "Invalid Federated Cloud ID" : "ID Federated Cloud e pavlefshme", + "Server to server sharing is not enabled on this server" : "Shpërndarja server në server nuk është e mundësuar në këtë server", + "Storage not valid" : "memorja nuk është e vlefshme", + "Couldn't add remote share" : "Nuk mund të shtohet ndarja në largësi", "Sharing %s failed, because this item is already shared with %s" : "Ndarja për %s dështoi, ngaqë ky objekt është ndarë një herë me %s", "Not allowed to create a federated share with the same user" : "S’i lejohet të krijojë një ndarje të federuar me të njëjtin përdorues", - "File is already shared with %s" : "Kartelë e ndarë tashmë me %s", - "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Ndarja për %s dështoi, s’u gjet dot %s, ndoshta shërbyesi është hëpërhë jashtë pune.", - "You received \"/%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "\"/%3$s\" e morët si një ndarje të largët prej %1$s (në emër të %2$s)", - "You received \"/%3$s\" as a remote share from %1$s" : "\"/%3$s\" e morët si një ndarje të largët prej %1$s", + "File is already shared with %s" : "Skedari është ndarë tashmë me %s", + "Sharing %s failed, could not find %s, maybe the server is currently unreachable or uses a self-signed certificate." : "Ndarja e %s dështoi, nuk mund të gjendet %s, ndoshta serveri është për momentin i paaksesueshëm ose përdor një çertifikatë të vetë-nënshkruar", + "Could not find share" : "Nuk mund të gjenim ndarjen", + "You received {share} as a remote share from {user} (on behalf of {behalf})" : "Ju ", + "You received \"%3$s\" as a remote share from %1$s" : "Ju pranuat \"%3$s\" si një shpërndarje në distancë nga %1$s", "Accept" : "Pranoje", "Decline" : "Hidhe poshtë", "Share with me through my #Nextcloud Federated Cloud ID, see %s" : "Ndani me mua përmes ID-së time për #Nextcloud Federated Cloud, shihni %s", @@ -22,6 +35,9 @@ OC.L10N.register( "Share it:" : "Ndajeni:", "Add to your website" : "Shtojeni te sajti juaj", "Share with me via Nextcloud" : "Ndani me mua përmes Nextcloud-it", - "HTML Code:" : "Kod HTML:" + "HTML Code:" : "Kod HTML:", + "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Ndarja për %s dështoi, s’u gjet dot %s, ndoshta shërbyesi është hëpërhë jashtë pune.", + "You received \"/%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "\"/%3$s\" e morët si një ndarje të largët prej %1$s (në emër të %2$s)", + "You received \"/%3$s\" as a remote share from %1$s" : "\"/%3$s\" e morët si një ndarje të largët prej %1$s" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/federatedfilesharing/l10n/sq.json b/apps/federatedfilesharing/l10n/sq.json index 57961c2c2ae..07858aa6434 100644 --- a/apps/federatedfilesharing/l10n/sq.json +++ b/apps/federatedfilesharing/l10n/sq.json @@ -1,12 +1,25 @@ { "translations": { "Federated sharing" : "Ndarje e federuar", + "Do you want to add the remote share {name} from {owner}@{remote}?" : "Doni që të shtoni ndarjen në remote {name} nga {owner}@{remote}?", + "Remote share" : "Ndarje në largësi", + "Remote share password" : "Fjalëkalim ndarjeje të largët", + "Cancel" : "Anulo", + "Copy" : "Kopjo", + "Copied!" : "U kopjua!", + "Not supported!" : "Nuk mbështetet!", + "Press ⌘-C to copy." : "Shtyp ⌘-C për të kopjuar.", + "Press Ctrl-C to copy." : "Shtypni Ctrl-C për të kopjuar", "Invalid Federated Cloud ID" : "ID Federated Cloud e pavlefshme", + "Server to server sharing is not enabled on this server" : "Shpërndarja server në server nuk është e mundësuar në këtë server", + "Storage not valid" : "memorja nuk është e vlefshme", + "Couldn't add remote share" : "Nuk mund të shtohet ndarja në largësi", "Sharing %s failed, because this item is already shared with %s" : "Ndarja për %s dështoi, ngaqë ky objekt është ndarë një herë me %s", "Not allowed to create a federated share with the same user" : "S’i lejohet të krijojë një ndarje të federuar me të njëjtin përdorues", - "File is already shared with %s" : "Kartelë e ndarë tashmë me %s", - "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Ndarja për %s dështoi, s’u gjet dot %s, ndoshta shërbyesi është hëpërhë jashtë pune.", - "You received \"/%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "\"/%3$s\" e morët si një ndarje të largët prej %1$s (në emër të %2$s)", - "You received \"/%3$s\" as a remote share from %1$s" : "\"/%3$s\" e morët si një ndarje të largët prej %1$s", + "File is already shared with %s" : "Skedari është ndarë tashmë me %s", + "Sharing %s failed, could not find %s, maybe the server is currently unreachable or uses a self-signed certificate." : "Ndarja e %s dështoi, nuk mund të gjendet %s, ndoshta serveri është për momentin i paaksesueshëm ose përdor një çertifikatë të vetë-nënshkruar", + "Could not find share" : "Nuk mund të gjenim ndarjen", + "You received {share} as a remote share from {user} (on behalf of {behalf})" : "Ju ", + "You received \"%3$s\" as a remote share from %1$s" : "Ju pranuat \"%3$s\" si një shpërndarje në distancë nga %1$s", "Accept" : "Pranoje", "Decline" : "Hidhe poshtë", "Share with me through my #Nextcloud Federated Cloud ID, see %s" : "Ndani me mua përmes ID-së time për #Nextcloud Federated Cloud, shihni %s", @@ -20,6 +33,9 @@ "Share it:" : "Ndajeni:", "Add to your website" : "Shtojeni te sajti juaj", "Share with me via Nextcloud" : "Ndani me mua përmes Nextcloud-it", - "HTML Code:" : "Kod HTML:" + "HTML Code:" : "Kod HTML:", + "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Ndarja për %s dështoi, s’u gjet dot %s, ndoshta shërbyesi është hëpërhë jashtë pune.", + "You received \"/%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "\"/%3$s\" e morët si një ndarje të largët prej %1$s (në emër të %2$s)", + "You received \"/%3$s\" as a remote share from %1$s" : "\"/%3$s\" e morët si një ndarje të largët prej %1$s" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php b/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php index 55329338a92..3c399268124 100644 --- a/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php +++ b/apps/federatedfilesharing/lib/Controller/MountPublicLinkController.php @@ -25,18 +25,24 @@ namespace OCA\FederatedFileSharing\Controller; +use OC\Files\Filesystem; use OC\HintException; +use OC\Share\Helper; use OCA\FederatedFileSharing\AddressHandler; +use OCA\FederatedFileSharing\DiscoveryManager; use OCA\FederatedFileSharing\FederatedShareProvider; +use OCA\Files_Sharing\External\Manager; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; +use OCP\Files\StorageInvalidException; use OCP\Http\Client\IClientService; use OCP\IL10N; use OCP\IRequest; use OCP\ISession; use OCP\IUserSession; use OCP\Share\IManager; +use OCP\Util; /** * Class MountPublicLinkController @@ -107,6 +113,7 @@ class MountPublicLinkController extends Controller { * * @NoCSRFRequired * @PublicPage + * @BruteForceProtection publicLink2FederatedShare * * @param string $shareWith * @param string $token @@ -226,22 +233,22 @@ class MountPublicLinkController extends Controller { private function legacyMountPublicLink($token, $remote, $password, $name, $owner, $ownerDisplayName) { // Check for invalid name - if (!\OCP\Util::isValidFileName($name)) { + if (!Util::isValidFileName($name)) { return new JSONResponse(['message' => $this->l->t('The mountpoint name contains invalid characters.')], Http::STATUS_BAD_REQUEST); } $currentUser = $this->userSession->getUser()->getUID(); $currentServer = $this->addressHandler->generateRemoteURL(); - if (\OC\Share\Helper::isSameUserOnSameServer($owner, $remote, $currentUser, $currentServer)) { + if (Helper::isSameUserOnSameServer($owner, $remote, $currentUser, $currentServer)) { return new JSONResponse(['message' => $this->l->t('Not allowed to create a federated share with the owner.')], Http::STATUS_BAD_REQUEST); } - $discoveryManager = new \OCA\FederatedFileSharing\DiscoveryManager( + $discoveryManager = new DiscoveryManager( \OC::$server->getMemCacheFactory(), \OC::$server->getHTTPClientService() ); - $externalManager = new \OCA\Files_Sharing\External\Manager( + $externalManager = new Manager( \OC::$server->getDatabaseConnection(), - \OC\Files\Filesystem::getMountManager(), - \OC\Files\Filesystem::getLoader(), + Filesystem::getMountManager(), + Filesystem::getLoader(), \OC::$server->getHTTPClientService(), \OC::$server->getNotificationManager(), $discoveryManager, @@ -249,7 +256,8 @@ class MountPublicLinkController extends Controller { ); // check for ssl cert - if (substr($remote, 0, 5) === 'https') { + + if (strpos($remote, 'https') === 0) { try { $client = $this->clientService->newClient(); $client->get($remote, [ @@ -268,19 +276,19 @@ class MountPublicLinkController extends Controller { try { // check if storage exists $storage->checkStorageAvailability(); - } catch (\OCP\Files\StorageInvalidException $e) { + } catch (StorageInvalidException $e) { // note: checkStorageAvailability will already remove the invalid share - \OCP\Util::writeLog( + Util::writeLog( 'federatedfilesharing', 'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(), - \OCP\Util::DEBUG + Util::DEBUG ); return new JSONResponse(['message' => $this->l->t('Could not authenticate to remote share, password might be wrong')], Http::STATUS_BAD_REQUEST); } catch (\Exception $e) { - \OCP\Util::writeLog( + Util::writeLog( 'federatedfilesharing', 'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(), - \OCP\Util::DEBUG + Util::DEBUG ); $externalManager->removeShare($mount->getMountPoint()); return new JSONResponse(['message' => $this->l->t('Storage not valid')], Http::STATUS_BAD_REQUEST); @@ -295,27 +303,27 @@ class MountPublicLinkController extends Controller { 'legacyMount' => '1' ] ); - } catch (\OCP\Files\StorageInvalidException $e) { - \OCP\Util::writeLog( + } catch (StorageInvalidException $e) { + Util::writeLog( 'federatedfilesharing', 'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(), - \OCP\Util::DEBUG + Util::DEBUG ); return new JSONResponse(['message' => $this->l->t('Storage not valid')], Http::STATUS_BAD_REQUEST); } catch (\Exception $e) { - \OCP\Util::writeLog( + Util::writeLog( 'federatedfilesharing', 'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(), - \OCP\Util::DEBUG + Util::DEBUG ); return new JSONResponse(['message' => $this->l->t('Couldn\'t add remote share')], Http::STATUS_BAD_REQUEST); } } else { $externalManager->removeShare($mount->getMountPoint()); - \OCP\Util::writeLog( + Util::writeLog( 'federatedfilesharing', 'Couldn\'t add remote share', - \OCP\Util::DEBUG + Util::DEBUG ); return new JSONResponse(['message' => $this->l->t('Couldn\'t add remote share')], Http::STATUS_BAD_REQUEST); } diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 7956ef5c6ae..05b8e58cbe4 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -768,46 +768,20 @@ html.ie8 #controls .button.new { } .newFileMenu { - width: 200px; - margin-left: -56px; - margin-top: 25px; + font-weight: 300; + top: 100%; + margin-top: 4px; + min-width: 100px; + margin-left: 7px; z-index: 1001; } -.newFileMenu .menuitem { - white-space: nowrap; - overflow: hidden; -} -.newFileMenu.popovermenu a.menuitem, -.newFileMenu.popovermenu label.menuitem, -.newFileMenu.popovermenu .menuitem { - padding: 0; - margin: 0; -} - -.newFileMenu.popovermenu a.menuitem.active { - opacity: 1; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; - filter: alpha(opacity=100); -} - -.newFileMenu.bubble:after { - left: 75px; - right: auto; -} -.newFileMenu.bubble:before { - left: 75px; - right: auto; -} - .newFileMenu .filenameform { display: inline-block; } .newFileMenu .filenameform input { - width: 100%; - box-sizing: border-box; - margin: -2px 0; + margin: 2px 0; } #fileList .popovermenu .action { @@ -835,6 +809,9 @@ html.ie8 #controls .button.new { height: 15px; } +.app-files .actions .button.new { + position: relative; +} .app-files .actions .button.new .icon { margin-bottom: 2px; } diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index cd0eb390ee3..3a59da53517 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -1180,7 +1180,7 @@ var innernameSpan = $('<span></span>').addClass('innernametext').text(basename); if (path && path !== '/') { - var conflictingItems = this.$fileList.find('tr[data-file="' + name.replace( /(:|\.|\[|\]|,|=)/g, "\\$1") + '"]'); + var conflictingItems = this.$fileList.find('tr[data-file="' + this._jqSelEscape(name) + '"]'); if (conflictingItems.length !== 0) { if (conflictingItems.length === 1) { // Update the path on the first conflicting item @@ -1266,6 +1266,14 @@ return tr; }, + /* escape a selector expression for jQuery */ + _jqSelEscape: function (expression) { + if (expression) { + return expression.replace(/[!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~]/g, '\\$&'); + } + return null; + }, + /** * Adds an entry to the files array and also into the DOM * in a sorted manner. @@ -2470,6 +2478,11 @@ if (!_.isArray(file)) { file = [file]; } + if (file.length === 1) { + _.defer(function() { + this.showDetailsView(file[0]); + }.bind(this)); + } this.highlightFiles(file, function($tr) { $tr.addClass('searchresult'); $tr.one('hover', function() { @@ -2943,7 +2956,7 @@ this._newFileMenu = new OCA.Files.NewFileMenu({ fileList: this }); - $('body').append(this._newFileMenu.$el); + $('.actions').append(this._newFileMenu.$el); } this._newFileMenu.showAt($target); diff --git a/apps/files/js/newfilemenu.js b/apps/files/js/newfilemenu.js index 75c4cdcc0ba..e4023c62342 100644 --- a/apps/files/js/newfilemenu.js +++ b/apps/files/js/newfilemenu.js @@ -38,7 +38,8 @@ */ var NewFileMenu = OC.Backbone.View.extend({ tagName: 'div', - className: 'newFileMenu popovermenu bubble hidden open menu', + // Menu is opened by default because it's rendered on "add-button" click + className: 'newFileMenu popovermenu bubble menu open menu-left', events: { 'click .menuitem': '_onClickAction' @@ -235,13 +236,6 @@ */ showAt: function($target) { this.render(); - var targetOffset = $target.offset(); - this.$el.css({ - left: targetOffset.left, - top: targetOffset.top + $target.height() - }); - this.$el.removeClass('hidden'); - OC.showMenu(null, this.$el); } }); diff --git a/apps/files/l10n/de.js b/apps/files/l10n/de.js index afd1f8142c2..0127235b605 100644 --- a/apps/files/l10n/de.js +++ b/apps/files/l10n/de.js @@ -76,7 +76,7 @@ OC.L10N.register( "Added to favorites" : "Zu den Favoriten hinzugefügt", "Removed from favorites" : "Aus den Favoriten entfernt", "You added {file} to your favorites" : "Du hast {file} zu deinen Favoriten hinzugefügt", - "You removed {file} from your favorites" : "Du hast {file} aus deinen Favoriten hentfernt", + "You removed {file} from your favorites" : "Du hast {file} aus deinen Favoriten entfernt", "File changes" : "Dateiänderungen", "Created by {user}" : "Erstellt durch {user}", "Changed by {user}" : "Geändert durch {user}", @@ -98,7 +98,7 @@ OC.L10N.register( "You moved {oldfile} to {newfile}" : "Du hast {oldfile} nach {newfile} verschoben", "{user} moved {oldfile} to {newfile}" : "{user} hat {oldfile} nach {newfile} verschoben", "A file has been added to or removed from your <strong>favorites</strong>" : "Eine Datei wurde deinen <strong>Favoriten</strong> hinzugefügt oder daraus entfernt", - "A file or folder has been <strong>changed</strong> or <strong>renamed</strong>" : "Eine Datei oder Ordner wurden <strong>geändert</strong> oder <strong>umbenannt</strong>", + "A file or folder has been <strong>changed</strong> or <strong>renamed</strong>" : "Eine Datei / Ordner wurde <strong>geändert</strong> oder <strong>umbenannt</strong>", "A new file or folder has been <strong>created</strong>" : "Eine neue Datei oder ein neuer Ordner wurde <strong>erstellt</strong>", "A new file or folder has been <strong>deleted</strong>" : "Neue Datei oder Verzeichnis wurde <strong>gelöscht</strong>", "Limit notifications about creation and changes to your <strong>favorite files</strong> <em>(Stream only)</em>" : "Benachrichtigungen über Neues und Änderungen auf deine <strong>favorisierten Dateien</strong> beschränken <em>(nur im Stream)</em>", diff --git a/apps/files/l10n/de.json b/apps/files/l10n/de.json index 30a2730b47c..d64a9eb0850 100644 --- a/apps/files/l10n/de.json +++ b/apps/files/l10n/de.json @@ -74,7 +74,7 @@ "Added to favorites" : "Zu den Favoriten hinzugefügt", "Removed from favorites" : "Aus den Favoriten entfernt", "You added {file} to your favorites" : "Du hast {file} zu deinen Favoriten hinzugefügt", - "You removed {file} from your favorites" : "Du hast {file} aus deinen Favoriten hentfernt", + "You removed {file} from your favorites" : "Du hast {file} aus deinen Favoriten entfernt", "File changes" : "Dateiänderungen", "Created by {user}" : "Erstellt durch {user}", "Changed by {user}" : "Geändert durch {user}", @@ -96,7 +96,7 @@ "You moved {oldfile} to {newfile}" : "Du hast {oldfile} nach {newfile} verschoben", "{user} moved {oldfile} to {newfile}" : "{user} hat {oldfile} nach {newfile} verschoben", "A file has been added to or removed from your <strong>favorites</strong>" : "Eine Datei wurde deinen <strong>Favoriten</strong> hinzugefügt oder daraus entfernt", - "A file or folder has been <strong>changed</strong> or <strong>renamed</strong>" : "Eine Datei oder Ordner wurden <strong>geändert</strong> oder <strong>umbenannt</strong>", + "A file or folder has been <strong>changed</strong> or <strong>renamed</strong>" : "Eine Datei / Ordner wurde <strong>geändert</strong> oder <strong>umbenannt</strong>", "A new file or folder has been <strong>created</strong>" : "Eine neue Datei oder ein neuer Ordner wurde <strong>erstellt</strong>", "A new file or folder has been <strong>deleted</strong>" : "Neue Datei oder Verzeichnis wurde <strong>gelöscht</strong>", "Limit notifications about creation and changes to your <strong>favorite files</strong> <em>(Stream only)</em>" : "Benachrichtigungen über Neues und Änderungen auf deine <strong>favorisierten Dateien</strong> beschränken <em>(nur im Stream)</em>", diff --git a/apps/files/l10n/de_DE.js b/apps/files/l10n/de_DE.js index 9ef2aed2802..17961360c98 100644 --- a/apps/files/l10n/de_DE.js +++ b/apps/files/l10n/de_DE.js @@ -76,7 +76,7 @@ OC.L10N.register( "Added to favorites" : "Zu den Favoriten hinzugefügt", "Removed from favorites" : "Aus den Favoriten entfernt", "You added {file} to your favorites" : "Sie haben {file} zu Ihren Favoriten hinzugefügt", - "You removed {file} from your favorites" : "Sie haben {file} aus Ihren Favoriten hentfernt", + "You removed {file} from your favorites" : "Sie haben {file} aus Ihren Favoriten entfernt", "File changes" : "Datei geändert", "Created by {user}" : "Erstellt durch {user}", "Changed by {user}" : "Geändert durch {user}", diff --git a/apps/files/l10n/de_DE.json b/apps/files/l10n/de_DE.json index 3466d7ebd9a..926434c523c 100644 --- a/apps/files/l10n/de_DE.json +++ b/apps/files/l10n/de_DE.json @@ -74,7 +74,7 @@ "Added to favorites" : "Zu den Favoriten hinzugefügt", "Removed from favorites" : "Aus den Favoriten entfernt", "You added {file} to your favorites" : "Sie haben {file} zu Ihren Favoriten hinzugefügt", - "You removed {file} from your favorites" : "Sie haben {file} aus Ihren Favoriten hentfernt", + "You removed {file} from your favorites" : "Sie haben {file} aus Ihren Favoriten entfernt", "File changes" : "Datei geändert", "Created by {user}" : "Erstellt durch {user}", "Changed by {user}" : "Geändert durch {user}", diff --git a/apps/files/l10n/fr.js b/apps/files/l10n/fr.js index dcd0928ca25..8d110fe5f3f 100644 --- a/apps/files/l10n/fr.js +++ b/apps/files/l10n/fr.js @@ -1,24 +1,24 @@ OC.L10N.register( "files", { - "Storage is temporarily not available" : "Le support de stockage est temporairement non disponible", - "Storage invalid" : "Support de stockage non valable", + "Storage is temporarily not available" : "Le support de stockage est temporairement indisponible", + "Storage invalid" : "Support de stockage invalide", "Unknown error" : "Erreur inconnue ", "Files" : "Fichiers", "All files" : "Tous les fichiers", "Recent" : "Récent", - "File could not be found" : "Ce fichier n'a pu être trouvé.", + "File could not be found" : "Fichier introuvable", "Home" : "Mes fichiers", "Close" : "Fermer", "Favorites" : "Favoris", "Could not create folder \"{dir}\"" : "Impossible de créer le dossier \"{dir}\"", - "Upload cancelled." : "Envoi annulé.", + "Upload cancelled." : "Téléversement annulé.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Impossible d'envoyer {filename} car il s'agit d'un répertoire ou d'un fichier de taille nulle", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Espace libre insuffisant : vous tentez d'envoyer {size1} mais seulement {size2} sont disponibles", "Target folder \"{dir}\" does not exist any more" : "Le dossier cible « {dir} » n'existe plus", - "Not enough free space" : "Pas assez d'espace disponible", + "Not enough free space" : "Espace disponible insuffisant", "Uploading..." : "Téléversement en cours…", - "..." : "...", + "..." : "…", "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize} sur {totalSize} ({bitrate})", "Actions" : "Actions", "Download" : "Télécharger", @@ -34,7 +34,7 @@ OC.L10N.register( "Pending" : "En attente", "Unable to determine date" : "Impossible de déterminer la date", "This operation is forbidden" : "Cette opération est interdite", - "This directory is unavailable, please check the logs or contact the administrator" : "Ce répertoire n'est pas disponible. Consultez les logs ou contactez votre administrateur", + "This directory is unavailable, please check the logs or contact the administrator" : "Ce dossier n'est pas disponible. Consultez les logs ou contactez votre administrateur", "Could not move \"{file}\", target exists" : "Impossible de déplacer \"{file}\", la cible existe", "Could not move \"{file}\"" : "Impossible de déplacer \"{file}\"", "{newName} already exists" : "{newName} existe déjà", @@ -52,18 +52,18 @@ OC.L10N.register( "_%n folder_::_%n folders_" : ["%n dossier","%n dossiers"], "_%n file_::_%n files_" : ["%n fichier","%n fichiers"], "{dirs} and {files}" : "{dirs} et {files}", - "_including %n hidden_::_including %n hidden_" : ["inclus %n caché","inclus %n cachés"], - "You don’t have permission to upload or create files here" : "Vous n'avez pas la permission d'ajouter des fichiers ici", + "_including %n hidden_::_including %n hidden_" : ["inclus %n masqué","inclus %n masqués"], + "You don’t have permission to upload or create files here" : "Vous n'avez pas la permission d'envoyer ou de créer des fichiers ici", "_Uploading %n file_::_Uploading %n files_" : ["Téléversement de %n fichier","Téléversement de %n fichiers"], "New" : "Nouveau", "\"{name}\" is an invalid file name." : "\"{name}\" n'est pas un nom de fichier valide.", "File name cannot be empty." : "Le nom de fichier ne peut être vide.", - "Storage of {owner} is full, files can not be updated or synced anymore!" : "L'espace de stockage de {owner} est plein. Les fichiers ne peuvent plus être mis à jour ou synchronisés!", - "Your storage is full, files can not be updated or synced anymore!" : "Votre espage de stockage est plein, les fichiers ne peuvent plus être ajoutés ou synchronisés !", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "L'espace de stockage de {owner} est plein. Les fichiers ne peuvent plus être mis à jour ni synchronisés !", + "Your storage is full, files can not be updated or synced anymore!" : "Votre espace de stockage est plein. Les fichiers ne peuvent plus être mis à jour ni synchronisés !", "Storage of {owner} is almost full ({usedSpacePercent}%)" : "L'espace de stockage de {owner} est presque plein ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Votre espace de stockage est presque plein ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["correspond à '{filter}'","correspondent à '{filter}'"], - "View in folder" : "Voir dans le dossier", + "View in folder" : "Afficher dans le dossier", "Path" : "Chemin", "_%n byte_::_%n bytes_" : ["%n octet","%n octets"], "Favorited" : "Marqué comme favori", @@ -71,13 +71,13 @@ OC.L10N.register( "Copy local link" : "Copier le dossier local", "Folder" : "Dossier", "New folder" : "Nouveau dossier", - "Upload" : "Chargement", + "Upload" : "Téléverser", "An error occurred while trying to update the tags" : "Une erreur est survenue lors de la mise à jour des étiquettes", "Added to favorites" : "Ajouté aux favoris", "Removed from favorites" : "Retiré des favoris", "You added {file} to your favorites" : "Vous avez ajouté {file} à vos favoris", "You removed {file} from your favorites" : "Vous avez retiré {file} de vos favoris", - "File changes" : "Modifications du fichier", + "File changes" : "Modifications de fichiers", "Created by {user}" : "Créé par {user}", "Changed by {user}" : "Modifié par {user}", "Deleted by {user}" : "Supprimé par {user}", @@ -107,9 +107,9 @@ OC.L10N.register( "File handling" : "Gestion de fichiers", "Maximum upload size" : "Taille max. d'envoi", "max. possible: " : "Max. possible :", - "Save" : "Sauvegarder", + "Save" : "Enregistrer", "With PHP-FPM it might take 5 minutes for changes to be applied." : "Avec PHP-FPM il peut se passer jusqu'à 5 minutes pour que les changements soient appliqués.", - "Missing permissions to edit from here." : "Manque de permissions pour éditer à partir d'ici.", + "Missing permissions to edit from here." : "Permissions insuffisantes pour modifier à partir d'ici.", "Settings" : "Paramètres", "Show hidden files" : "Afficher les fichiers cachés", "WebDAV" : "WebDAV", @@ -129,21 +129,21 @@ OC.L10N.register( "Deleted files" : "Fichiers supprimés", "Text file" : "Fichier texte", "New text file.txt" : "Nouveau fichier texte.txt", - "Storage not available" : "Support de stockage non disponible", + "Storage not available" : "Espace de stockage non disponible", "Unable to set upload directory." : "Impossible de définir le dossier de destination.", "Invalid Token" : "Jeton non valide", "No file was uploaded. Unknown error" : "Aucun fichier n'a été envoyé. Erreur inconnue", - "There is no error, the file uploaded with success" : "Aucune erreur, le fichier a été envoyé avec succès.", + "There is no error, the file uploaded with success" : "Aucune erreur, le fichier a été envoyé avec succès", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " : "Le fichier envoyé dépasse l'instruction upload_max_filesize située dans le fichier php.ini :", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Le fichier envoyé dépasse la valeur MAX_FILE_SIZE qui était spécifiée dans le formulaire HTML.", "The uploaded file was only partially uploaded" : "Le fichier n'a été que partiellement envoyé.", "No file was uploaded" : "Pas de fichier envoyé.", "Missing a temporary folder" : "Absence de dossier temporaire", "Failed to write to disk" : "Erreur d'écriture sur le disque", - "Not enough storage available" : "Trop peu d'espace de stockage disponible", + "Not enough storage available" : "Espace disponible insuffisant", "The target folder has been moved or deleted." : "Le dossier cible a été déplacé ou supprimé.", - "Upload failed. Could not find uploaded file" : "L'envoi a échoué. Impossible de trouver le fichier envoyé.", - "Upload failed. Could not get file info." : "L'envoi a échoué. Impossible d'obtenir les informations du fichier.", + "Upload failed. Could not find uploaded file" : "Le téléversement a échoué. Impossible de trouver le fichier envoyé.", + "Upload failed. Could not get file info." : "Le téléversement a échoué. Impossible d'obtenir les informations du fichier.", "Invalid directory." : "Dossier non valide.", "Total file size {size1} exceeds upload limit {size2}" : "La taille totale du fichier {size1} excède la taille maximale d'envoi {size2}", "Error uploading file \"{fileName}\": {message}" : "Erreur lors de l'envoi du fichier \"{fileName}\" : {message}", @@ -155,10 +155,10 @@ OC.L10N.register( "{seconds} second{plural_s} left" : "{seconds} seconde{plural_s} restante{plural_s}", "{seconds}s" : "{seconds}s", "Any moment now..." : "D'ici quelques instants…", - "Soon..." : "Bientôt...", + "Soon..." : "Bientôt…", "File upload is in progress. Leaving the page now will cancel the upload." : "L'envoi du fichier est en cours. Quitter cette page maintenant annulera l'envoi du fichier.", "No entries in this folder match '{filter}'" : "Aucune entrée de ce dossier ne correspond à '{filter}'", - "Local link" : "Dossier local", + "Local link" : "Lien local", "{newname} already exists" : "{newname} existe déjà", "A file or folder has been <strong>changed</strong>" : "Un fichier ou un répertoire a été <strong>modifié</strong>", "A file or folder has been <strong>deleted</strong>" : "Un fichier ou un répertoire a été <strong>supprimé</strong>", diff --git a/apps/files/l10n/fr.json b/apps/files/l10n/fr.json index e990093bbbb..7538abdba42 100644 --- a/apps/files/l10n/fr.json +++ b/apps/files/l10n/fr.json @@ -1,22 +1,22 @@ { "translations": { - "Storage is temporarily not available" : "Le support de stockage est temporairement non disponible", - "Storage invalid" : "Support de stockage non valable", + "Storage is temporarily not available" : "Le support de stockage est temporairement indisponible", + "Storage invalid" : "Support de stockage invalide", "Unknown error" : "Erreur inconnue ", "Files" : "Fichiers", "All files" : "Tous les fichiers", "Recent" : "Récent", - "File could not be found" : "Ce fichier n'a pu être trouvé.", + "File could not be found" : "Fichier introuvable", "Home" : "Mes fichiers", "Close" : "Fermer", "Favorites" : "Favoris", "Could not create folder \"{dir}\"" : "Impossible de créer le dossier \"{dir}\"", - "Upload cancelled." : "Envoi annulé.", + "Upload cancelled." : "Téléversement annulé.", "Unable to upload {filename} as it is a directory or has 0 bytes" : "Impossible d'envoyer {filename} car il s'agit d'un répertoire ou d'un fichier de taille nulle", "Not enough free space, you are uploading {size1} but only {size2} is left" : "Espace libre insuffisant : vous tentez d'envoyer {size1} mais seulement {size2} sont disponibles", "Target folder \"{dir}\" does not exist any more" : "Le dossier cible « {dir} » n'existe plus", - "Not enough free space" : "Pas assez d'espace disponible", + "Not enough free space" : "Espace disponible insuffisant", "Uploading..." : "Téléversement en cours…", - "..." : "...", + "..." : "…", "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize} sur {totalSize} ({bitrate})", "Actions" : "Actions", "Download" : "Télécharger", @@ -32,7 +32,7 @@ "Pending" : "En attente", "Unable to determine date" : "Impossible de déterminer la date", "This operation is forbidden" : "Cette opération est interdite", - "This directory is unavailable, please check the logs or contact the administrator" : "Ce répertoire n'est pas disponible. Consultez les logs ou contactez votre administrateur", + "This directory is unavailable, please check the logs or contact the administrator" : "Ce dossier n'est pas disponible. Consultez les logs ou contactez votre administrateur", "Could not move \"{file}\", target exists" : "Impossible de déplacer \"{file}\", la cible existe", "Could not move \"{file}\"" : "Impossible de déplacer \"{file}\"", "{newName} already exists" : "{newName} existe déjà", @@ -50,18 +50,18 @@ "_%n folder_::_%n folders_" : ["%n dossier","%n dossiers"], "_%n file_::_%n files_" : ["%n fichier","%n fichiers"], "{dirs} and {files}" : "{dirs} et {files}", - "_including %n hidden_::_including %n hidden_" : ["inclus %n caché","inclus %n cachés"], - "You don’t have permission to upload or create files here" : "Vous n'avez pas la permission d'ajouter des fichiers ici", + "_including %n hidden_::_including %n hidden_" : ["inclus %n masqué","inclus %n masqués"], + "You don’t have permission to upload or create files here" : "Vous n'avez pas la permission d'envoyer ou de créer des fichiers ici", "_Uploading %n file_::_Uploading %n files_" : ["Téléversement de %n fichier","Téléversement de %n fichiers"], "New" : "Nouveau", "\"{name}\" is an invalid file name." : "\"{name}\" n'est pas un nom de fichier valide.", "File name cannot be empty." : "Le nom de fichier ne peut être vide.", - "Storage of {owner} is full, files can not be updated or synced anymore!" : "L'espace de stockage de {owner} est plein. Les fichiers ne peuvent plus être mis à jour ou synchronisés!", - "Your storage is full, files can not be updated or synced anymore!" : "Votre espage de stockage est plein, les fichiers ne peuvent plus être ajoutés ou synchronisés !", + "Storage of {owner} is full, files can not be updated or synced anymore!" : "L'espace de stockage de {owner} est plein. Les fichiers ne peuvent plus être mis à jour ni synchronisés !", + "Your storage is full, files can not be updated or synced anymore!" : "Votre espace de stockage est plein. Les fichiers ne peuvent plus être mis à jour ni synchronisés !", "Storage of {owner} is almost full ({usedSpacePercent}%)" : "L'espace de stockage de {owner} est presque plein ({usedSpacePercent}%)", "Your storage is almost full ({usedSpacePercent}%)" : "Votre espace de stockage est presque plein ({usedSpacePercent}%)", "_matches '{filter}'_::_match '{filter}'_" : ["correspond à '{filter}'","correspondent à '{filter}'"], - "View in folder" : "Voir dans le dossier", + "View in folder" : "Afficher dans le dossier", "Path" : "Chemin", "_%n byte_::_%n bytes_" : ["%n octet","%n octets"], "Favorited" : "Marqué comme favori", @@ -69,13 +69,13 @@ "Copy local link" : "Copier le dossier local", "Folder" : "Dossier", "New folder" : "Nouveau dossier", - "Upload" : "Chargement", + "Upload" : "Téléverser", "An error occurred while trying to update the tags" : "Une erreur est survenue lors de la mise à jour des étiquettes", "Added to favorites" : "Ajouté aux favoris", "Removed from favorites" : "Retiré des favoris", "You added {file} to your favorites" : "Vous avez ajouté {file} à vos favoris", "You removed {file} from your favorites" : "Vous avez retiré {file} de vos favoris", - "File changes" : "Modifications du fichier", + "File changes" : "Modifications de fichiers", "Created by {user}" : "Créé par {user}", "Changed by {user}" : "Modifié par {user}", "Deleted by {user}" : "Supprimé par {user}", @@ -105,9 +105,9 @@ "File handling" : "Gestion de fichiers", "Maximum upload size" : "Taille max. d'envoi", "max. possible: " : "Max. possible :", - "Save" : "Sauvegarder", + "Save" : "Enregistrer", "With PHP-FPM it might take 5 minutes for changes to be applied." : "Avec PHP-FPM il peut se passer jusqu'à 5 minutes pour que les changements soient appliqués.", - "Missing permissions to edit from here." : "Manque de permissions pour éditer à partir d'ici.", + "Missing permissions to edit from here." : "Permissions insuffisantes pour modifier à partir d'ici.", "Settings" : "Paramètres", "Show hidden files" : "Afficher les fichiers cachés", "WebDAV" : "WebDAV", @@ -127,21 +127,21 @@ "Deleted files" : "Fichiers supprimés", "Text file" : "Fichier texte", "New text file.txt" : "Nouveau fichier texte.txt", - "Storage not available" : "Support de stockage non disponible", + "Storage not available" : "Espace de stockage non disponible", "Unable to set upload directory." : "Impossible de définir le dossier de destination.", "Invalid Token" : "Jeton non valide", "No file was uploaded. Unknown error" : "Aucun fichier n'a été envoyé. Erreur inconnue", - "There is no error, the file uploaded with success" : "Aucune erreur, le fichier a été envoyé avec succès.", + "There is no error, the file uploaded with success" : "Aucune erreur, le fichier a été envoyé avec succès", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " : "Le fichier envoyé dépasse l'instruction upload_max_filesize située dans le fichier php.ini :", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Le fichier envoyé dépasse la valeur MAX_FILE_SIZE qui était spécifiée dans le formulaire HTML.", "The uploaded file was only partially uploaded" : "Le fichier n'a été que partiellement envoyé.", "No file was uploaded" : "Pas de fichier envoyé.", "Missing a temporary folder" : "Absence de dossier temporaire", "Failed to write to disk" : "Erreur d'écriture sur le disque", - "Not enough storage available" : "Trop peu d'espace de stockage disponible", + "Not enough storage available" : "Espace disponible insuffisant", "The target folder has been moved or deleted." : "Le dossier cible a été déplacé ou supprimé.", - "Upload failed. Could not find uploaded file" : "L'envoi a échoué. Impossible de trouver le fichier envoyé.", - "Upload failed. Could not get file info." : "L'envoi a échoué. Impossible d'obtenir les informations du fichier.", + "Upload failed. Could not find uploaded file" : "Le téléversement a échoué. Impossible de trouver le fichier envoyé.", + "Upload failed. Could not get file info." : "Le téléversement a échoué. Impossible d'obtenir les informations du fichier.", "Invalid directory." : "Dossier non valide.", "Total file size {size1} exceeds upload limit {size2}" : "La taille totale du fichier {size1} excède la taille maximale d'envoi {size2}", "Error uploading file \"{fileName}\": {message}" : "Erreur lors de l'envoi du fichier \"{fileName}\" : {message}", @@ -153,10 +153,10 @@ "{seconds} second{plural_s} left" : "{seconds} seconde{plural_s} restante{plural_s}", "{seconds}s" : "{seconds}s", "Any moment now..." : "D'ici quelques instants…", - "Soon..." : "Bientôt...", + "Soon..." : "Bientôt…", "File upload is in progress. Leaving the page now will cancel the upload." : "L'envoi du fichier est en cours. Quitter cette page maintenant annulera l'envoi du fichier.", "No entries in this folder match '{filter}'" : "Aucune entrée de ce dossier ne correspond à '{filter}'", - "Local link" : "Dossier local", + "Local link" : "Lien local", "{newname} already exists" : "{newname} existe déjà", "A file or folder has been <strong>changed</strong>" : "Un fichier ou un répertoire a été <strong>modifié</strong>", "A file or folder has been <strong>deleted</strong>" : "Un fichier ou un répertoire a été <strong>supprimé</strong>", diff --git a/apps/files/l10n/hu_HU.js b/apps/files/l10n/hu_HU.js index 13504df625a..a78413903b8 100644 --- a/apps/files/l10n/hu_HU.js +++ b/apps/files/l10n/hu_HU.js @@ -28,6 +28,7 @@ OC.L10N.register( "Delete" : "Törlés", "Disconnect storage" : "Tároló leválasztása", "Unshare" : "A megosztás visszavonása", + "Could not load info for file \"{file}\"" : "Nem sikerült betölteni az információs fájl ehhez: \"{file}\"", "Details" : "Részletek", "Select" : "Kiválaszt", "Pending" : "Folyamatban", diff --git a/apps/files/l10n/hu_HU.json b/apps/files/l10n/hu_HU.json index 2eab8691b64..f0606da7774 100644 --- a/apps/files/l10n/hu_HU.json +++ b/apps/files/l10n/hu_HU.json @@ -26,6 +26,7 @@ "Delete" : "Törlés", "Disconnect storage" : "Tároló leválasztása", "Unshare" : "A megosztás visszavonása", + "Could not load info for file \"{file}\"" : "Nem sikerült betölteni az információs fájl ehhez: \"{file}\"", "Details" : "Részletek", "Select" : "Kiválaszt", "Pending" : "Folyamatban", diff --git a/apps/files/l10n/lv.js b/apps/files/l10n/lv.js index 80e636ff5f0..442f6fc35d6 100644 --- a/apps/files/l10n/lv.js +++ b/apps/files/l10n/lv.js @@ -1,6 +1,7 @@ OC.L10N.register( "files", { + "Storage is temporarily not available" : "Glabātuve īslaicīgi nav pieejama", "Storage invalid" : "Nepareiza glabātuve", "Unknown error" : "Nezināma kļūda", "Files" : "Datnes", @@ -64,6 +65,7 @@ OC.L10N.register( "New folder" : "Jauna mape", "Upload" : "Augšupielādēt", "An error occurred while trying to update the tags" : "Notika kļūda atjaunojot atzīmi", + "You restored {file}" : "Tu atjaunoji {file}", "A new file or folder has been <strong>created</strong>" : "<strong>Izveidota</strong> jauna datne vai mape", "Limit notifications about creation and changes to your <strong>favorite files</strong> <em>(Stream only)</em>" : "Limitēt ziņojumus par jūsu <strong>iecienīto datņu</strong> izveidošanu un izmaiņām <em>(tikai datu straumei)</em>", "Upload (max. %s)" : "Augšupielādēt (maks. %s)", @@ -85,6 +87,10 @@ OC.L10N.register( "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Augšupielādējamās datnes pārsniedz servera pieļaujamo datņu augšupielādes apjomu", "No favorites" : "Nav favorītu", "Files and folders you mark as favorite will show up here" : "Datnes un mapes, ko atzīmēsiet kā favorītus, tiks rādīti šeit", + "Shared with you" : "Koplietots ar tevi", + "Shared by link" : "Koplietots ar saiti", + "Tags" : "Atzīmes", + "Deleted files" : "Dzēstās datnes", "Text file" : "Teksta datne", "New text file.txt" : "Jauna teksta datne.txt", "Storage not available" : "Glabātuve nav pieejama", diff --git a/apps/files/l10n/lv.json b/apps/files/l10n/lv.json index d88665b810f..f109de5242f 100644 --- a/apps/files/l10n/lv.json +++ b/apps/files/l10n/lv.json @@ -1,4 +1,5 @@ { "translations": { + "Storage is temporarily not available" : "Glabātuve īslaicīgi nav pieejama", "Storage invalid" : "Nepareiza glabātuve", "Unknown error" : "Nezināma kļūda", "Files" : "Datnes", @@ -62,6 +63,7 @@ "New folder" : "Jauna mape", "Upload" : "Augšupielādēt", "An error occurred while trying to update the tags" : "Notika kļūda atjaunojot atzīmi", + "You restored {file}" : "Tu atjaunoji {file}", "A new file or folder has been <strong>created</strong>" : "<strong>Izveidota</strong> jauna datne vai mape", "Limit notifications about creation and changes to your <strong>favorite files</strong> <em>(Stream only)</em>" : "Limitēt ziņojumus par jūsu <strong>iecienīto datņu</strong> izveidošanu un izmaiņām <em>(tikai datu straumei)</em>", "Upload (max. %s)" : "Augšupielādēt (maks. %s)", @@ -83,6 +85,10 @@ "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Augšupielādējamās datnes pārsniedz servera pieļaujamo datņu augšupielādes apjomu", "No favorites" : "Nav favorītu", "Files and folders you mark as favorite will show up here" : "Datnes un mapes, ko atzīmēsiet kā favorītus, tiks rādīti šeit", + "Shared with you" : "Koplietots ar tevi", + "Shared by link" : "Koplietots ar saiti", + "Tags" : "Atzīmes", + "Deleted files" : "Dzēstās datnes", "Text file" : "Teksta datne", "New text file.txt" : "Jauna teksta datne.txt", "Storage not available" : "Glabātuve nav pieejama", diff --git a/apps/files/l10n/nb_NO.js b/apps/files/l10n/nb_NO.js index 63164a86d65..e0f02a26713 100644 --- a/apps/files/l10n/nb_NO.js +++ b/apps/files/l10n/nb_NO.js @@ -28,6 +28,7 @@ OC.L10N.register( "Delete" : "Slett", "Disconnect storage" : "Koble fra lagring", "Unshare" : "Avslutt deling", + "Could not load info for file \"{file}\"" : "Klarte ikke å hente informasjon som filen \"{file}\"", "Details" : "Detaljer", "Select" : "Velg", "Pending" : "Venter", diff --git a/apps/files/l10n/nb_NO.json b/apps/files/l10n/nb_NO.json index 1d6d0ab113d..216f9a56368 100644 --- a/apps/files/l10n/nb_NO.json +++ b/apps/files/l10n/nb_NO.json @@ -26,6 +26,7 @@ "Delete" : "Slett", "Disconnect storage" : "Koble fra lagring", "Unshare" : "Avslutt deling", + "Could not load info for file \"{file}\"" : "Klarte ikke å hente informasjon som filen \"{file}\"", "Details" : "Detaljer", "Select" : "Velg", "Pending" : "Venter", diff --git a/apps/files/l10n/zh_CN.js b/apps/files/l10n/zh_CN.js index 0a8e66d18c9..e13409dfc91 100644 --- a/apps/files/l10n/zh_CN.js +++ b/apps/files/l10n/zh_CN.js @@ -1,7 +1,7 @@ OC.L10N.register( "files", { - "Storage is temporarily not available" : "存储暂时不可用", + "Storage is temporarily not available" : "存储空间暂时不可用", "Storage invalid" : "存储空间无效", "Unknown error" : "未知错误", "Files" : "文件", @@ -13,8 +13,8 @@ OC.L10N.register( "Favorites" : "收藏", "Could not create folder \"{dir}\"" : "无法创建文件夹 \"{dir}\"", "Upload cancelled." : "上传已取消", - "Unable to upload {filename} as it is a directory or has 0 bytes" : "无法上传文件 {filename}, 因为其是一个目录或者长度为0字节", - "Not enough free space, you are uploading {size1} but only {size2} is left" : "可用空间不足, 您上传的文件大小为 {size1}, 但可用空间仅剩 {size2}", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "无法上传文件 {filename},因为它是一个目录或者是大小为 0 的空文件", + "Not enough free space, you are uploading {size1} but only {size2} is left" : "可用空间不足,您上传的文件大小为 {size1} ,但可用空间仅剩 {size2}", "Target folder \"{dir}\" does not exist any more" : "目标目录 \"{dir}\" 不存在", "Not enough free space" : "可用空间不足", "Uploading..." : "正在上传...", @@ -28,7 +28,7 @@ OC.L10N.register( "Delete" : "删除", "Disconnect storage" : "断开存储链接", "Unshare" : "取消共享", - "Could not load info for file \"{file}\"" : "无法加载 \"{file}\" 文件信息", + "Could not load info for file \"{file}\"" : "无法加载文件 \"{file}\" 的信息", "Details" : "详细信息", "Select" : "选择", "Pending" : "等待", @@ -42,15 +42,15 @@ OC.L10N.register( "The name \"{targetName}\" is already used in the folder \"{dir}\". Please choose a different name." : "文件夹 \"{dir}\" 中已经存在 \"{targetName}\". 请尝试其他的名称.", "Could not rename \"{fileName}\"" : "无法重命名 \"{fileName}\"", "Could not create file \"{file}\"" : "无法创建文件 \"{file}\"", - "Could not create file \"{file}\" because it already exists" : "无法创建文件 \"{file}\", 因为其已经存在", - "Could not create folder \"{dir}\" because it already exists" : "无法创建文件夹 \"{dir}\", 因为其已经存在", + "Could not create file \"{file}\" because it already exists" : "无法创建文件 \"{file}\", 因为其已经存在", + "Could not create folder \"{dir}\" because it already exists" : "无法创建文件夹 \"{dir}\", 因为其已经存在", "Error deleting file \"{fileName}\"." : "删除文件 \"{fileName}\" 时出错.", "No search results in other folders for '{tag}{filter}{endtag}'" : " 在其他文件夹未找到包含 '{tag}{filter}{endtag}' 标签的结果", "Name" : "名称", "Size" : "大小", "Modified" : "修改日期", "_%n folder_::_%n folders_" : ["%n 个文件夹"], - "_%n file_::_%n files_" : ["%n个文件"], + "_%n file_::_%n files_" : ["%n 个文件"], "{dirs} and {files}" : "{dirs} 和 {files}", "_including %n hidden_::_including %n hidden_" : ["包括 %n 个隐藏文件"], "You don’t have permission to upload or create files here" : "您没有权限在此上传或创建文件", @@ -131,7 +131,7 @@ OC.L10N.register( "New text file.txt" : "创建文本文件 .txt", "Storage not available" : "存储空间不可用", "Unable to set upload directory." : "无法设置上传文件夹.", - "Invalid Token" : "无效密匙", + "Invalid Token" : "无效密钥", "No file was uploaded. Unknown error" : "没有文件被上传. 未知错误", "There is no error, the file uploaded with success" : "文件上传成功, 没有任何错误", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " : "上传文件的大小已超过 php.ini 中 upload_max_filesize 设置的值", diff --git a/apps/files/l10n/zh_CN.json b/apps/files/l10n/zh_CN.json index 26ed83ac15c..9de26c4ee29 100644 --- a/apps/files/l10n/zh_CN.json +++ b/apps/files/l10n/zh_CN.json @@ -1,5 +1,5 @@ { "translations": { - "Storage is temporarily not available" : "存储暂时不可用", + "Storage is temporarily not available" : "存储空间暂时不可用", "Storage invalid" : "存储空间无效", "Unknown error" : "未知错误", "Files" : "文件", @@ -11,8 +11,8 @@ "Favorites" : "收藏", "Could not create folder \"{dir}\"" : "无法创建文件夹 \"{dir}\"", "Upload cancelled." : "上传已取消", - "Unable to upload {filename} as it is a directory or has 0 bytes" : "无法上传文件 {filename}, 因为其是一个目录或者长度为0字节", - "Not enough free space, you are uploading {size1} but only {size2} is left" : "可用空间不足, 您上传的文件大小为 {size1}, 但可用空间仅剩 {size2}", + "Unable to upload {filename} as it is a directory or has 0 bytes" : "无法上传文件 {filename},因为它是一个目录或者是大小为 0 的空文件", + "Not enough free space, you are uploading {size1} but only {size2} is left" : "可用空间不足,您上传的文件大小为 {size1} ,但可用空间仅剩 {size2}", "Target folder \"{dir}\" does not exist any more" : "目标目录 \"{dir}\" 不存在", "Not enough free space" : "可用空间不足", "Uploading..." : "正在上传...", @@ -26,7 +26,7 @@ "Delete" : "删除", "Disconnect storage" : "断开存储链接", "Unshare" : "取消共享", - "Could not load info for file \"{file}\"" : "无法加载 \"{file}\" 文件信息", + "Could not load info for file \"{file}\"" : "无法加载文件 \"{file}\" 的信息", "Details" : "详细信息", "Select" : "选择", "Pending" : "等待", @@ -40,15 +40,15 @@ "The name \"{targetName}\" is already used in the folder \"{dir}\". Please choose a different name." : "文件夹 \"{dir}\" 中已经存在 \"{targetName}\". 请尝试其他的名称.", "Could not rename \"{fileName}\"" : "无法重命名 \"{fileName}\"", "Could not create file \"{file}\"" : "无法创建文件 \"{file}\"", - "Could not create file \"{file}\" because it already exists" : "无法创建文件 \"{file}\", 因为其已经存在", - "Could not create folder \"{dir}\" because it already exists" : "无法创建文件夹 \"{dir}\", 因为其已经存在", + "Could not create file \"{file}\" because it already exists" : "无法创建文件 \"{file}\", 因为其已经存在", + "Could not create folder \"{dir}\" because it already exists" : "无法创建文件夹 \"{dir}\", 因为其已经存在", "Error deleting file \"{fileName}\"." : "删除文件 \"{fileName}\" 时出错.", "No search results in other folders for '{tag}{filter}{endtag}'" : " 在其他文件夹未找到包含 '{tag}{filter}{endtag}' 标签的结果", "Name" : "名称", "Size" : "大小", "Modified" : "修改日期", "_%n folder_::_%n folders_" : ["%n 个文件夹"], - "_%n file_::_%n files_" : ["%n个文件"], + "_%n file_::_%n files_" : ["%n 个文件"], "{dirs} and {files}" : "{dirs} 和 {files}", "_including %n hidden_::_including %n hidden_" : ["包括 %n 个隐藏文件"], "You don’t have permission to upload or create files here" : "您没有权限在此上传或创建文件", @@ -129,7 +129,7 @@ "New text file.txt" : "创建文本文件 .txt", "Storage not available" : "存储空间不可用", "Unable to set upload directory." : "无法设置上传文件夹.", - "Invalid Token" : "无效密匙", + "Invalid Token" : "无效密钥", "No file was uploaded. Unknown error" : "没有文件被上传. 未知错误", "There is no error, the file uploaded with success" : "文件上传成功, 没有任何错误", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " : "上传文件的大小已超过 php.ini 中 upload_max_filesize 设置的值", diff --git a/apps/files_external/appinfo/info.xml b/apps/files_external/appinfo/info.xml index b2f73dce621..8482b8b25ed 100644 --- a/apps/files_external/appinfo/info.xml +++ b/apps/files_external/appinfo/info.xml @@ -3,9 +3,9 @@ <id>files_external</id> <name>External storage support</name> <description> - This application enables administrators to configure connections to external storage providers, such as FTP servers, S3 or SWIFT object stores, Google Drive, Dropbox, other ownCloud servers, WebDAV servers, and more. Administrators can choose which types of storage to enable and can mount these storage locations for a user, a group, or the entire system. Users will see a new folder appear in their root ownCloud directory, which they can access and use like any other ownCloud folder. External storage also allows users to share files stored in these external locations. In these cases, the credentials for the owner of the file are used when the recipient requests the file from external storage, thereby ensuring that the recipient can access the shared file. - - External storage can be configured using the GUI or at the command line. This second option provides the advanced user with more flexibility for configuring bulk external storage mounts and setting mount priorities. More information is available in the external storage GUI documentation and the external storage Configuration File documentation. +This application enables administrators to configure connections to external storage providers, such as FTP servers, S3 or SWIFT object stores, Google Drive, Dropbox, other ownCloud servers, WebDAV servers, and more. Administrators can choose which types of storage to enable and can mount these storage locations for a user, a group, or the entire system. Users will see a new folder appear in their root ownCloud directory, which they can access and use like any other ownCloud folder. External storage also allows users to share files stored in these external locations. In these cases, the credentials for the owner of the file are used when the recipient requests the file from external storage, thereby ensuring that the recipient can access the shared file. + +External storage can be configured using the GUI or at the command line. This second option provides the advanced user with more flexibility for configuring bulk external storage mounts and setting mount priorities. More information is available in the external storage GUI documentation and the external storage Configuration File documentation. </description> <licence>AGPL</licence> <author>Robin Appelman, Michael Gapczynski, Vincent Petry</author> diff --git a/apps/files_external/img/app-dark.svg b/apps/files_external/img/app-dark.svg new file mode 100644 index 00000000000..157af238eeb --- /dev/null +++ b/apps/files_external/img/app-dark.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" viewBox="0 0 32 32"><path d="M14.903 3.237l4.76 4.515-7.14 6.772 4.76 4.514 7.142-6.772 4.762 4.515V3.237H14.904zM5.38 5.495C4.063 5.495 3 6.5 3 7.752V25.81c0 1.25 1.062 2.257 2.38 2.257h19.045c1.318 0 2.38-1.007 2.38-2.257v-6.772l-2.38-2.257v9.03H5.38V7.752h9.523l-2.38-2.258H5.38z" fill="#000"/></svg> diff --git a/apps/files_external/lib/Settings/Section.php b/apps/files_external/lib/Settings/Section.php index 4b4bac93d29..4829bb60d39 100644 --- a/apps/files_external/lib/Settings/Section.php +++ b/apps/files_external/lib/Settings/Section.php @@ -24,13 +24,21 @@ namespace OCA\Files_External\Settings; use OCP\IL10N; -use OCP\Settings\ISection; +use OCP\IURLGenerator; +use OCP\Settings\IIconSection; -class Section implements ISection { +class Section implements IIconSection { /** @var IL10N */ private $l; + /** @var IURLGenerator */ + private $url; - public function __construct(IL10N $l) { + /** + * @param IURLGenerator $url + * @param IL10N $l + */ + public function __construct(IURLGenerator $url, IL10N $l) { + $this->url = $url; $this->l = $l; } @@ -64,4 +72,11 @@ class Section implements ISection { public function getPriority() { return 10; } + + /** + * {@inheritdoc} + */ + public function getIcon() { + return $this->url->imagePath('files_external', 'app-dark.svg'); + } } diff --git a/apps/files_external/tests/Settings/SectionTest.php b/apps/files_external/tests/Settings/SectionTest.php index b5dfb28b382..ee501b1270b 100644 --- a/apps/files_external/tests/Settings/SectionTest.php +++ b/apps/files_external/tests/Settings/SectionTest.php @@ -25,19 +25,24 @@ namespace OCA\Files_External\Tests\Settings; use OCA\Files_External\Settings\Section; use OCP\IL10N; +use OCP\IURLGenerator; use Test\TestCase; class SectionTest extends TestCase { /** @var IL10N */ private $l; + /** @var IURLGenerator */ + private $urlGenerator; /** @var Section */ private $section; public function setUp() { parent::setUp(); + $this->urlGenerator = $this->getMockBuilder('\OCP\IURLGenerator')->disableOriginalConstructor()->getMock(); $this->l = $this->getMockBuilder('\OCP\IL10N')->disableOriginalConstructor()->getMock(); $this->section = new Section( + $this->urlGenerator, $this->l ); } diff --git a/apps/files_sharing/css/authenticate.css b/apps/files_sharing/css/authenticate.css index 55a40cf508d..16687916ac4 100644 --- a/apps/files_sharing/css/authenticate.css +++ b/apps/files_sharing/css/authenticate.css @@ -9,12 +9,8 @@ input[type='submit'] { margin: 6px; } -#body-login input[type='submit'] { - position: absolute; - top: 0; - border: none; -} - fieldset > p { position: relative; + display: flex; + align-items: center; } diff --git a/apps/files_sharing/css/public.css b/apps/files_sharing/css/public.css index 94183cf0057..9c8c4a66630 100644 --- a/apps/files_sharing/css/public.css +++ b/apps/files_sharing/css/public.css @@ -107,29 +107,33 @@ thead { max-width: 90%; } +/* header buttons */ +#details { + display: inline-flex; +} +#details button, +#details input, +#details .button { + margin: 0 5px; + line-height: normal; +} +#details button:hover, +#details input:hover, +#details .button:hover { + /* No */ + border-color: rgba(0,0,0,0.3) !important; +} + /* within #save */ #save .save-form { position: relative; } #remote_address { - margin: 0; - width: 130px; - height: 14px; - padding: 6px; - padding-right: 24px; -} + width: 200px; -.ie8 #remote_address { - padding-right: 30px; -} - -#save #save-button, -#save #save-button-confirm { - margin: 0 5px; - height: 28px; - padding-bottom: 4px; - line-height: 14px; + margin-right: 4px; + height: 31px; } #save-button-confirm { @@ -137,31 +141,9 @@ thead { background-color: transparent; border: none; margin: 2px 4px !important; - right: 0; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; - filter: alpha(opacity=50); - opacity: .5; -} - -.ie8 #save-button-confirm { - margin: 2px 0 !important; -} - -#save-button-confirm:disabled, -#save-button-confirm:disabled:hover, -#save-button-confirm:disabled:focus { - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)"; - filter: alpha(opacity=20); - opacity: .2; - cursor: default; -} - -#save-button-confirm:hover, -#save-button-confirm:focus { - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; - filter: alpha(opacity=100); - opacity: 1; - cursor: pointer; + right: 7px; + top: -8px; + height: 30px; } #public-upload .avatardiv { diff --git a/apps/files_sharing/css/sharetabview.css b/apps/files_sharing/css/sharetabview.css index 936e1af246a..979ef01c030 100644 --- a/apps/files_sharing/css/sharetabview.css +++ b/apps/files_sharing/css/sharetabview.css @@ -51,10 +51,9 @@ padding: 0 0 16px; } -#shareWithList li { +#shareWithList > li { padding-top: 5px; padding-bottom: 5px; - font-weight: bold; white-space: normal; display: inline-flex; align-items: center; @@ -70,6 +69,11 @@ opacity: .5; } +#shareWithList .shareOption.menuitem > label:before { + /* Checkboxes positionning */ + margin: 0 12px !important; +} + #shareWithList .unshare { padding: 1px 6px; vertical-align: text-bottom; @@ -78,12 +82,6 @@ vertical-align: text-top; } -#shareWithList .unshare .icon-delete { - padding-right: 4px; - background-position-x: 0; - display: inline-block; -} - #shareWithList .sharingOptionsGroup .popovermenu:after { right: 3px; } @@ -100,7 +98,7 @@ overflow: hidden; vertical-align: middle; } -#shareWithList li label { +#shareWithList li .sharingOptionsGroup > .shareOption > label { padding: 6px; margin-right: 8px; vertical-align: text-top; diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index 0045c7156d2..ad3ef856f23 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -259,7 +259,7 @@ OCA.Sharing.PublicApp = { $('.save-form').submit(function (event) { event.preventDefault(); - var remote = $(this).find('input[type="text"]').val(); + var remote = $(this).find('input[type="email"]').val(); var token = $('#sharingToken').val(); var owner = $('#save').data('owner'); var ownerDisplayName = $('#save').data('owner-display-name'); diff --git a/apps/files_sharing/l10n/de.js b/apps/files_sharing/l10n/de.js index be95fb9cbca..3505b3b07ab 100644 --- a/apps/files_sharing/l10n/de.js +++ b/apps/files_sharing/l10n/de.js @@ -91,9 +91,9 @@ OC.L10N.register( "{actor} shared {file} with you" : "{actor} hat {file} mit dir geteilt", "%2$s removed you from %1$s" : "Du wurdest durch %2$s von %1$s entfernt", "{actor} removed you from {file}" : "Du wurdest durch {actor} von {file} entfernt", - "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Eine Datei oder ein Ordner der per E-Mail oder öffentlich geteilt ist wurde <strong>heruntergeladen</strong>", + "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Öffentlich oder per E-Mail geteilte Datei / Ordner wurde <strong>heruntergeladen</strong>", "A file or folder was shared from <strong>another server</strong>" : "Eine Datei oder ein Ordner wurde von <strong>einem anderen Server</strong> geteilt", - "A file or folder has been <strong>shared</strong>" : "Eine Datei oder ein Ordner wurde <strong>geteilt</strong>", + "A file or folder has been <strong>shared</strong>" : "Eine Datei oder ein Ordner wurden <strong>geteilt</strong>", "Wrong share ID, share doesn't exist" : "Fehlerhafte Freigabe-ID, Freigabe existiert nicht", "could not delete share" : "Freigabe konnte nicht gelöscht werden", "Could not delete share" : "Freigabe konnte nicht gelöscht werden", @@ -138,7 +138,7 @@ OC.L10N.register( "Select or drop files" : "Dateien auswählen oder hierher ziehen", "Uploading files…" : "Dateien werden hochgeladen...", "Uploaded files:" : "Hochgeladene Dateien: ", - "A public shared file or folder was <strong>downloaded</strong>" : "Eine öffentliche geteilte Datei oder ein öffentlicher geteilter Ordner wurde <strong>heruntergeladen</strong>", + "A public shared file or folder was <strong>downloaded</strong>" : "Eine öffentlich geteilte Datei / Ordner wurde <strong>heruntergeladen</strong>", "You received a new remote share %2$s from %1$s" : "Du hast eine neue Remotefreigabe %2$s von %1$s erhalten", "You received a new remote share from %s" : "Du hast eine neue Remotefreigabe von %s erhalten", "%1$s accepted remote share %2$s" : "%1$s hat die Remotefreigabe von %2$s akzeptiert", diff --git a/apps/files_sharing/l10n/de.json b/apps/files_sharing/l10n/de.json index fe75914067f..95c3f5dd72e 100644 --- a/apps/files_sharing/l10n/de.json +++ b/apps/files_sharing/l10n/de.json @@ -89,9 +89,9 @@ "{actor} shared {file} with you" : "{actor} hat {file} mit dir geteilt", "%2$s removed you from %1$s" : "Du wurdest durch %2$s von %1$s entfernt", "{actor} removed you from {file}" : "Du wurdest durch {actor} von {file} entfernt", - "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Eine Datei oder ein Ordner der per E-Mail oder öffentlich geteilt ist wurde <strong>heruntergeladen</strong>", + "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Öffentlich oder per E-Mail geteilte Datei / Ordner wurde <strong>heruntergeladen</strong>", "A file or folder was shared from <strong>another server</strong>" : "Eine Datei oder ein Ordner wurde von <strong>einem anderen Server</strong> geteilt", - "A file or folder has been <strong>shared</strong>" : "Eine Datei oder ein Ordner wurde <strong>geteilt</strong>", + "A file or folder has been <strong>shared</strong>" : "Eine Datei oder ein Ordner wurden <strong>geteilt</strong>", "Wrong share ID, share doesn't exist" : "Fehlerhafte Freigabe-ID, Freigabe existiert nicht", "could not delete share" : "Freigabe konnte nicht gelöscht werden", "Could not delete share" : "Freigabe konnte nicht gelöscht werden", @@ -136,7 +136,7 @@ "Select or drop files" : "Dateien auswählen oder hierher ziehen", "Uploading files…" : "Dateien werden hochgeladen...", "Uploaded files:" : "Hochgeladene Dateien: ", - "A public shared file or folder was <strong>downloaded</strong>" : "Eine öffentliche geteilte Datei oder ein öffentlicher geteilter Ordner wurde <strong>heruntergeladen</strong>", + "A public shared file or folder was <strong>downloaded</strong>" : "Eine öffentlich geteilte Datei / Ordner wurde <strong>heruntergeladen</strong>", "You received a new remote share %2$s from %1$s" : "Du hast eine neue Remotefreigabe %2$s von %1$s erhalten", "You received a new remote share from %s" : "Du hast eine neue Remotefreigabe von %s erhalten", "%1$s accepted remote share %2$s" : "%1$s hat die Remotefreigabe von %2$s akzeptiert", diff --git a/apps/files_sharing/l10n/de_DE.js b/apps/files_sharing/l10n/de_DE.js index bbfdae37c58..01bcc8ccbe8 100644 --- a/apps/files_sharing/l10n/de_DE.js +++ b/apps/files_sharing/l10n/de_DE.js @@ -97,7 +97,7 @@ OC.L10N.register( "Wrong share ID, share doesn't exist" : "Fehlerhafte Freigabe-ID, Freigabe existiert nicht", "could not delete share" : "Freigabe konnte nicht gelöscht werden", "Could not delete share" : "Freigabe konnte nicht gelöscht werden", - "Please specify a file or folder path" : "Bitte geben Sie eine Datei oder Ordner an", + "Please specify a file or folder path" : "Bitte Datei oder Ordner-Pfad eingeben", "Wrong path, file/folder doesn't exist" : "Falscher Pfad, Datei/Verzeichnis existiert nicht", "Could not create share" : "Freigabe konnte nicht erstellt werden", "invalid permissions" : "Ungültige Berechtigung", diff --git a/apps/files_sharing/l10n/de_DE.json b/apps/files_sharing/l10n/de_DE.json index e62bb0d816f..5c5d6b815b7 100644 --- a/apps/files_sharing/l10n/de_DE.json +++ b/apps/files_sharing/l10n/de_DE.json @@ -95,7 +95,7 @@ "Wrong share ID, share doesn't exist" : "Fehlerhafte Freigabe-ID, Freigabe existiert nicht", "could not delete share" : "Freigabe konnte nicht gelöscht werden", "Could not delete share" : "Freigabe konnte nicht gelöscht werden", - "Please specify a file or folder path" : "Bitte geben Sie eine Datei oder Ordner an", + "Please specify a file or folder path" : "Bitte Datei oder Ordner-Pfad eingeben", "Wrong path, file/folder doesn't exist" : "Falscher Pfad, Datei/Verzeichnis existiert nicht", "Could not create share" : "Freigabe konnte nicht erstellt werden", "invalid permissions" : "Ungültige Berechtigung", diff --git a/apps/files_sharing/l10n/fr.js b/apps/files_sharing/l10n/fr.js index ce7f6154280..095483d6167 100644 --- a/apps/files_sharing/l10n/fr.js +++ b/apps/files_sharing/l10n/fr.js @@ -13,7 +13,7 @@ OC.L10N.register( "You can upload into this folder" : "Vous pouvez téléverser dans ce dossier", "No compatible server found at {remote}" : "Aucun serveur compatible trouvé sur {remote}", "Invalid server URL" : "URL serveur invalide", - "Failed to add the public link to your Nextcloud" : "Echec de l'ajout du lien public à votre Nextcloud", + "Failed to add the public link to your Nextcloud" : "Échec de l'ajout du lien public à votre Nextcloud", "Share" : "Partager", "No expiration date set" : "Aucune date d'expiration définie", "Shared by" : "Partagé par", diff --git a/apps/files_sharing/l10n/fr.json b/apps/files_sharing/l10n/fr.json index ba1cc34f790..024e9f7983d 100644 --- a/apps/files_sharing/l10n/fr.json +++ b/apps/files_sharing/l10n/fr.json @@ -11,7 +11,7 @@ "You can upload into this folder" : "Vous pouvez téléverser dans ce dossier", "No compatible server found at {remote}" : "Aucun serveur compatible trouvé sur {remote}", "Invalid server URL" : "URL serveur invalide", - "Failed to add the public link to your Nextcloud" : "Echec de l'ajout du lien public à votre Nextcloud", + "Failed to add the public link to your Nextcloud" : "Échec de l'ajout du lien public à votre Nextcloud", "Share" : "Partager", "No expiration date set" : "Aucune date d'expiration définie", "Shared by" : "Partagé par", diff --git a/apps/files_sharing/l10n/pl.js b/apps/files_sharing/l10n/pl.js index e1bec669533..0e2339b6581 100644 --- a/apps/files_sharing/l10n/pl.js +++ b/apps/files_sharing/l10n/pl.js @@ -1,55 +1,168 @@ OC.L10N.register( "files_sharing", { - "Server to server sharing is not enabled on this server" : "Współdzielenie między serwerami nie jest uruchomione na tym serwerze", - "The mountpoint name contains invalid characters." : "Nazwa zamontowanego zasobu zawiera niedozwolone znaki.", - "Invalid or untrusted SSL certificate" : "Niewłaściwy lub niezaufany certyfikat SSL", - "Could not authenticate to remote share, password might be wrong" : "Nie można zalogować do zdalnego zasobu, hasło może być niepoprawne", - "Storage not valid" : "Zasób nie jest prawidłowy", - "Couldn't add remote share" : "Nie można dodać zdalnego folderu", "Shared with you" : "Współdzielony z Tobą", "Shared with others" : "Współdzielony z innymi", "Shared by link" : "Współdzielony linkiem", "Nothing shared with you yet" : "Nie masz jeszcze nic udostępnionego", "Files and folders others share with you will show up here" : "Pliki i foldery udostępnione Tobie przez innych wyświetlą się tutaj", "Nothing shared yet" : "Jeszcze nic nie udostępniono", - "Files and folders you share will show up here" : "Plik i foldery, które udostępniasz, pokażą się tutaj", + "Files and folders you share will show up here" : "Pliki i foldery, które udostępniasz, pokażą się tutaj", "No shared links" : "Brak udostępnionych odnośników", - "Files and folders you share by link will show up here" : "Plik i foldery, które udostępniasz, pokażą się tutaj", - "Do you want to add the remote share {name} from {owner}@{remote}?" : "Czy chcesz dodać udział zdalny {name} od {owner}@{remote}?", - "Remote share" : "Zdalny zasób", - "Remote share password" : "Hasło do zdalnego zasobu", - "Cancel" : "Anuluj", - "Add remote share" : "Dodaj zdalny zasób", - "No ownCloud installation (7 or higher) found at {remote}" : "Nie znaleziono instalacji ownCloud (w wersji 7 lub nowszej) na {remote}", - "Invalid ownCloud url" : "Błędny adres URL", + "Files and folders you share by link will show up here" : "Pliki i foldery, które udostępniasz, pokażą się tutaj", + "You can upload into this folder" : "Możesz przesłać do tego folderu", + "No compatible server found at {remote}" : "Nie znaleziono kompatybilnego serwera na {remote}", + "Invalid server URL" : "Błędny adres serwera", + "Failed to add the public link to your Nextcloud" : "Nie udało się dodać linku do publicznego Nextcloud", + "Share" : "Udostępnij", + "No expiration date set" : "Nie ustawiono daty wygaśnięcia", "Shared by" : "Udostępniane przez", "Sharing" : "Udostępnianie", + "File shares" : "Udziały", + "Downloaded via public link" : "Pobierane poprzez link publiczny", + "Downloaded by %1$s" : "Pobierane przez %1$s", + "Downloaded by {email}" : "Pobierane przez {email}", + "%1$s downloaded via public link" : "%1$s pobierane za pośrednictwem łącza publicznego", + "{file} downloaded via public link" : "{file} pobierane za pośrednictwem łącza publicznego", + "%1$s downloaded %2$s" : "%1$s pobierane %2$s", + "{email} downloaded {file}" : "{email} pobierane {file}", + "Shared with group %1$s" : "Udostępnione grupie %1$s", + "Shared with group {group}" : "Udostępnione grupie {group}", + "Removed share for group %1$s" : "Zakończono udostępnianie grupie %1$s", + "Removed share for group {group}" : "Zakończono udostępnianie grupie {group}", + "%2$s shared with group %1$s" : "%2$s jest udostępniane grupie %1$s", + "{actor} shared with group {group}" : "{actor} udostępnił grupie {group}", + "%2$s removed share for group %1$s" : "%2$s zakończył udostępnianie grupie %1$s", + "{actor} removed share for group {group}" : "{actor} zakończył udostępnianie grupie {group}", + "You shared %1$s with group %2$s" : "Współdzielisz %1$s z grupą %2$s", + "You shared {file} with group {group}" : "Udostępniasz {file} grupie {group}", + "You removed group %2$s from %1$s" : "Usunąłeś grupę %2$s z %1$s", + "You removed group {group} from {file}" : "Usunąłeś grupę {group} z {file}", + "%3$s shared %1$s with group %2$s" : "%3$s udostępnił %1$s grupie %2$s", + "{actor} shared {file} with group {group}" : "{actor} udostępnił {file} grupie {group}", + "%3$s removed group %2$s from %1$s" : "%3$s usunął grupę %2$s z %1$s", + "{actor} removed group {group} from {file}" : "{actor} usunął grupę {group} z {file}", + "Shared as public link" : "Udostępnione jako publiczny link", + "Removed public link" : "Usunięto link publiczny", + "%1$s shared as public link" : "%1$s udostępnione jako publiczny link", + "{actor} shared as public link" : "{actor} udostępniony jako publiczny link", + "%1$s removed public link" : "%1$s usunąłeś publiczny link", + "{actor} removed public link" : "{actor} usunął publiczny link", + "You shared %1$s as public link" : "Udostępniasz %1$s jako publiczny link", + "You shared {file} as public link" : "Udostępniasz {file} jako publiczny link", + "You removed public link for %1$s" : "Usuwasz link publiczny dla %1$s", + "You removed public link for {file}" : "Usuwasz link publiczny dla {file}", + "%2$s shared %1$s as public link" : "%2$s udostępnił %1$s jako publiczne łącze", + "{actor} shared {file} as public link" : "{actor} udostępnił {file} jako publiczne łącze", + "%2$s removed public link for %1$s" : "%2$s usunął publiczne łącze do %1$s", + "{actor} removed public link for {file}" : "{actor} usunął publiczne łącze do {file}", + "%1$s accepted the remote share" : "%1$s zaakceptował zdalny udział", + "{user} accepted the remote share" : "{user} zaakceptował zdalny udział", + "%1$s declined the remote share" : "%1$s odrzucił zdalny udział", + "{user} declined the remote share" : "{user} odrzucił zdalny udział", + "You received a new remote share %1$s from %2$s" : "Otrzymałeś nowy zdalny udział %1$s od użytkownika %2$s", + "You received a new remote share {file} from {user}" : "Otrzymałeś nowy zdalny udział {file} od użytkownika {user}", + "%2$s accepted the remote share of %1$s" : "%2$s zaakceptował zdalny udział %1$s", + "{user} accepted the remote share of {file}" : "{user} zaakceptował zdalny udział {file}", + "%2$s declined the remote share of %1$s" : "%2$s odrzucił zdalny udział %1$s", + "{user} declined the remote share of {file}" : "{user} odrzucił zadalny udział {file}", + "%2$s unshared %1$s from you" : "%2$s przestał ci udostępniać %1$s", + "{user} unshared {file} from you" : "{user} przestał ci udostępniać {file}", + "Shared with %1$s" : "Udostępnione %1$s", + "Shared with {user}" : "Udostępnione użytkownikowi {user}", + "Removed share for %1$s" : "Zakończono udostępnianie użytkownikowi %1$s", + "Removed share for {user}" : "Zakończono udostępnianie użytkownikowi {user}", + "%2$s shared with %1$s" : "%2$s udostępnia użytkownikowi %1$s", + "{actor} shared with {user}" : "{actor} udostępnia użytkownikowi {user}", + "%2$s removed share for %1$s" : "%2$s usuwa udostępnienie dla użytkownika %1$s", + "{actor} removed share for {user}" : "{actor} usuwa udostępnienie dla użytkownika {user}", + "Shared by %1$s" : "Udostępnione przez użytkownika %1$s", + "Shared by {actor}" : "Udostępnione przez użytkownika {actor}", + "%1$s removed share" : "%1$s usunął udostępnienie", + "{actor} removed share" : "{actor} usunął udostępnienie", + "You shared %1$s with %2$s" : "Współdzielisz %1$s z %2$s", + "You shared {file} with {user}" : "Współdzielisz {file} z {user}", + "You removed %2$s from %1$s" : "Usunąłeś użytkownika %2$s z %1$s", + "You removed {user} from {file}" : "Usunąłeś użytkownika {user} z {file}", + "%3$s shared %1$s with %2$s" : "%3$s udostępnił %1$s użytkownikowi %2$s", + "{actor} removed {user} from {file}" : "{actor} usunął użytkownika {user} z {file}", + "%3$s removed %2$s from %1$s" : "%3$s usunął użytkownika %2$s z %1$s", + "%2$s shared %1$s with you" : "%2$s współdzieli %1$s z Tobą", + "{actor} shared {file} with you" : "{actor} udostępnił ci {file}", + "%2$s removed you from %1$s" : "%2$s usunął cię z %1$s", + "{actor} removed you from {file}" : "{actor} usunął cie z {file}", + "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Plik lub folder udostępniony za pomocą maila lub publicznego łącza został <strong>pobrany</strong>", + "A file or folder was shared from <strong>another server</strong>" : "Plik lub folder został udostępniony z <strong>innego serwera</strong>", + "A file or folder has been <strong>shared</strong>" : "Plik lub folder stał się <strong>współdzielony</strong>", + "Wrong share ID, share doesn't exist" : "Złe ID udziału, udział nie istnieje", + "could not delete share" : "nie można usunąć udział", + "Could not delete share" : "Nie można usunąć udział", + "Please specify a file or folder path" : "Proszę podać pliku lub ścieżkę do folderu", + "Wrong path, file/folder doesn't exist" : "Ścieżka nieprawidłowa, plik/folder nie istnieje", + "Could not create share" : "Nie można utworzyć udział", + "invalid permissions" : "nieprawidłowe uprawnienia", + "Please specify a valid user" : "Proszę podać poprawnego użytkownika", + "Group sharing is disabled by the administrator" : "Udostępnianie grupy zostało wyłączone przez administratora", + "Please specify a valid group" : "Proszę podać prawidłową grupę", "Public link sharing is disabled by the administrator" : "Udostępnianie linków publicznych zostało zablokowane przez twojego administratora", "Public upload disabled by the administrator" : "Publiczne wczytywanie zostało zablokowane przez twojego administratora", "Public upload is only possible for publicly shared folders" : "Publiczne wczytywanie jest możliwe wyłącznie do katalogów publicznych", - "A file or folder has been <strong>shared</strong>" : "Plik lub folder stał się <strong>współdzielony</strong>", - "You shared %1$s with %2$s" : "Współdzielisz %1$s z %2$s", - "You shared %1$s with group %2$s" : "Współdzielisz %1$s z grupą %2$s", - "You shared %1$s via link" : "Udostępniasz %1$s przez link", - "%2$s shared %1$s with you" : "%2$s współdzieli %1$s z Tobą", - "%2$s removed the share for %1$s" : "%2$s usunął udział dla %1$s", - "Shares" : "Udziały", + "Invalid date, date format must be YYYY-MM-DD" : "Nieprawidłowa data, format daty musi być YYYY-MM-DD", + "Sharing %s failed because the back end does not allow shares from type %s" : "Udostępnienie %s nie powiodło się ponieważ backend nie zezwala na udziały typu %s", + "Unknown share type" : "Nieznany typ udziału", + "Not a directory" : "Nie jest katalogiem", + "Could not lock path" : "Nie udało się zablokować ścieżki", + "Wrong or no update parameter given" : "Brakujący lub błędny parametr aktualizacji", + "Can't change permissions for public share links" : "Nie można zmienić uprawnień dla publicznych udziałów", + "Cannot increase permissions" : "Nie można zwiększyć uprawnień", + "%s is publicly shared" : "%s jest publicznie dostępny", + "Share API is disabled" : "API udostępniania jest wyłączone", "This share is password-protected" : "Udział ten jest chroniony hasłem", "The password is wrong. Try again." : "To hasło jest niewłaściwe. Spróbuj ponownie.", "Password" : "Hasło", "No entries found in this folder" : "Brak wpisów w tym folderze", "Name" : "Nazwa", "Share time" : "Czas współdzielenia", + "Expiration date" : "Data wygaśnięcia", "Sorry, this link doesn’t seem to work anymore." : "Przepraszamy ale wygląda na to, że ten link już nie działa.", "Reasons might be:" : "Możliwe powody:", "the item was removed" : "element został usunięty", "the link expired" : "link wygasł", "sharing is disabled" : "udostępnianie jest wyłączone", "For more info, please ask the person who sent this link." : "Aby uzyskać więcej informacji proszę poprosić osobę, która wysłał ten link.", - "Add to your ownCloud" : "Dodaj do twojego ownCloud", + "Add to your Nextcloud" : "Dodaj do swojego Nextcloud", "Download" : "Pobierz", "Download %s" : "Pobierz %s", - "Direct link" : "Bezpośredni link" + "Direct link" : "Bezpośredni link", + "Upload files to %s" : "Prześlij pliki do %s", + "Select or drop files" : "Wybierz i upuść pliki", + "Uploading files…" : "Wysyłanie plików...", + "Uploaded files:" : "Wysłane pliki:", + "A public shared file or folder was <strong>downloaded</strong>" : "Publicznie udostępniony plik lub katalog został <strong>pobrany</strong>", + "You received a new remote share %2$s from %1$s" : "Otrzymałeś nowy udział zdalny %2$s z %1$s", + "You received a new remote share from %s" : "Otrzymałeś nowy zdalny udział z %s", + "%1$s accepted remote share %2$s" : "%1$s zaakceptował zdalny udział %2$s", + "%1$s declined remote share %2$s" : "%1$s odrzucił zdalny udział %2$s", + "%1$s unshared %2$s from you" : "%1$s zakończył udostępnianie Ci %2$s", + "Public shared folder %1$s was downloaded" : "Udostępniony publicznie folder %1$s został pobrany", + "Public shared file %1$s was downloaded" : "Udostępniony publicznie plik %1$s został pobrany", + "%2$s shared %1$s with %3$s" : "%2$s udostępnił %1$s użytkownikowi %3$s", + "You removed the share of %2$s for %1$s" : "Zakończyłeś udostępnianie %2$s użytkownikowi %1$s", + "%2$s removed the share of %3$s for %1$s" : "%2$s zakończył udostępnianie %3$s użytkownikowi %1$s", + "%2$s shared %1$s with group %3$s" : "%2$s udostępnił %1$s grupie %3$s", + "%2$s shared %1$s via link" : "%2$s udostępnił %1$s poprzez łącze", + "You shared %1$s via link" : "Udostępniasz %1$s przez link", + "Your public link for %1$s expired" : "Twoje publiczne łącze do %1$s wygasło", + "%2$s removed the share for %1$s" : "%2$s usunął udział dla %1$s", + "Shared with %2$s" : "Współdzielone z %2$s", + "Shared with %3$s by %2$s" : "Udostępniono użytkownikowi %3$s przez %2$s", + "Shared with group %2$s" : "Udostępniono grupie %2$s", + "Shared with group %3$s by %2$s" : "Udostępniono grupie %3$s przez użytkownika %2$s", + "Shared via link by %2$s" : "Udostępniono za pomocą łącza przez użytkownika %2$s", + "Shared via public link" : "Udostępniono przez publiczne łącze", + "%2$s removed public link" : "%2$s usunął publiczne łącze", + "Public link expired" : "Link publiczny wygasł", + "Shared by %2$s" : "Udostępniane przez %2$s", + "Shares" : "Udziały" }, "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"); diff --git a/apps/files_sharing/l10n/pl.json b/apps/files_sharing/l10n/pl.json index 6190871b16f..955222647b3 100644 --- a/apps/files_sharing/l10n/pl.json +++ b/apps/files_sharing/l10n/pl.json @@ -1,53 +1,166 @@ { "translations": { - "Server to server sharing is not enabled on this server" : "Współdzielenie między serwerami nie jest uruchomione na tym serwerze", - "The mountpoint name contains invalid characters." : "Nazwa zamontowanego zasobu zawiera niedozwolone znaki.", - "Invalid or untrusted SSL certificate" : "Niewłaściwy lub niezaufany certyfikat SSL", - "Could not authenticate to remote share, password might be wrong" : "Nie można zalogować do zdalnego zasobu, hasło może być niepoprawne", - "Storage not valid" : "Zasób nie jest prawidłowy", - "Couldn't add remote share" : "Nie można dodać zdalnego folderu", "Shared with you" : "Współdzielony z Tobą", "Shared with others" : "Współdzielony z innymi", "Shared by link" : "Współdzielony linkiem", "Nothing shared with you yet" : "Nie masz jeszcze nic udostępnionego", "Files and folders others share with you will show up here" : "Pliki i foldery udostępnione Tobie przez innych wyświetlą się tutaj", "Nothing shared yet" : "Jeszcze nic nie udostępniono", - "Files and folders you share will show up here" : "Plik i foldery, które udostępniasz, pokażą się tutaj", + "Files and folders you share will show up here" : "Pliki i foldery, które udostępniasz, pokażą się tutaj", "No shared links" : "Brak udostępnionych odnośników", - "Files and folders you share by link will show up here" : "Plik i foldery, które udostępniasz, pokażą się tutaj", - "Do you want to add the remote share {name} from {owner}@{remote}?" : "Czy chcesz dodać udział zdalny {name} od {owner}@{remote}?", - "Remote share" : "Zdalny zasób", - "Remote share password" : "Hasło do zdalnego zasobu", - "Cancel" : "Anuluj", - "Add remote share" : "Dodaj zdalny zasób", - "No ownCloud installation (7 or higher) found at {remote}" : "Nie znaleziono instalacji ownCloud (w wersji 7 lub nowszej) na {remote}", - "Invalid ownCloud url" : "Błędny adres URL", + "Files and folders you share by link will show up here" : "Pliki i foldery, które udostępniasz, pokażą się tutaj", + "You can upload into this folder" : "Możesz przesłać do tego folderu", + "No compatible server found at {remote}" : "Nie znaleziono kompatybilnego serwera na {remote}", + "Invalid server URL" : "Błędny adres serwera", + "Failed to add the public link to your Nextcloud" : "Nie udało się dodać linku do publicznego Nextcloud", + "Share" : "Udostępnij", + "No expiration date set" : "Nie ustawiono daty wygaśnięcia", "Shared by" : "Udostępniane przez", "Sharing" : "Udostępnianie", + "File shares" : "Udziały", + "Downloaded via public link" : "Pobierane poprzez link publiczny", + "Downloaded by %1$s" : "Pobierane przez %1$s", + "Downloaded by {email}" : "Pobierane przez {email}", + "%1$s downloaded via public link" : "%1$s pobierane za pośrednictwem łącza publicznego", + "{file} downloaded via public link" : "{file} pobierane za pośrednictwem łącza publicznego", + "%1$s downloaded %2$s" : "%1$s pobierane %2$s", + "{email} downloaded {file}" : "{email} pobierane {file}", + "Shared with group %1$s" : "Udostępnione grupie %1$s", + "Shared with group {group}" : "Udostępnione grupie {group}", + "Removed share for group %1$s" : "Zakończono udostępnianie grupie %1$s", + "Removed share for group {group}" : "Zakończono udostępnianie grupie {group}", + "%2$s shared with group %1$s" : "%2$s jest udostępniane grupie %1$s", + "{actor} shared with group {group}" : "{actor} udostępnił grupie {group}", + "%2$s removed share for group %1$s" : "%2$s zakończył udostępnianie grupie %1$s", + "{actor} removed share for group {group}" : "{actor} zakończył udostępnianie grupie {group}", + "You shared %1$s with group %2$s" : "Współdzielisz %1$s z grupą %2$s", + "You shared {file} with group {group}" : "Udostępniasz {file} grupie {group}", + "You removed group %2$s from %1$s" : "Usunąłeś grupę %2$s z %1$s", + "You removed group {group} from {file}" : "Usunąłeś grupę {group} z {file}", + "%3$s shared %1$s with group %2$s" : "%3$s udostępnił %1$s grupie %2$s", + "{actor} shared {file} with group {group}" : "{actor} udostępnił {file} grupie {group}", + "%3$s removed group %2$s from %1$s" : "%3$s usunął grupę %2$s z %1$s", + "{actor} removed group {group} from {file}" : "{actor} usunął grupę {group} z {file}", + "Shared as public link" : "Udostępnione jako publiczny link", + "Removed public link" : "Usunięto link publiczny", + "%1$s shared as public link" : "%1$s udostępnione jako publiczny link", + "{actor} shared as public link" : "{actor} udostępniony jako publiczny link", + "%1$s removed public link" : "%1$s usunąłeś publiczny link", + "{actor} removed public link" : "{actor} usunął publiczny link", + "You shared %1$s as public link" : "Udostępniasz %1$s jako publiczny link", + "You shared {file} as public link" : "Udostępniasz {file} jako publiczny link", + "You removed public link for %1$s" : "Usuwasz link publiczny dla %1$s", + "You removed public link for {file}" : "Usuwasz link publiczny dla {file}", + "%2$s shared %1$s as public link" : "%2$s udostępnił %1$s jako publiczne łącze", + "{actor} shared {file} as public link" : "{actor} udostępnił {file} jako publiczne łącze", + "%2$s removed public link for %1$s" : "%2$s usunął publiczne łącze do %1$s", + "{actor} removed public link for {file}" : "{actor} usunął publiczne łącze do {file}", + "%1$s accepted the remote share" : "%1$s zaakceptował zdalny udział", + "{user} accepted the remote share" : "{user} zaakceptował zdalny udział", + "%1$s declined the remote share" : "%1$s odrzucił zdalny udział", + "{user} declined the remote share" : "{user} odrzucił zdalny udział", + "You received a new remote share %1$s from %2$s" : "Otrzymałeś nowy zdalny udział %1$s od użytkownika %2$s", + "You received a new remote share {file} from {user}" : "Otrzymałeś nowy zdalny udział {file} od użytkownika {user}", + "%2$s accepted the remote share of %1$s" : "%2$s zaakceptował zdalny udział %1$s", + "{user} accepted the remote share of {file}" : "{user} zaakceptował zdalny udział {file}", + "%2$s declined the remote share of %1$s" : "%2$s odrzucił zdalny udział %1$s", + "{user} declined the remote share of {file}" : "{user} odrzucił zadalny udział {file}", + "%2$s unshared %1$s from you" : "%2$s przestał ci udostępniać %1$s", + "{user} unshared {file} from you" : "{user} przestał ci udostępniać {file}", + "Shared with %1$s" : "Udostępnione %1$s", + "Shared with {user}" : "Udostępnione użytkownikowi {user}", + "Removed share for %1$s" : "Zakończono udostępnianie użytkownikowi %1$s", + "Removed share for {user}" : "Zakończono udostępnianie użytkownikowi {user}", + "%2$s shared with %1$s" : "%2$s udostępnia użytkownikowi %1$s", + "{actor} shared with {user}" : "{actor} udostępnia użytkownikowi {user}", + "%2$s removed share for %1$s" : "%2$s usuwa udostępnienie dla użytkownika %1$s", + "{actor} removed share for {user}" : "{actor} usuwa udostępnienie dla użytkownika {user}", + "Shared by %1$s" : "Udostępnione przez użytkownika %1$s", + "Shared by {actor}" : "Udostępnione przez użytkownika {actor}", + "%1$s removed share" : "%1$s usunął udostępnienie", + "{actor} removed share" : "{actor} usunął udostępnienie", + "You shared %1$s with %2$s" : "Współdzielisz %1$s z %2$s", + "You shared {file} with {user}" : "Współdzielisz {file} z {user}", + "You removed %2$s from %1$s" : "Usunąłeś użytkownika %2$s z %1$s", + "You removed {user} from {file}" : "Usunąłeś użytkownika {user} z {file}", + "%3$s shared %1$s with %2$s" : "%3$s udostępnił %1$s użytkownikowi %2$s", + "{actor} removed {user} from {file}" : "{actor} usunął użytkownika {user} z {file}", + "%3$s removed %2$s from %1$s" : "%3$s usunął użytkownika %2$s z %1$s", + "%2$s shared %1$s with you" : "%2$s współdzieli %1$s z Tobą", + "{actor} shared {file} with you" : "{actor} udostępnił ci {file}", + "%2$s removed you from %1$s" : "%2$s usunął cię z %1$s", + "{actor} removed you from {file}" : "{actor} usunął cie z {file}", + "A file or folder shared by mail or by public link was <strong>downloaded</strong>" : "Plik lub folder udostępniony za pomocą maila lub publicznego łącza został <strong>pobrany</strong>", + "A file or folder was shared from <strong>another server</strong>" : "Plik lub folder został udostępniony z <strong>innego serwera</strong>", + "A file or folder has been <strong>shared</strong>" : "Plik lub folder stał się <strong>współdzielony</strong>", + "Wrong share ID, share doesn't exist" : "Złe ID udziału, udział nie istnieje", + "could not delete share" : "nie można usunąć udział", + "Could not delete share" : "Nie można usunąć udział", + "Please specify a file or folder path" : "Proszę podać pliku lub ścieżkę do folderu", + "Wrong path, file/folder doesn't exist" : "Ścieżka nieprawidłowa, plik/folder nie istnieje", + "Could not create share" : "Nie można utworzyć udział", + "invalid permissions" : "nieprawidłowe uprawnienia", + "Please specify a valid user" : "Proszę podać poprawnego użytkownika", + "Group sharing is disabled by the administrator" : "Udostępnianie grupy zostało wyłączone przez administratora", + "Please specify a valid group" : "Proszę podać prawidłową grupę", "Public link sharing is disabled by the administrator" : "Udostępnianie linków publicznych zostało zablokowane przez twojego administratora", "Public upload disabled by the administrator" : "Publiczne wczytywanie zostało zablokowane przez twojego administratora", "Public upload is only possible for publicly shared folders" : "Publiczne wczytywanie jest możliwe wyłącznie do katalogów publicznych", - "A file or folder has been <strong>shared</strong>" : "Plik lub folder stał się <strong>współdzielony</strong>", - "You shared %1$s with %2$s" : "Współdzielisz %1$s z %2$s", - "You shared %1$s with group %2$s" : "Współdzielisz %1$s z grupą %2$s", - "You shared %1$s via link" : "Udostępniasz %1$s przez link", - "%2$s shared %1$s with you" : "%2$s współdzieli %1$s z Tobą", - "%2$s removed the share for %1$s" : "%2$s usunął udział dla %1$s", - "Shares" : "Udziały", + "Invalid date, date format must be YYYY-MM-DD" : "Nieprawidłowa data, format daty musi być YYYY-MM-DD", + "Sharing %s failed because the back end does not allow shares from type %s" : "Udostępnienie %s nie powiodło się ponieważ backend nie zezwala na udziały typu %s", + "Unknown share type" : "Nieznany typ udziału", + "Not a directory" : "Nie jest katalogiem", + "Could not lock path" : "Nie udało się zablokować ścieżki", + "Wrong or no update parameter given" : "Brakujący lub błędny parametr aktualizacji", + "Can't change permissions for public share links" : "Nie można zmienić uprawnień dla publicznych udziałów", + "Cannot increase permissions" : "Nie można zwiększyć uprawnień", + "%s is publicly shared" : "%s jest publicznie dostępny", + "Share API is disabled" : "API udostępniania jest wyłączone", "This share is password-protected" : "Udział ten jest chroniony hasłem", "The password is wrong. Try again." : "To hasło jest niewłaściwe. Spróbuj ponownie.", "Password" : "Hasło", "No entries found in this folder" : "Brak wpisów w tym folderze", "Name" : "Nazwa", "Share time" : "Czas współdzielenia", + "Expiration date" : "Data wygaśnięcia", "Sorry, this link doesn’t seem to work anymore." : "Przepraszamy ale wygląda na to, że ten link już nie działa.", "Reasons might be:" : "Możliwe powody:", "the item was removed" : "element został usunięty", "the link expired" : "link wygasł", "sharing is disabled" : "udostępnianie jest wyłączone", "For more info, please ask the person who sent this link." : "Aby uzyskać więcej informacji proszę poprosić osobę, która wysłał ten link.", - "Add to your ownCloud" : "Dodaj do twojego ownCloud", + "Add to your Nextcloud" : "Dodaj do swojego Nextcloud", "Download" : "Pobierz", "Download %s" : "Pobierz %s", - "Direct link" : "Bezpośredni link" + "Direct link" : "Bezpośredni link", + "Upload files to %s" : "Prześlij pliki do %s", + "Select or drop files" : "Wybierz i upuść pliki", + "Uploading files…" : "Wysyłanie plików...", + "Uploaded files:" : "Wysłane pliki:", + "A public shared file or folder was <strong>downloaded</strong>" : "Publicznie udostępniony plik lub katalog został <strong>pobrany</strong>", + "You received a new remote share %2$s from %1$s" : "Otrzymałeś nowy udział zdalny %2$s z %1$s", + "You received a new remote share from %s" : "Otrzymałeś nowy zdalny udział z %s", + "%1$s accepted remote share %2$s" : "%1$s zaakceptował zdalny udział %2$s", + "%1$s declined remote share %2$s" : "%1$s odrzucił zdalny udział %2$s", + "%1$s unshared %2$s from you" : "%1$s zakończył udostępnianie Ci %2$s", + "Public shared folder %1$s was downloaded" : "Udostępniony publicznie folder %1$s został pobrany", + "Public shared file %1$s was downloaded" : "Udostępniony publicznie plik %1$s został pobrany", + "%2$s shared %1$s with %3$s" : "%2$s udostępnił %1$s użytkownikowi %3$s", + "You removed the share of %2$s for %1$s" : "Zakończyłeś udostępnianie %2$s użytkownikowi %1$s", + "%2$s removed the share of %3$s for %1$s" : "%2$s zakończył udostępnianie %3$s użytkownikowi %1$s", + "%2$s shared %1$s with group %3$s" : "%2$s udostępnił %1$s grupie %3$s", + "%2$s shared %1$s via link" : "%2$s udostępnił %1$s poprzez łącze", + "You shared %1$s via link" : "Udostępniasz %1$s przez link", + "Your public link for %1$s expired" : "Twoje publiczne łącze do %1$s wygasło", + "%2$s removed the share for %1$s" : "%2$s usunął udział dla %1$s", + "Shared with %2$s" : "Współdzielone z %2$s", + "Shared with %3$s by %2$s" : "Udostępniono użytkownikowi %3$s przez %2$s", + "Shared with group %2$s" : "Udostępniono grupie %2$s", + "Shared with group %3$s by %2$s" : "Udostępniono grupie %3$s przez użytkownika %2$s", + "Shared via link by %2$s" : "Udostępniono za pomocą łącza przez użytkownika %2$s", + "Shared via public link" : "Udostępniono przez publiczne łącze", + "%2$s removed public link" : "%2$s usunął publiczne łącze", + "Public link expired" : "Link publiczny wygasł", + "Shared by %2$s" : "Udostępniane przez %2$s", + "Shares" : "Udziały" },"pluralForm" :"nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }
\ No newline at end of file diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index ccd0e3aa31d..6181cde6fe6 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -668,6 +668,7 @@ class ShareAPIController extends OCSController { \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE, // legacy \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE, // correct \OCP\Constants::PERMISSION_CREATE, // hidden file list + \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE, // allow to edit single files ]) ) { throw new OCSBadRequestException($this->l->t('Can\'t change permissions for public share links')); diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php index 32e4f3d3dd6..dd2ea855b0b 100644 --- a/apps/files_sharing/templates/public.php +++ b/apps/files_sharing/templates/public.php @@ -35,40 +35,35 @@ $maxUploadFilesize = min($upload_max_filesize, $post_max_size); <header><div id="header" class="<?php p((isset($_['folder']) ? 'share-folder' : 'share-file')) ?>"> - <a href="<?php print_unescaped(link_to('', 'index.php')); ?>" - title="" id="nextcloud"> - <div class="logo-icon svg"> - </div> - </a> - - <div class="header-appname-container"> - <h1 class="header-appname"> - <?php p($theme->getName()); ?> - </h1> + <div id="header-left"> + <a href="<?php print_unescaped(link_to('', 'index.php')); ?>" + title="" id="nextcloud"> + <div class="logo-icon svg"></div> + <h1 class="header-appname"> + <?php p($theme->getName()); ?> + </h1> + </a> </div> <div id="logo-claim" style="display:none;"><?php p($theme->getLogoClaim()); ?></div> - <div class="header-right"> - <span id="details"> - <?php - if (!isset($_['hideFileList']) || (isset($_['hideFileList']) && $_['hideFileList'] === false)) { - if ($_['server2serversharing']) { - ?> - <span id="save" data-protected="<?php p($_['protected']) ?>" - data-owner-display-name="<?php p($_['displayName']) ?>" data-owner="<?php p($_['owner']) ?>" data-name="<?php p($_['filename']) ?>"> - <button id="save-button"><?php p($l->t('Add to your Nextcloud')) ?></button> - <form class="save-form hidden" action="#"> - <input type="text" id="remote_address" placeholder="user@yourNextcloud.org"/> - <button id="save-button-confirm" class="icon-confirm svg" disabled></button> - </form> - </span> - <?php } ?> - <a href="<?php p($_['downloadURL']); ?>" id="download" class="button"> - <img class="svg" alt="" src="<?php print_unescaped(image_path("core", "actions/download.svg")); ?>"/> - <span id="download-text"><?php p($l->t('Download'))?></span> - </a> + <div id="header-right"> + <?php if (!isset($_['hideFileList']) || (isset($_['hideFileList']) && $_['hideFileList'] === false)) { + if ($_['server2serversharing']) { + ?> + <span id="save" data-protected="<?php p($_['protected']) ?>" + data-owner-display-name="<?php p($_['displayName']) ?>" data-owner="<?php p($_['owner']) ?>" data-name="<?php p($_['filename']) ?>"> + <button id="save-button"><?php p($l->t('Add to your Nextcloud')) ?></button> + <form class="save-form hidden" action="#"> + <input type="email" id="remote_address" placeholder="user@yourNextcloud.org"/> + <button id="save-button-confirm" class="icon-confirm svg" disabled></button> + </form> + </span> <?php } ?> - </span> + <a href="<?php p($_['downloadURL']); ?>" id="download" class="button"> + <span class="icon icon-download"></span> + <span id="download-text"><?php p($l->t('Download'))?></span> + </a> + <?php } ?> </div> </div></header> <div id="content-wrapper"> @@ -89,8 +84,8 @@ $maxUploadFilesize = min($upload_max_filesize, $post_max_size); <div id="imgframe"></div> <?php endif; ?> <div class="directDownload"> - <a href="<?php p($_['downloadURL']); ?>" id="downloadFile" class="button"> - <img class="svg" alt="" src="<?php print_unescaped(image_path("core", "actions/download.svg")); ?>"/> + <a href="<?php p($_['downloadURL']); ?>" id="downloadFile" class="button primary"> + <span class="icon icon-download"></span> <?php p($l->t('Download %s', array($_['filename'])))?> (<?php p($_['fileSize']) ?>) </a> </div> diff --git a/apps/provisioning_api/appinfo/routes.php b/apps/provisioning_api/appinfo/routes.php index 04a34fba903..baa4e475be8 100644 --- a/apps/provisioning_api/appinfo/routes.php +++ b/apps/provisioning_api/appinfo/routes.php @@ -45,6 +45,7 @@ return [ ['root' => '/cloud', 'name' => 'Users#getUsers', 'url' => '/users', 'verb' => 'GET'], ['root' => '/cloud', 'name' => 'Users#addUser', 'url' => '/users', 'verb' => 'POST'], ['root' => '/cloud', 'name' => 'Users#getUser', 'url' => '/users/{userId}', 'verb' => 'GET'], + ['root' => '/cloud', 'name' => 'Users#getCurrentUser', 'url' => '/user', 'verb' => 'GET'], ['root' => '/cloud', 'name' => 'Users#editUser', 'url' => '/users/{userId}', 'verb' => 'PUT'], ['root' => '/cloud', 'name' => 'Users#deleteUser', 'url' => '/users/{userId}', 'verb' => 'DELETE'], ['root' => '/cloud', 'name' => 'Users#enableUser', 'url' => '/users/{userId}/enable', 'verb' => 'PUT'], diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index cc1d63d2d34..45839cf4f8d 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -29,14 +29,15 @@ namespace OCA\Provisioning_API\Controller; +use OC\Accounts\AccountManager; use \OC_Helper; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSException; use OCP\AppFramework\OCS\OCSForbiddenException; -use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\AppFramework\OCSController; use OCP\Files\NotFoundException; use OCP\IConfig; +use OCP\IGroup; use OCP\IGroupManager; use OCP\ILogger; use OCP\IRequest; @@ -53,6 +54,8 @@ class UsersController extends OCSController { private $groupManager; /** @var IUserSession */ private $userSession; + /** @var AccountManager */ + private $accountManager; /** @var ILogger */ private $logger; @@ -63,6 +66,7 @@ class UsersController extends OCSController { * @param IConfig $config * @param IGroupManager $groupManager * @param IUserSession $userSession + * @param AccountManager $accountManager * @param ILogger $logger */ public function __construct($appName, @@ -71,6 +75,7 @@ class UsersController extends OCSController { IConfig $config, IGroupManager $groupManager, IUserSession $userSession, + AccountManager $accountManager, ILogger $logger) { parent::__construct($appName, $request); @@ -78,6 +83,7 @@ class UsersController extends OCSController { $this->config = $config; $this->groupManager = $groupManager; $this->userSession = $userSession; + $this->accountManager = $accountManager; $this->logger = $logger; } @@ -107,7 +113,7 @@ class UsersController extends OCSController { } if($offset === null) { - $offset = 0; + $offset = 0; } $users = []; @@ -159,7 +165,7 @@ class UsersController extends OCSController { throw new OCSException('no group specified (required for subadmins)', 106); } } - + try { $newUser = $this->userManager->createUser($userid, $password); $this->logger->info('Successful addUser call with userid: '.$userid, ['app' => 'ocs_api']); @@ -209,10 +215,17 @@ class UsersController extends OCSController { } } + $userAccount = $this->accountManager->getUser($targetUserObject); + // Find the data + $data['id'] = $targetUserObject->getUID(); $data['quota'] = $this->fillStorageInfo($userId); $data['email'] = $targetUserObject->getEMailAddress(); $data['displayname'] = $targetUserObject->getDisplayName(); + $data['phone'] = $userAccount[\OC\Accounts\AccountManager::PROPERTY_PHONE]['value']; + $data['address'] = $userAccount[\OC\Accounts\AccountManager::PROPERTY_ADDRESS]['value']; + $data['webpage'] = $userAccount[\OC\Accounts\AccountManager::PROPERTY_WEBSITE]['value']; + $data['twitter'] = $userAccount[\OC\Accounts\AccountManager::PROPERTY_TWITTER]['value']; return new DataResponse($data); } @@ -220,6 +233,30 @@ class UsersController extends OCSController { /** * @NoAdminRequired * @NoSubAdminRequired + * + * gets user info from the currently logged in user + * + * @return DataResponse + * @throws OCSException + */ + public function getCurrentUser() { + $user = $this->userSession->getUser(); + if ($user) { + $result = $this->getUser($user->getUID()); + // rename "displayname" to "display-name" only for this call to keep + // the API stable. + $result['display-name'] = $result['displayname']; + unset($result['displayname']); + return $result; + + } + + throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED); + } + + /** + * @NoAdminRequired + * @NoSubAdminRequired * @PasswordConfirmationRequired * * edit users @@ -275,9 +312,9 @@ class UsersController extends OCSController { break; case 'quota': $quota = $value; - if($quota !== 'none' and $quota !== 'default') { + if($quota !== 'none' && $quota !== 'default') { if (is_numeric($quota)) { - $quota = floatval($quota); + $quota = (float) $quota; } else { $quota = \OCP\Util::computerFileSize($quota); } @@ -421,6 +458,7 @@ class UsersController extends OCSController { // Looking up someone else if($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) { // Return the group that the method caller is subadmin of for the user in question + /** @var IGroup[] $getSubAdminsGroups */ $getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser); foreach ($getSubAdminsGroups as $key => $group) { $getSubAdminsGroups[$key] = $group->getGID(); @@ -435,11 +473,13 @@ class UsersController extends OCSController { throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED); } } - + } /** * @PasswordConfirmationRequired + * @NoAdminRequired + * * @param string $userId * @param string $groupid * @return DataResponse @@ -459,6 +499,13 @@ class UsersController extends OCSController { throw new OCSException('', 103); } + // If they're not an admin, check they are a subadmin of the group in question + $loggedInUser = $this->userSession->getUser(); + $subAdminManager = $this->groupManager->getSubAdmin(); + if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) { + throw new OCSException('', 104); + } + // Add user to group $group->addUser($targetUser); return new DataResponse(); @@ -492,25 +539,33 @@ class UsersController extends OCSController { // If they're not an admin, check they are a subadmin of the group in question $subAdminManager = $this->groupManager->getSubAdmin(); - if(!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminofGroup($loggedInUser, $group)) { + if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) { throw new OCSException('', 104); } + // Check they aren't removing themselves from 'admin' or their 'subadmin; group - if($userId === $loggedInUser->getUID()) { - if($this->groupManager->isAdmin($loggedInUser->getUID())) { - if($group->getGID() === 'admin') { + if ($userId === $loggedInUser->getUID()) { + if ($this->groupManager->isAdmin($loggedInUser->getUID())) { + if ($group->getGID() === 'admin') { throw new OCSException('Cannot remove yourself from the admin group', 105); } } else { - // Not an admin, check they are not removing themself from their subadmin group - $subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser); - foreach ($subAdminGroups as $key => $group) { - $subAdminGroups[$key] = $group->getGID(); - } + // Not an admin, so the user must be a subadmin of this group, but that is not allowed. + throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105); + } - if(in_array($group->getGID(), $subAdminGroups, true)) { - throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105); - } + } else if (!$this->groupManager->isAdmin($loggedInUser->getUID())) { + /** @var IGroup[] $subAdminGroups */ + $subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser); + $subAdminGroups = array_map(function (IGroup $subAdminGroup) { + return $subAdminGroup->getGID(); + }, $subAdminGroups); + $userGroups = $this->groupManager->getUserGroupIds($targetUser); + $userSubAdminGroups = array_intersect($subAdminGroups, $userGroups); + + if (count($userSubAdminGroups) <= 1) { + // Subadmin must not be able to remove a user from all their subadmin groups. + throw new OCSException('Cannot remove user from this group as this is the only remaining group you are a SubAdmin of', 105); } } diff --git a/apps/provisioning_api/tests/Controller/UsersControllerTest.php b/apps/provisioning_api/tests/Controller/UsersControllerTest.php index e04ee86feae..52f7f391c97 100644 --- a/apps/provisioning_api/tests/Controller/UsersControllerTest.php +++ b/apps/provisioning_api/tests/Controller/UsersControllerTest.php @@ -29,7 +29,12 @@ namespace OCA\Provisioning_API\Tests\Controller; +use OC\Accounts\AccountManager; use OCA\Provisioning_API\Controller\UsersController; +use OCP\AppFramework\Http\DataResponse; +use OCP\IGroup; +use OCP\IRequest; +use OCP\IUser; use OCP\IUserManager; use OCP\IConfig; use OCP\IUserSession; @@ -38,7 +43,7 @@ use Test\TestCase as OriginalTest; use OCP\ILogger; class UsersControllerTest extends OriginalTest { - + /** @var IUserManager | PHPUnit_Framework_MockObject_MockObject */ protected $userManager; /** @var IConfig | PHPUnit_Framework_MockObject_MockObject */ @@ -51,6 +56,10 @@ class UsersControllerTest extends OriginalTest { protected $logger; /** @var UsersController | PHPUnit_Framework_MockObject_MockObject */ protected $api; + /** @var AccountManager | PHPUnit_Framework_MockObject_MockObject */ + protected $accountManager; + /** @var IRequest | PHPUnit_Framework_MockObject_MockObject */ + protected $request; protected function tearDown() { parent::tearDown(); @@ -74,17 +83,21 @@ class UsersControllerTest extends OriginalTest { $this->logger = $this->getMockBuilder('OCP\ILogger') ->disableOriginalConstructor() ->getMock(); - $request = $this->getMockBuilder('OCP\IRequest') + $this->request = $this->getMockBuilder('OCP\IRequest') + ->disableOriginalConstructor() + ->getMock(); + $this->accountManager = $this->getMockBuilder(AccountManager::class) ->disableOriginalConstructor() ->getMock(); $this->api = $this->getMockBuilder('OCA\Provisioning_API\Controller\UsersController') ->setConstructorArgs([ 'provisioning_api', - $request, + $this->request, $this->userManager, $this->config, $this->groupManager, $this->userSession, + $this->accountManager, $this->logger, ]) ->setMethods(['fillStorageInfo']) @@ -649,6 +662,16 @@ class UsersControllerTest extends OriginalTest { ->method('isAdmin') ->with('admin') ->will($this->returnValue(true)); + $this->accountManager->expects($this->any())->method('getUser') + ->with($targetUser) + ->willReturn( + [ + AccountManager::PROPERTY_ADDRESS => ['value' => 'address'], + AccountManager::PROPERTY_PHONE => ['value' => 'phone'], + AccountManager::PROPERTY_TWITTER => ['value' => 'twitter'], + AccountManager::PROPERTY_WEBSITE => ['value' => 'website'], + ] + ); $this->config ->expects($this->at(0)) ->method('getUserValue') @@ -663,12 +686,21 @@ class UsersControllerTest extends OriginalTest { ->expects($this->once()) ->method('getDisplayName') ->will($this->returnValue('Demo User')); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UID')); $expected = [ + 'id' => 'UID', 'enabled' => 'true', 'quota' => ['DummyValue'], 'email' => 'demo@owncloud.org', 'displayname' => 'Demo User', + 'phone' => 'phone', + 'address' => 'address', + 'webpage' => 'website', + 'twitter' => 'twitter' ]; $this->assertEquals($expected, $this->api->getUser('UserToGet')->getData()); } @@ -728,12 +760,31 @@ class UsersControllerTest extends OriginalTest { ->expects($this->once()) ->method('getDisplayName') ->will($this->returnValue('Demo User')); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UID')); + $this->accountManager->expects($this->any())->method('getUser') + ->with($targetUser) + ->willReturn( + [ + AccountManager::PROPERTY_ADDRESS => ['value' => 'address'], + AccountManager::PROPERTY_PHONE => ['value' => 'phone'], + AccountManager::PROPERTY_TWITTER => ['value' => 'twitter'], + AccountManager::PROPERTY_WEBSITE => ['value' => 'website'], + ] + ); $expected = [ + 'id' => 'UID', 'enabled' => 'true', 'quota' => ['DummyValue'], 'email' => 'demo@owncloud.org', 'displayname' => 'Demo User', + 'phone' => 'phone', + 'address' => 'address', + 'webpage' => 'website', + 'twitter' => 'twitter' ]; $this->assertEquals($expected, $this->api->getUser('UserToGet')->getData()); } @@ -834,11 +885,30 @@ class UsersControllerTest extends OriginalTest { ->expects($this->once()) ->method('getEMailAddress') ->will($this->returnValue('subadmin@owncloud.org')); + $targetUser + ->expects($this->once()) + ->method('getUID') + ->will($this->returnValue('UID')); + $this->accountManager->expects($this->any())->method('getUser') + ->with($targetUser) + ->willReturn( + [ + AccountManager::PROPERTY_ADDRESS => ['value' => 'address'], + AccountManager::PROPERTY_PHONE => ['value' => 'phone'], + AccountManager::PROPERTY_TWITTER => ['value' => 'twitter'], + AccountManager::PROPERTY_WEBSITE => ['value' => 'website'], + ] + ); $expected = [ + 'id' => 'UID', 'quota' => ['DummyValue'], 'email' => 'subadmin@owncloud.org', 'displayname' => 'Subadmin User', + 'phone' => 'phone', + 'address' => 'address', + 'webpage' => 'website', + 'twitter' => 'twitter' ]; $this->assertEquals($expected, $this->api->getUser('subadmin')->getData()); } @@ -1598,11 +1668,10 @@ class UsersControllerTest extends OriginalTest { * @expectedExceptionCode 102 */ public function testAddToGroupWithTargetGroupNotExisting() { - $this->groupManager - ->expects($this->once()) + $this->groupManager->expects($this->once()) ->method('get') ->with('GroupToAddTo') - ->will($this->returnValue(null)); + ->willReturn(null); $this->api->addToGroup('TargetUser', 'GroupToAddTo'); } @@ -1620,18 +1689,151 @@ class UsersControllerTest extends OriginalTest { * @expectedExceptionCode 103 */ public function testAddToGroupWithTargetUserNotExisting() { - $targetGroup = $this->getMockBuilder('\OCP\IGroup')->disableOriginalConstructor()->getMock(); - $this->groupManager - ->expects($this->once()) + $targetGroup = $this->createMock(IGroup::class); + $this->groupManager->expects($this->once()) ->method('get') ->with('GroupToAddTo') - ->will($this->returnValue($targetGroup)); + ->willReturn($targetGroup); $this->api->addToGroup('TargetUser', 'GroupToAddTo'); } /** * @expectedException \OCP\AppFramework\OCS\OCSException + * @expectedExceptionCode 104 + */ + public function testAddToGroupNoSubadmin() { + $targetUser = $this->createMock(IUser::class); + $loggedInUser = $this->createMock(IUser::class); + $loggedInUser->expects($this->once()) + ->method('getUID') + ->willReturn('subadmin'); + + $targetGroup = $this->createMock(IGroup::class); + $targetGroup->expects($this->never()) + ->method('addUser') + ->with($targetUser); + + $this->groupManager->expects($this->once()) + ->method('get') + ->with('GroupToAddTo') + ->willReturn($targetGroup); + + + $subAdminManager = $this->createMock(\OC\SubAdmin::class); + $subAdminManager->expects($this->once()) + ->method('isSubAdminOfGroup') + ->with($loggedInUser, $targetGroup) + ->willReturn(false); + + $this->groupManager->expects($this->once()) + ->method('getSubAdmin') + ->willReturn($subAdminManager); + $this->groupManager->expects($this->once()) + ->method('isAdmin') + ->with('subadmin') + ->willReturn(false); + + $this->userManager->expects($this->once()) + ->method('get') + ->with('TargetUser') + ->willReturn($targetUser); + + $this->userSession->expects($this->once()) + ->method('getUser') + ->willReturn($loggedInUser); + + $this->api->addToGroup('TargetUser', 'GroupToAddTo'); + } + + public function testAddToGroupSuccessAsSubadmin() { + $targetUser = $this->createMock(IUser::class); + $loggedInUser = $this->createMock(IUser::class); + $loggedInUser->expects($this->once()) + ->method('getUID') + ->willReturn('subadmin'); + + $targetGroup = $this->createMock(IGroup::class); + $targetGroup->expects($this->once()) + ->method('addUser') + ->with($targetUser); + + $this->groupManager->expects($this->once()) + ->method('get') + ->with('GroupToAddTo') + ->willReturn($targetGroup); + + + $subAdminManager = $this->createMock(\OC\SubAdmin::class); + $subAdminManager->expects($this->once()) + ->method('isSubAdminOfGroup') + ->with($loggedInUser, $targetGroup) + ->willReturn(true); + + $this->groupManager->expects($this->once()) + ->method('getSubAdmin') + ->willReturn($subAdminManager); + $this->groupManager->expects($this->once()) + ->method('isAdmin') + ->with('subadmin') + ->willReturn(false); + + $this->userManager->expects($this->once()) + ->method('get') + ->with('TargetUser') + ->willReturn($targetUser); + + $this->userSession->expects($this->once()) + ->method('getUser') + ->willReturn($loggedInUser); + + $this->assertEquals(new DataResponse(), $this->api->addToGroup('TargetUser', 'GroupToAddTo')); + } + + public function testAddToGroupSuccessAsAdmin() { + $targetUser = $this->createMock(IUser::class); + $loggedInUser = $this->createMock(IUser::class); + $loggedInUser->expects($this->once()) + ->method('getUID') + ->willReturn('admin'); + + $targetGroup = $this->createMock(IGroup::class); + $targetGroup->expects($this->once()) + ->method('addUser') + ->with($targetUser); + + $this->groupManager->expects($this->once()) + ->method('get') + ->with('GroupToAddTo') + ->willReturn($targetGroup); + + + $subAdminManager = $this->createMock(\OC\SubAdmin::class); + $subAdminManager->expects($this->never()) + ->method('isSubAdminOfGroup'); + + $this->groupManager->expects($this->once()) + ->method('getSubAdmin') + ->willReturn($subAdminManager); + $this->groupManager->expects($this->once()) + ->method('isAdmin') + ->with('admin') + ->willReturn(true); + + $this->userManager->expects($this->once()) + ->method('get') + ->with('TargetUser') + ->willReturn($targetUser); + + $this->userSession->expects($this->once()) + ->method('getUser') + ->willReturn($loggedInUser); + + $this->assertEquals(new DataResponse(), $this->api->addToGroup('TargetUser', 'GroupToAddTo')); + } + + /** + * @expectedException \OCP\AppFramework\OCS\OCSException * @expectedExceptionCode 101 */ public function testRemoveFromGroupWithNoTargetGroup() { @@ -1813,22 +2015,79 @@ class UsersControllerTest extends OriginalTest { ->method('isSubAdminofGroup') ->with($loggedInUser, $targetGroup) ->will($this->returnValue(true)); + $this->groupManager + ->expects($this->once()) + ->method('getSubAdmin') + ->will($this->returnValue($subAdminManager)); + $this->groupManager + ->expects($this->any()) + ->method('isAdmin') + ->with('subadmin') + ->will($this->returnValue(false)); + + $this->api->removeFromGroup('subadmin', 'subadmin'); + } + + /** + * @expectedException \OCP\AppFramework\OCS\OCSException + * @expectedExceptionCode 105 + * @expectedExceptionMessage Cannot remove user from this group as this is the only remaining group you are a SubAdmin of + */ + public function testRemoveFromGroupAsSubAdminFromLastSubAdminGroup() { + $loggedInUser = $this->getMockBuilder('\OCP\IUser')->disableOriginalConstructor()->getMock(); + $loggedInUser + ->expects($this->any()) + ->method('getUID') + ->will($this->returnValue('subadmin')); + $targetUser = $this->getMockBuilder('\OCP\IUser')->disableOriginalConstructor()->getMock(); + $targetGroup = $this->getMockBuilder('\OCP\IGroup')->disableOriginalConstructor()->getMock(); + $targetGroup + ->expects($this->any()) + ->method('getGID') + ->will($this->returnValue('subadmin')); + $this->userSession + ->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($loggedInUser)); + $this->groupManager + ->expects($this->once()) + ->method('get') + ->with('subadmin') + ->will($this->returnValue($targetGroup)); + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('AnotherUser') + ->will($this->returnValue($targetUser)); + $subAdminManager = $this->getMockBuilder('OC\SubAdmin') + ->disableOriginalConstructor()->getMock(); $subAdminManager ->expects($this->once()) - ->method('getSubAdminsGroups') - ->with($loggedInUser) - ->will($this->returnValue([$targetGroup])); + ->method('isSubAdminofGroup') + ->with($loggedInUser, $targetGroup) + ->will($this->returnValue(true)); $this->groupManager ->expects($this->once()) ->method('getSubAdmin') ->will($this->returnValue($subAdminManager)); + $subAdminManager + ->expects($this->once()) + ->method('getSubAdminsGroups') + ->with($loggedInUser) + ->will($this->returnValue([$targetGroup])); + $this->groupManager ->expects($this->any()) ->method('isAdmin') ->with('subadmin') ->will($this->returnValue(false)); + $this->groupManager + ->expects($this->once()) + ->method('getUserGroupIds') + ->with($targetUser) + ->willReturn(['subadmin', 'other group']); - $this->api->removeFromGroup('subadmin', 'subadmin'); + $this->api->removeFromGroup('AnotherUser', 'subadmin'); } public function testRemoveFromGroupSuccessful() { @@ -2293,4 +2552,70 @@ class UsersControllerTest extends OriginalTest { $this->assertEquals([], $this->api->disableUser('RequestedUser')->getData()); } + + public function testGetCurrentUserLoggedIn() { + + $user = $this->getMock(IUser::class); + $user->expects($this->once())->method('getUID')->willReturn('UID'); + + $this->userSession->expects($this->once())->method('getUser') + ->willReturn($user); + + /** @var UsersController | PHPUnit_Framework_MockObject_MockObject $api */ + $api = $this->getMockBuilder('OCA\Provisioning_API\Controller\UsersController') + ->setConstructorArgs([ + 'provisioning_api', + $this->request, + $this->userManager, + $this->config, + $this->groupManager, + $this->userSession, + $this->accountManager, + $this->logger, + ]) + ->setMethods(['getUser']) + ->getMock(); + + $api->expects($this->once())->method('getUser')->with('UID') + ->willReturn( + [ + 'id' => 'UID', + 'enabled' => 'true', + 'quota' => ['DummyValue'], + 'email' => 'demo@owncloud.org', + 'displayname' => 'Demo User', + 'phone' => 'phone', + 'address' => 'address', + 'webpage' => 'website', + 'twitter' => 'twitter' + ] + ); + + $expected = [ + 'id' => 'UID', + 'enabled' => 'true', + 'quota' => ['DummyValue'], + 'email' => 'demo@owncloud.org', + 'phone' => 'phone', + 'address' => 'address', + 'webpage' => 'website', + 'twitter' => 'twitter', + 'display-name' => 'Demo User' + ]; + + $this->assertSame($expected, $api->getCurrentUser()); + } + + /** + * @expectedException \OCP\AppFramework\OCS\OCSException + */ + public function testGetCurrentUserNotLoggedIn() { + + $this->userSession->expects($this->once())->method('getUser') + ->willReturn(null); + + $this->api->getCurrentUser(); + } + + } diff --git a/apps/systemtags/l10n/de.js b/apps/systemtags/l10n/de.js index 2fb855a859b..8694bb0b389 100644 --- a/apps/systemtags/l10n/de.js +++ b/apps/systemtags/l10n/de.js @@ -40,7 +40,7 @@ OC.L10N.register( "{actor} removed system tag {systemtag} from {file}" : "{actor} hat den System-Tag {systemtag} von {file} entfernt", "%s (restricted)" : "%s (eingeschränkt)", "%s (invisible)" : "%s (unsichtbar)", - "<strong>System tags</strong> for a file have been modified" : "<strong>System-Tags</strong> für eine Datei sind geändert worden", + "<strong>System tags</strong> for a file have been modified" : "<strong>System-Tags</strong> für eine Datei wurden geändert", "Collaborative tags" : "Zusammenarbeits-Tags", "Name" : "Name", "Delete" : "Löschen", diff --git a/apps/systemtags/l10n/de.json b/apps/systemtags/l10n/de.json index defb3f58a0c..9c408bb0c09 100644 --- a/apps/systemtags/l10n/de.json +++ b/apps/systemtags/l10n/de.json @@ -38,7 +38,7 @@ "{actor} removed system tag {systemtag} from {file}" : "{actor} hat den System-Tag {systemtag} von {file} entfernt", "%s (restricted)" : "%s (eingeschränkt)", "%s (invisible)" : "%s (unsichtbar)", - "<strong>System tags</strong> for a file have been modified" : "<strong>System-Tags</strong> für eine Datei sind geändert worden", + "<strong>System tags</strong> for a file have been modified" : "<strong>System-Tags</strong> für eine Datei wurden geändert", "Collaborative tags" : "Zusammenarbeits-Tags", "Name" : "Name", "Delete" : "Löschen", diff --git a/apps/systemtags/l10n/de_DE.js b/apps/systemtags/l10n/de_DE.js index 33554f5086d..69d9bce4420 100644 --- a/apps/systemtags/l10n/de_DE.js +++ b/apps/systemtags/l10n/de_DE.js @@ -40,7 +40,7 @@ OC.L10N.register( "{actor} removed system tag {systemtag} from {file}" : "{actor} hat den System-Tag {systemtag} von {file} entfernt", "%s (restricted)" : "%s (eingeschränkt)", "%s (invisible)" : "%s (unsichtbar)", - "<strong>System tags</strong> for a file have been modified" : "<strong>System-Tags</strong> für eine Datei sind geändert worden", + "<strong>System tags</strong> for a file have been modified" : "<strong>System-Tags</strong> für eine Datei wurden geändert", "Collaborative tags" : "Gemeinsame Tags", "Name" : "Name", "Delete" : "Löschen", diff --git a/apps/systemtags/l10n/de_DE.json b/apps/systemtags/l10n/de_DE.json index f1a71612dfb..1155159a066 100644 --- a/apps/systemtags/l10n/de_DE.json +++ b/apps/systemtags/l10n/de_DE.json @@ -38,7 +38,7 @@ "{actor} removed system tag {systemtag} from {file}" : "{actor} hat den System-Tag {systemtag} von {file} entfernt", "%s (restricted)" : "%s (eingeschränkt)", "%s (invisible)" : "%s (unsichtbar)", - "<strong>System tags</strong> for a file have been modified" : "<strong>System-Tags</strong> für eine Datei sind geändert worden", + "<strong>System tags</strong> for a file have been modified" : "<strong>System-Tags</strong> für eine Datei wurden geändert", "Collaborative tags" : "Gemeinsame Tags", "Name" : "Name", "Delete" : "Löschen", diff --git a/apps/systemtags/l10n/sq.js b/apps/systemtags/l10n/sq.js index 9312d671bd1..3c1c1b4f039 100644 --- a/apps/systemtags/l10n/sq.js +++ b/apps/systemtags/l10n/sq.js @@ -2,31 +2,52 @@ OC.L10N.register( "systemtags", { "Tags" : "Etiketa", + "Update" : "Përditëso", + "Create" : "Krijo", + "Select tag…" : "Përzgjidh etiketën...", "Tagged files" : "Kartela të etiketuara", "Select tags to filter by" : "Përzgjidhni etiketa sipas të cilat të bëhet filtrimi", + "No tags found" : "Asnjë etiket nuk u gjet", "Please select tags to filter by" : "Ju lutemi, përzgjidhni etiketa sipas të cilat të bëhet filtrimi", "No files found for the selected tags" : "S’u gjetën kartela për etiketat e përzgjedhura", + "Added system tag %1$s" : "U shtua etiketa %1$s e sistemit ", + "Added system tag {systemtag}" : "Tagu i shtuar i sistemit{systemtag}", + "%1$s added system tag %2$s" : "%1$s shtoi etiketën %2$s të sistemit ", + "{actor} added system tag {systemtag}" : "{actor} shtoi etiketën e sistemit {systemtag}", + "Removed system tag %1$s" : "Hoqi etiketën %1$s të sistemit ", + "Removed system tag {systemtag}" : "Hoqi etiketën e sistemit {systemtag}", + "%1$s removed system tag %2$s" : "%1$s hoqi etiketën %2$s të sistemit ", + "{actor} removed system tag {systemtag}" : "{actor} hoqi etiketën e sistemit {systemtag}", + "You created system tag %1$s" : "Ju krijuat etiketën %1$s të sistemit", + "%1$s created system tag %2$s" : "%1$s krijoi etiketën e sistemit %2$s", + "You deleted system tag %1$s" : "Ju fshit etiketën %1$s të sistemit", + "You deleted system tag {systemtag}" : "Ju fshit etiketën {systemtag} të sistemit", + "%1$s deleted system tag %2$s" : "%1$s fshiu etiketën e sistemit %2$s", + "{actor} deleted system tag {systemtag}" : "{actor} fshiu etiketën {systemtag} të sistemit", + "You updated system tag %2$s to %1$s" : "Ju përditësuat etiketën e sistemit nga %2$s në %1$s", + "You updated system tag {oldsystemtag} to {newsystemtag}" : "Ju përditësuat etiketën e sistemit nga {oldsystemtag} në {newsystemtag}", + "%1$s updated system tag %3$s to %2$s" : "%1$s përditësoi etiketën e sistemit %3$s si %2$s", + "You added system tag %2$s to %1$s" : "Ju shtuat tagun e sistemit%2$s në %1$s", + "You added system tag {systemtag} to {file}" : "Ju shtuat tagun e sistemit{systemtag} në{file}", + "You removed system tag {systemtag} from {file}" : "Hoqët etiketën e sistemit {systemtag} nga {file}", + "%s (restricted)" : "%s (e kufizuar)", + "%s (invisible)" : "%s (e padukshme)", "<strong>System tags</strong> for a file have been modified" : "U ndryshyan <strong>etiketa sistemi</strong>për një kartelë", + "Name" : "Emër", + "No files in here" : "S’ka kartela këtu", + "No entries found in this folder" : "S’u gjetën zëra në këtë dosje", + "Size" : "Madhësi", + "Modified" : "Ndryshuar më", "You assigned system tag %3$s" : "Caktuat etiketën e sistemit %3$s", "%1$s assigned system tag %3$s" : "%1$s caktoi etiketën e sistemit %3$s", "You unassigned system tag %3$s" : "I hoqët etiketën e sistemit %3$s", "%1$s unassigned system tag %3$s" : "%1$s e hoqi %3$s si etiketë sistemi", "You created system tag %2$s" : "Krijuat etiketën e sistemit %2$s", - "%1$s created system tag %2$s" : "%1$s krijoi etiketën e sistemit %2$s", "You deleted system tag %2$s" : "Fshitë etiketën e sistemit %2$s", - "%1$s deleted system tag %2$s" : "%1$s fshiu etiketën e sistemit %2$s", "You updated system tag %3$s to %2$s" : "Përditësuat etiketën e sistemit %3$s në %2$s", - "%1$s updated system tag %3$s to %2$s" : "%1$s përditësoi etiketën e sistemit %3$s si %2$s", "You assigned system tag %3$s to %2$s" : "Caktuat etiketë sistemi %3$s për %2$s", "%1$s assigned system tag %3$s to %2$s" : "%1$s caktoi etiketën e sistemit %3$s si %2$s", "You unassigned system tag %3$s from %2$s" : "I hoqët %2$s etiketën e sistemit %3$s", - "%1$s unassigned system tag %3$s from %2$s" : "%1$s hoqi prej %2$s etiketën e sistemit %3$s", - "%s (restricted)" : "%s (e kufizuar)", - "%s (invisible)" : "%s (e padukshme)", - "Name" : "Emër", - "No files in here" : "S’ka kartela këtu", - "No entries found in this folder" : "S’u gjetën zëra në këtë dosje", - "Size" : "Madhësi", - "Modified" : "Ndryshuar më" + "%1$s unassigned system tag %3$s from %2$s" : "%1$s hoqi prej %2$s etiketën e sistemit %3$s" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/systemtags/l10n/sq.json b/apps/systemtags/l10n/sq.json index eed88992e5a..31b30a1ffa3 100644 --- a/apps/systemtags/l10n/sq.json +++ b/apps/systemtags/l10n/sq.json @@ -1,30 +1,51 @@ { "translations": { "Tags" : "Etiketa", + "Update" : "Përditëso", + "Create" : "Krijo", + "Select tag…" : "Përzgjidh etiketën...", "Tagged files" : "Kartela të etiketuara", "Select tags to filter by" : "Përzgjidhni etiketa sipas të cilat të bëhet filtrimi", + "No tags found" : "Asnjë etiket nuk u gjet", "Please select tags to filter by" : "Ju lutemi, përzgjidhni etiketa sipas të cilat të bëhet filtrimi", "No files found for the selected tags" : "S’u gjetën kartela për etiketat e përzgjedhura", + "Added system tag %1$s" : "U shtua etiketa %1$s e sistemit ", + "Added system tag {systemtag}" : "Tagu i shtuar i sistemit{systemtag}", + "%1$s added system tag %2$s" : "%1$s shtoi etiketën %2$s të sistemit ", + "{actor} added system tag {systemtag}" : "{actor} shtoi etiketën e sistemit {systemtag}", + "Removed system tag %1$s" : "Hoqi etiketën %1$s të sistemit ", + "Removed system tag {systemtag}" : "Hoqi etiketën e sistemit {systemtag}", + "%1$s removed system tag %2$s" : "%1$s hoqi etiketën %2$s të sistemit ", + "{actor} removed system tag {systemtag}" : "{actor} hoqi etiketën e sistemit {systemtag}", + "You created system tag %1$s" : "Ju krijuat etiketën %1$s të sistemit", + "%1$s created system tag %2$s" : "%1$s krijoi etiketën e sistemit %2$s", + "You deleted system tag %1$s" : "Ju fshit etiketën %1$s të sistemit", + "You deleted system tag {systemtag}" : "Ju fshit etiketën {systemtag} të sistemit", + "%1$s deleted system tag %2$s" : "%1$s fshiu etiketën e sistemit %2$s", + "{actor} deleted system tag {systemtag}" : "{actor} fshiu etiketën {systemtag} të sistemit", + "You updated system tag %2$s to %1$s" : "Ju përditësuat etiketën e sistemit nga %2$s në %1$s", + "You updated system tag {oldsystemtag} to {newsystemtag}" : "Ju përditësuat etiketën e sistemit nga {oldsystemtag} në {newsystemtag}", + "%1$s updated system tag %3$s to %2$s" : "%1$s përditësoi etiketën e sistemit %3$s si %2$s", + "You added system tag %2$s to %1$s" : "Ju shtuat tagun e sistemit%2$s në %1$s", + "You added system tag {systemtag} to {file}" : "Ju shtuat tagun e sistemit{systemtag} në{file}", + "You removed system tag {systemtag} from {file}" : "Hoqët etiketën e sistemit {systemtag} nga {file}", + "%s (restricted)" : "%s (e kufizuar)", + "%s (invisible)" : "%s (e padukshme)", "<strong>System tags</strong> for a file have been modified" : "U ndryshyan <strong>etiketa sistemi</strong>për një kartelë", + "Name" : "Emër", + "No files in here" : "S’ka kartela këtu", + "No entries found in this folder" : "S’u gjetën zëra në këtë dosje", + "Size" : "Madhësi", + "Modified" : "Ndryshuar më", "You assigned system tag %3$s" : "Caktuat etiketën e sistemit %3$s", "%1$s assigned system tag %3$s" : "%1$s caktoi etiketën e sistemit %3$s", "You unassigned system tag %3$s" : "I hoqët etiketën e sistemit %3$s", "%1$s unassigned system tag %3$s" : "%1$s e hoqi %3$s si etiketë sistemi", "You created system tag %2$s" : "Krijuat etiketën e sistemit %2$s", - "%1$s created system tag %2$s" : "%1$s krijoi etiketën e sistemit %2$s", "You deleted system tag %2$s" : "Fshitë etiketën e sistemit %2$s", - "%1$s deleted system tag %2$s" : "%1$s fshiu etiketën e sistemit %2$s", "You updated system tag %3$s to %2$s" : "Përditësuat etiketën e sistemit %3$s në %2$s", - "%1$s updated system tag %3$s to %2$s" : "%1$s përditësoi etiketën e sistemit %3$s si %2$s", "You assigned system tag %3$s to %2$s" : "Caktuat etiketë sistemi %3$s për %2$s", "%1$s assigned system tag %3$s to %2$s" : "%1$s caktoi etiketën e sistemit %3$s si %2$s", "You unassigned system tag %3$s from %2$s" : "I hoqët %2$s etiketën e sistemit %3$s", - "%1$s unassigned system tag %3$s from %2$s" : "%1$s hoqi prej %2$s etiketën e sistemit %3$s", - "%s (restricted)" : "%s (e kufizuar)", - "%s (invisible)" : "%s (e padukshme)", - "Name" : "Emër", - "No files in here" : "S’ka kartela këtu", - "No entries found in this folder" : "S’u gjetën zëra në këtë dosje", - "Size" : "Madhësi", - "Modified" : "Ndryshuar më" + "%1$s unassigned system tag %3$s from %2$s" : "%1$s hoqi prej %2$s etiketën e sistemit %3$s" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/theming/img/app-dark.svg b/apps/theming/img/app-dark.svg new file mode 100644 index 00000000000..adf97966c41 --- /dev/null +++ b/apps/theming/img/app-dark.svg @@ -0,0 +1 @@ +<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.707 11.412l-.587-.587-.03-.03a.513.513 0 0 1-.074-.526L13.07 3.4l-1.5-1.498-.15.15-.708-.706.505-.505a.538.538 0 0 1 .224-.128c.04-.01.05-.01.087-.016h.087c.04.006.05.006.086.016.072.02.134.055.192.1.74.676 1.42 1.415 2.127 2.124a.503.503 0 0 1 .103.556l-3.053 6.87.344.343.49-.49 3.01 3.01a1.192 1.192 0 0 1-1.685 1.686l-3.012-3.01.49-.488zm-.533-10.217a.986.986 0 0 0-1.396 0l-7.582 7.58a.99.99 0 0 0 0 1.398l1.397 1.396a.986.986 0 0 0 1.396 0l7.58-7.583a.988.988 0 0 0 0-1.396l-1.396-1.395z" fill="#000"/></svg> diff --git a/apps/theming/lib/Controller/ThemingController.php b/apps/theming/lib/Controller/ThemingController.php index 73e3ed3a4b4..24ac1c7d8d5 100644 --- a/apps/theming/lib/Controller/ThemingController.php +++ b/apps/theming/lib/Controller/ThemingController.php @@ -374,6 +374,7 @@ class ThemingController extends Controller { '; $responseCss .= sprintf('.nc-theming-main-background {background-color: %s}' . "\n", $color); $responseCss .= sprintf('.nc-theming-main-text {color: %s}' . "\n", $color); + $responseCss .= sprintf('#app-navigation li:hover > a, #app-navigation li:focus > a, #app-navigation a:focus, #app-navigation .selected, #app-navigation .selected a, #app-navigation .active, #app-navigation .active a {box-shadow: inset 2px 0 %s}' . "\n", $color); } $logo = $this->config->getAppValue($this->appName, 'logoMime'); @@ -445,8 +446,7 @@ class ThemingController extends Controller { cacheBuster: ' . json_encode($cacheBusterValue). ' }; })();'; - $response = new Http\DataDisplayResponse($responseJS); - $response->addHeader('Content-type', 'text/javascript'); + $response = new DataDownloadResponse($responseJS, 'javascript', 'text/javascript'); $response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime())); $response->addHeader('Pragma', 'cache'); $response->cacheFor(3600); diff --git a/apps/theming/lib/Settings/Section.php b/apps/theming/lib/Settings/Section.php index cffbb8901c8..6078743dead 100644 --- a/apps/theming/lib/Settings/Section.php +++ b/apps/theming/lib/Settings/Section.php @@ -24,13 +24,21 @@ namespace OCA\Theming\Settings; use OCP\IL10N; -use OCP\Settings\ISection; +use OCP\IURLGenerator; +use OCP\Settings\IIconSection; -class Section implements ISection { +class Section implements IIconSection { /** @var IL10N */ private $l; + /** @var IURLGenerator */ + private $url; - public function __construct(IL10N $l) { + /** + * @param IURLGenerator $url + * @param IL10N $l + */ + public function __construct(IURLGenerator $url, IL10N $l) { + $this->url = $url; $this->l = $l; } @@ -64,4 +72,11 @@ class Section implements ISection { public function getPriority() { return 30; } + + /** + * {@inheritdoc} + */ + public function getIcon() { + return $this->url->imagePath('theming', 'app-dark.svg'); + } } diff --git a/apps/theming/templates/settings-admin.php b/apps/theming/templates/settings-admin.php index 013b3bcf34f..920b4a007da 100644 --- a/apps/theming/templates/settings-admin.php +++ b/apps/theming/templates/settings-admin.php @@ -74,7 +74,7 @@ style('theming', 'settings-admin'); <div> <form class="uploadButton inlineblock" method="post" action="<?php p($_['uploadLogoRoute']) ?>"> <input type="hidden" id="current-backgroundMime" name="current-backgroundMime" value="<?php p($_['backgroundMime']); ?>" /> - <label for="upload-login-background"><span><?php p($l->t('Log in image')) ?></span></label> + <label for="upload-login-background"><span><?php p($l->t('Login image')) ?></span></label> <input id="upload-login-background" class="upload-logo-field" name="upload-login-background" type="file"> <label for="upload-login-background" class="button icon-upload svg" id="upload-login-background" title="<?php p($l->t("Upload new login background")) ?>"></label> <div data-setting="backgroundMime" data-toggle="tooltip" data-original-title="<?php p($l->t('reset to default')); ?>" class="theme-undo icon icon-history"></div> diff --git a/apps/theming/tests/Controller/ThemingControllerTest.php b/apps/theming/tests/Controller/ThemingControllerTest.php index d42e5afb245..97a5e985860 100644 --- a/apps/theming/tests/Controller/ThemingControllerTest.php +++ b/apps/theming/tests/Controller/ThemingControllerTest.php @@ -487,6 +487,7 @@ class ThemingControllerTest extends TestCase { '; $expectedData .= sprintf('.nc-theming-main-background {background-color: %s}' . "\n", $color); $expectedData .= sprintf('.nc-theming-main-text {color: %s}' . "\n", $color); + $expectedData .= sprintf('#app-navigation li:hover > a, #app-navigation li:focus > a, #app-navigation a:focus, #app-navigation .selected, #app-navigation .selected a, #app-navigation .active, #app-navigation .active a {box-shadow: inset 2px 0 %s}' . "\n", $color); $expectedData .= '.nc-theming-contrast {color: #ffffff}' . "\n"; $expectedData .= '.icon-file,.icon-filetype-text {' . 'background-image: url(\'./img/core/filetypes/text.svg?v=0\');' . "}\n" . @@ -581,6 +582,7 @@ class ThemingControllerTest extends TestCase { '; $expectedData .= sprintf('.nc-theming-main-background {background-color: %s}' . "\n", $color); $expectedData .= sprintf('.nc-theming-main-text {color: %s}' . "\n", $color); + $expectedData .= sprintf('#app-navigation li:hover > a, #app-navigation li:focus > a, #app-navigation a:focus, #app-navigation .selected, #app-navigation .selected a, #app-navigation .active, #app-navigation .active a {box-shadow: inset 2px 0 %s}' . "\n", $color); $expectedData .= '#header .header-appname, #expandDisplayName { color: #000000; }' . "\n"; $expectedData .= '#header .icon-caret { background-image: url(\'' . \OC::$WEBROOT . '/core/img/actions/caret-dark.svg\'); }' . "\n"; $expectedData .= '.searchbox input[type="search"] { background: transparent url(\'' . \OC::$WEBROOT . '/core/img/actions/search.svg\') no-repeat 6px center; color: #000; }' . "\n"; @@ -768,6 +770,7 @@ class ThemingControllerTest extends TestCase { '; $expectedData .= sprintf('.nc-theming-main-background {background-color: %s}' . "\n", $color); $expectedData .= sprintf('.nc-theming-main-text {color: %s}' . "\n", $color); + $expectedData .= sprintf('#app-navigation li:hover > a, #app-navigation li:focus > a, #app-navigation a:focus, #app-navigation .selected, #app-navigation .selected a, #app-navigation .active, #app-navigation .active a {box-shadow: inset 2px 0 %s}' . "\n", $color); $expectedData .= sprintf( '#header .logo {' . 'background-image: url(\'./logo?v=0\');' . @@ -879,6 +882,7 @@ class ThemingControllerTest extends TestCase { '; $expectedData .= sprintf('.nc-theming-main-background {background-color: %s}' . "\n", $color); $expectedData .= sprintf('.nc-theming-main-text {color: %s}' . "\n", $color); + $expectedData .= sprintf('#app-navigation li:hover > a, #app-navigation li:focus > a, #app-navigation a:focus, #app-navigation .selected, #app-navigation .selected a, #app-navigation .active, #app-navigation .active a {box-shadow: inset 2px 0 %s}' . "\n", $color); $expectedData .= sprintf( '#header .logo {' . 'background-image: url(\'./logo?v=0\');' . @@ -910,7 +914,6 @@ class ThemingControllerTest extends TestCase { 'background-image: url(\'./img/core/filetypes/folder.svg?v=0\');' . "}\n" . '.icon-filetype-folder-drag-accept {' . 'background-image: url(\'./img/core/filetypes/folder-drag-accept.svg?v=0\')!important;' . "}\n"; - $expected = new Http\DataDownloadResponse($expectedData, 'style', 'text/css'); $expected = new Http\DataDownloadResponse($expectedData, 'style', 'text/css'); $expected->cacheFor(3600); @@ -948,8 +951,7 @@ class ThemingControllerTest extends TestCase { cacheBuster: null }; })();'; - $expected = new Http\DataDisplayResponse($expectedResponse); - $expected->addHeader("Content-type","text/javascript"); + $expected = new Http\DataDownloadResponse($expectedResponse, 'javascript', 'text/javascript'); $expected->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime())); $expected->addHeader('Pragma', 'cache'); $expected->cacheFor(3600); @@ -983,8 +985,7 @@ class ThemingControllerTest extends TestCase { cacheBuster: null }; })();'; - $expected = new Http\DataDisplayResponse($expectedResponse); - $expected->addHeader("Content-type","text/javascript"); + $expected = new Http\DataDownloadResponse($expectedResponse, 'javascript', 'text/javascript'); $expected->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime())); $expected->addHeader('Pragma', 'cache'); $expected->cacheFor(3600); diff --git a/apps/theming/tests/Settings/SectionTest.php b/apps/theming/tests/Settings/SectionTest.php index 3a3a4375236..90d1854aebf 100644 --- a/apps/theming/tests/Settings/SectionTest.php +++ b/apps/theming/tests/Settings/SectionTest.php @@ -25,19 +25,24 @@ namespace OCA\Theming\Tests\Settings; use OCA\Theming\Settings\Section; use OCP\IL10N; +use OCP\IURLGenerator; use Test\TestCase; class SectionTest extends TestCase { - /** @var IL10N */ + /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */ + private $url; + /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ private $l; /** @var Section */ private $section; public function setUp() { parent::setUp(); - $this->l = $this->getMockBuilder('\OCP\IL10N')->getMock(); + $this->url = $this->createMock(IURLGenerator::class); + $this->l = $this->createMock(IL10N::class); $this->section = new Section( + $this->url, $this->l ); } @@ -59,4 +64,13 @@ class SectionTest extends TestCase { public function testGetPriority() { $this->assertSame(30, $this->section->getPriority()); } + + public function testGetIcon() { + $this->url->expects($this->once()) + ->method('imagePath') + ->with('theming', 'app-dark.svg') + ->willReturn('icon'); + + $this->assertSame('icon', $this->section->getIcon()); + } } diff --git a/apps/twofactor_backupcodes/appinfo/app.php b/apps/twofactor_backupcodes/appinfo/app.php index 31f9b6b8eae..0cb10531360 100644 --- a/apps/twofactor_backupcodes/appinfo/app.php +++ b/apps/twofactor_backupcodes/appinfo/app.php @@ -19,4 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ + +// @codeCoverageIgnoreStart OC_App::registerPersonal('twofactor_backupcodes', 'settings/personal'); +// @codeCoverageIgnoreEnd diff --git a/apps/twofactor_backupcodes/appinfo/routes.php b/apps/twofactor_backupcodes/appinfo/routes.php index f2af12e9b45..0119bfd0b08 100644 --- a/apps/twofactor_backupcodes/appinfo/routes.php +++ b/apps/twofactor_backupcodes/appinfo/routes.php @@ -19,6 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ +// @codeCoverageIgnoreStart return [ 'routes' => [ [ @@ -33,3 +34,4 @@ return [ ], ] ]; +// @codeCoverageIgnoreEnd diff --git a/apps/twofactor_backupcodes/l10n/de.js b/apps/twofactor_backupcodes/l10n/de.js index 96e1fca0759..039b8bea68b 100644 --- a/apps/twofactor_backupcodes/l10n/de.js +++ b/apps/twofactor_backupcodes/l10n/de.js @@ -13,7 +13,7 @@ OC.L10N.register( "Two-factor authentication" : "Zwei-Faktor Authentifizierung", "You successfully logged in using two-factor authentication (%1$s)" : "Erfolgreich mittels Zwei-Faktorauthentifizierung angemeldet (%1$s)", "A login attempt using two-factor authentication failed (%1$s)" : "Ein Anmeldeversuch mittels Zwei-Faktorauthentifizierung gescheitert (%1$s)", - "You created two-factor backup codes for your account" : "Du hast Zwei-Faktor Sicherungs-Codes für Ihr Konto erstellt", + "You created two-factor backup codes for your account" : "Du hast Zwei-Faktor Sicherungs-Codes für Dein Konto erstellt", "Backup code" : "Backup-Code", "Use backup code" : "Backup-Code verwenden", "Second-factor backup codes" : "Zweitfaktor-Backup-Codes" diff --git a/apps/twofactor_backupcodes/l10n/de.json b/apps/twofactor_backupcodes/l10n/de.json index 6f582fc8bf0..6afdfa52ac4 100644 --- a/apps/twofactor_backupcodes/l10n/de.json +++ b/apps/twofactor_backupcodes/l10n/de.json @@ -11,7 +11,7 @@ "Two-factor authentication" : "Zwei-Faktor Authentifizierung", "You successfully logged in using two-factor authentication (%1$s)" : "Erfolgreich mittels Zwei-Faktorauthentifizierung angemeldet (%1$s)", "A login attempt using two-factor authentication failed (%1$s)" : "Ein Anmeldeversuch mittels Zwei-Faktorauthentifizierung gescheitert (%1$s)", - "You created two-factor backup codes for your account" : "Du hast Zwei-Faktor Sicherungs-Codes für Ihr Konto erstellt", + "You created two-factor backup codes for your account" : "Du hast Zwei-Faktor Sicherungs-Codes für Dein Konto erstellt", "Backup code" : "Backup-Code", "Use backup code" : "Backup-Code verwenden", "Second-factor backup codes" : "Zweitfaktor-Backup-Codes" diff --git a/apps/twofactor_backupcodes/lib/Activity/Provider.php b/apps/twofactor_backupcodes/lib/Activity/Provider.php index cfb16c9f8d3..9c7aaeae630 100644 --- a/apps/twofactor_backupcodes/lib/Activity/Provider.php +++ b/apps/twofactor_backupcodes/lib/Activity/Provider.php @@ -40,6 +40,11 @@ class Provider implements IProvider { /** @var ILogger */ private $logger; + /** + * @param L10nFactory $l10n + * @param IURLGenerator $urlGenerator + * @param ILogger $logger + */ public function __construct(L10nFactory $l10n, IURLGenerator $urlGenerator, ILogger $logger) { $this->logger = $logger; $this->urlGenerator = $urlGenerator; diff --git a/apps/twofactor_backupcodes/lib/Db/BackupCodeMapper.php b/apps/twofactor_backupcodes/lib/Db/BackupCodeMapper.php index f64e2e9e60b..85cc174fb6a 100644 --- a/apps/twofactor_backupcodes/lib/Db/BackupCodeMapper.php +++ b/apps/twofactor_backupcodes/lib/Db/BackupCodeMapper.php @@ -22,7 +22,6 @@ namespace OCA\TwoFactorBackupCodes\Db; use OCP\AppFramework\Db\Mapper; -use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; use OCP\IUser; diff --git a/apps/twofactor_backupcodes/lib/Service/BackupCodeStorage.php b/apps/twofactor_backupcodes/lib/Service/BackupCodeStorage.php index ecb16305e92..1cf62d18801 100644 --- a/apps/twofactor_backupcodes/lib/Service/BackupCodeStorage.php +++ b/apps/twofactor_backupcodes/lib/Service/BackupCodeStorage.php @@ -33,6 +33,8 @@ use OCP\Security\ISecureRandom; class BackupCodeStorage { + private static $CODE_LENGTH = 16; + /** @var BackupCodeMapper */ private $mapper; @@ -48,6 +50,13 @@ class BackupCodeStorage { /** @var ILogger */ private $logger; + /** + * @param BackupCodeMapper $mapper + * @param ISecureRandom $random + * @param IHasher $hasher + * @param IManager $activityManager + * @param ILogger $logger + */ public function __construct(BackupCodeMapper $mapper, ISecureRandom $random, IHasher $hasher, IManager $activityManager, ILogger $logger) { $this->mapper = $mapper; @@ -69,7 +78,7 @@ class BackupCodeStorage { $uid = $user->getUID(); foreach (range(1, min([$number, 20])) as $i) { - $code = $this->random->generate(10, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'); + $code = $this->random->generate(self::$CODE_LENGTH, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS); $dbCode = new BackupCode(); $dbCode->setUserId($uid); diff --git a/apps/twofactor_backupcodes/settings/personal.php b/apps/twofactor_backupcodes/settings/personal.php index 037516e39a3..0a018c0ff28 100644 --- a/apps/twofactor_backupcodes/settings/personal.php +++ b/apps/twofactor_backupcodes/settings/personal.php @@ -1,5 +1,6 @@ <?php - +// @codeCoverageIgnoreStart $tmpl = new \OCP\Template('twofactor_backupcodes', 'personal'); return $tmpl->fetchPage(); +// @codeCoverageIgnoreEnd diff --git a/apps/twofactor_backupcodes/tests/Unit/Activity/GenericProviderTest.php b/apps/twofactor_backupcodes/tests/Unit/Activity/GenericProviderTest.php new file mode 100644 index 00000000000..242c4ab4e8d --- /dev/null +++ b/apps/twofactor_backupcodes/tests/Unit/Activity/GenericProviderTest.php @@ -0,0 +1,132 @@ +<?php + +/** + * @author Christoph Wurst <christoph@winzerhof-wurst.at> + * @copyright Copyright (c) 2016 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * Two-factor backup codes + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\TwoFactorBackupCodes\Test\Unit\Activity; + +use InvalidArgumentException; +use OCA\TwoFactorBackupCodes\Activity\GenericProvider; +use OCP\Activity\IEvent; +use OCP\IL10N; +use OCP\ILogger; +use OCP\IURLGenerator; +use OCP\L10N\IFactory; +use PHPUnit_Framework_MockObject_MockObject; +use Test\TestCase; + +class GenericProviderTest extends TestCase { + + /** @var IL10N|PHPUnit_Framework_MockObject_MockObject */ + private $l10n; + + /** @var IURLGenerator|PHPUnit_Framework_MockObject_MockObject */ + private $urlGenerator; + + /** @var ILogger|PHPUnit_Framework_MockObject_MockObject */ + private $logger; + + /** @var GenericProvider */ + private $provider; + + protected function setUp() { + parent::setUp(); + + $this->l10n = $this->createMock(IFactory::class); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->logger = $this->createMock(ILogger::class); + + $this->provider = new GenericProvider($this->l10n, $this->urlGenerator, $this->logger); + } + + public function testParseUnrelated() { + $lang = 'ru'; + $event = $this->createMock(IEvent::class); + $event->expects($this->once()) + ->method('getType') + ->willReturn('comments'); + $this->setExpectedException(InvalidArgumentException::class); + + $this->provider->parse($lang, $event); + } + + public function subjectData() { + return [ + ['twofactor_success'], + ['twofactor_failed'], + ]; + } + + /** + * @dataProvider subjectData + */ + public function testParse($subject) { + $lang = 'ru'; + $event = $this->createMock(IEvent::class); + $l = $this->createMock(IL10N::class); + + $event->expects($this->once()) + ->method('getType') + ->willReturn('twofactor'); + $this->l10n->expects($this->once()) + ->method('get') + ->with('core', $lang) + ->willReturn($l); + $this->urlGenerator->expects($this->once()) + ->method('imagePath') + ->with('core', 'actions/password.svg') + ->willReturn('path/to/image'); + $this->urlGenerator->expects($this->once()) + ->method('getAbsoluteURL') + ->with('path/to/image') + ->willReturn('absolute/path/to/image'); + $event->expects($this->once()) + ->method('setIcon') + ->with('absolute/path/to/image'); + $event->expects($this->once()) + ->method('getSubject') + ->willReturn($subject); + $event->expects($this->once()) + ->method('setParsedSubject'); + + $this->provider->parse($lang, $event); + } + + public function testParseInvalidSubject() { + $lang = 'ru'; + $l = $this->createMock(IL10N::class); + $event = $this->createMock(IEvent::class); + + $event->expects($this->once()) + ->method('getType') + ->willReturn('twofactor'); + $this->l10n->expects($this->once()) + ->method('get') + ->with('core', $lang) + ->willReturn($l); + $event->expects($this->once()) + ->method('getSubject') + ->willReturn('unrelated'); + + $this->expectException(InvalidArgumentException::class); + $this->provider->parse($lang, $event); + } + +} diff --git a/apps/twofactor_backupcodes/tests/Unit/Activity/ProviderTest.php b/apps/twofactor_backupcodes/tests/Unit/Activity/ProviderTest.php index 36e85ec1872..e1a13c89c10 100644 --- a/apps/twofactor_backupcodes/tests/Unit/Activity/ProviderTest.php +++ b/apps/twofactor_backupcodes/tests/Unit/Activity/ProviderTest.php @@ -2,7 +2,7 @@ /** * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @copyright Copyright (c) 2016 Christoph Wurst <christoph@winzerhof-wurst.at> + * @copyright Copyright (c) 2017 Christoph Wurst <christoph@winzerhof-wurst.at> * * Two-factor backup codes * @@ -23,21 +23,27 @@ namespace OCA\TwoFactorBackupCodes\Test\Unit\Activity; use InvalidArgumentException; -use OCA\TwoFactorBackupCodes\Activity\GenericProvider; +use OCA\TwoFactorBackupCodes\Activity\Provider; use OCP\Activity\IEvent; use OCP\IL10N; use OCP\ILogger; use OCP\IURLGenerator; use OCP\L10N\IFactory; +use PHPUnit_Framework_MockObject_MockObject; use Test\TestCase; class ProviderTest extends TestCase { + /** @var IL10N|PHPUnit_Framework_MockObject_MockObject */ private $l10n; + + /** @var IURLGenerator|PHPUnit_Framework_MockObject_MockObject */ private $urlGenerator; + + /** @var ILogger|PHPUnit_Framework_MockObject_MockObject */ private $logger; - /** @var GenericProvider */ + /** @var Provider */ private $provider; protected function setUp() { @@ -47,15 +53,15 @@ class ProviderTest extends TestCase { $this->urlGenerator = $this->createMock(IURLGenerator::class); $this->logger = $this->createMock(ILogger::class); - $this->provider = new GenericProvider($this->l10n, $this->urlGenerator, $this->logger); + $this->provider = new Provider($this->l10n, $this->urlGenerator, $this->logger); } public function testParseUnrelated() { $lang = 'ru'; $event = $this->createMock(IEvent::class); $event->expects($this->once()) - ->method('getType') - ->will($this->returnValue('comments')); + ->method('getApp') + ->willReturn('comments'); $this->setExpectedException(InvalidArgumentException::class); $this->provider->parse($lang, $event); @@ -63,8 +69,7 @@ class ProviderTest extends TestCase { public function subjectData() { return [ - ['twofactor_success'], - ['twofactor_failed'], + ['codes_generated'], ]; } @@ -77,30 +82,50 @@ class ProviderTest extends TestCase { $l = $this->createMock(IL10N::class); $event->expects($this->once()) - ->method('getType') - ->will($this->returnValue('twofactor')); + ->method('getApp') + ->willReturn('twofactor_backupcodes'); $this->l10n->expects($this->once()) ->method('get') - ->with('core', $lang) - ->will($this->returnValue($l)); + ->with('twofactor_backupcodes', $lang) + ->willReturn($l); $this->urlGenerator->expects($this->once()) ->method('imagePath') ->with('core', 'actions/password.svg') - ->will($this->returnValue('path/to/image')); + ->willReturn('path/to/image'); $this->urlGenerator->expects($this->once()) ->method('getAbsoluteURL') ->with('path/to/image') - ->will($this->returnValue('absolute/path/to/image')); + ->willReturn('absolute/path/to/image'); $event->expects($this->once()) ->method('setIcon') ->with('absolute/path/to/image'); $event->expects($this->once()) ->method('getSubject') - ->will($this->returnValue($subject)); + ->willReturn($subject); $event->expects($this->once()) ->method('setParsedSubject'); $this->provider->parse($lang, $event); } + public function testParseInvalidSubject() { + $lang = 'ru'; + $l = $this->createMock(IL10N::class); + $event = $this->createMock(IEvent::class); + + $event->expects($this->once()) + ->method('getApp') + ->willReturn('twofactor_backupcodes'); + $this->l10n->expects($this->once()) + ->method('get') + ->with('twofactor_backupcodes', $lang) + ->willReturn($l); + $event->expects($this->once()) + ->method('getSubject') + ->willReturn('unrelated'); + + $this->expectException(InvalidArgumentException::class); + $this->provider->parse($lang, $event); + } + } diff --git a/apps/twofactor_backupcodes/tests/Unit/Service/BackupCodeStorageTest.php b/apps/twofactor_backupcodes/tests/Unit/Service/BackupCodeStorageTest.php index 54738f74600..109db7f688c 100644 --- a/apps/twofactor_backupcodes/tests/Unit/Service/BackupCodeStorageTest.php +++ b/apps/twofactor_backupcodes/tests/Unit/Service/BackupCodeStorageTest.php @@ -31,23 +31,24 @@ use OCP\ILogger; use OCP\IUser; use OCP\Security\IHasher; use OCP\Security\ISecureRandom; +use PHPUnit_Framework_MockObject_MockObject; use Test\TestCase; class BackupCodeStorageTest extends TestCase { - /** @var BackupCodeMapper|\PHPUnit_Framework_MockObject_MockObject */ + /** @var BackupCodeMapper|PHPUnit_Framework_MockObject_MockObject */ private $mapper; - /** @var ISecureRandom|\PHPUnit_Framework_MockObject_MockObject */ + /** @var ISecureRandom|PHPUnit_Framework_MockObject_MockObject */ private $random; - /** @var IHasher|\PHPUnit_Framework_MockObject_MockObject */ + /** @var IHasher|PHPUnit_Framework_MockObject_MockObject */ private $hasher; - /** @var IManager|\PHPUnit_Framework_MockObject_MockObject */ + /** @var IManager|PHPUnit_Framework_MockObject_MockObject */ private $activityManager; - /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */ + /** @var ILogger|PHPUnit_Framework_MockObject_MockObject */ private $logger; /** @var BackupCodeStorage */ @@ -56,11 +57,9 @@ class BackupCodeStorageTest extends TestCase { protected function setUp() { parent::setUp(); - $this->mapper = $this->getMockBuilder(BackupCodeMapper::class) - ->disableOriginalConstructor() - ->getMock(); - $this->random = $this->getMockBuilder(ISecureRandom::class)->getMock(); - $this->hasher = $this->getMockBuilder(IHasher::class)->getMock(); + $this->mapper = $this->createMock(BackupCodeMapper::class); + $this->random = $this->createMock(ISecureRandom::class); + $this->hasher = $this->createMock(IHasher::class); $this->activityManager = $this->createMock(IManager::class); $this->logger = $this->createMock(ILogger::class); @@ -68,7 +67,7 @@ class BackupCodeStorageTest extends TestCase { } public function testCreateCodes() { - $user = $this->getMockBuilder(IUser::class)->getMock(); + $user = $this->createMock(IUser::class); $number = 5; $event = $this->createMock(IEvent::class); @@ -77,7 +76,7 @@ class BackupCodeStorageTest extends TestCase { ->will($this->returnValue('fritz')); $this->random->expects($this->exactly($number)) ->method('generate') - ->with(10, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') + ->with(16, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') ->will($this->returnValue('CODEABCDEF')); $this->hasher->expects($this->exactly($number)) ->method('hash') @@ -121,7 +120,7 @@ class BackupCodeStorageTest extends TestCase { } public function testHasBackupCodes() { - $user = $this->getMockBuilder(IUser::class)->getMock(); + $user = $this->createMock(IUser::class); $codes = [ new BackupCode(), new BackupCode(), @@ -136,7 +135,7 @@ class BackupCodeStorageTest extends TestCase { } public function testHasBackupCodesNoCodes() { - $user = $this->getMockBuilder(IUser::class)->getMock(); + $user = $this->createMock(IUser::class); $codes = []; $this->mapper->expects($this->once()) @@ -148,7 +147,7 @@ class BackupCodeStorageTest extends TestCase { } public function testGetBackupCodeState() { - $user = $this->getMockBuilder(IUser::class)->getMock(); + $user = $this->createMock(IUser::class); $code1 = new BackupCode(); $code1->setUsed(1); @@ -173,7 +172,7 @@ class BackupCodeStorageTest extends TestCase { } public function testGetBackupCodeDisabled() { - $user = $this->getMockBuilder(IUser::class)->getMock(); + $user = $this->createMock(IUser::class); $codes = []; @@ -191,7 +190,7 @@ class BackupCodeStorageTest extends TestCase { } public function testValidateCode() { - $user = $this->getMockBuilder(IUser::class)->getMock(); + $user = $this->createMock(IUser::class); $code = new BackupCode(); $code->setUsed(0); $code->setCode('HASHEDVALUE'); @@ -217,7 +216,7 @@ class BackupCodeStorageTest extends TestCase { } public function testValidateUsedCode() { - $user = $this->getMockBuilder(IUser::class)->getMock(); + $user = $this->createMock(IUser::class); $code = new BackupCode(); $code->setUsed('1'); $code->setCode('HASHEDVALUE'); @@ -238,7 +237,7 @@ class BackupCodeStorageTest extends TestCase { } public function testValidateCodeWithWrongHash() { - $user = $this->getMockBuilder(IUser::class)->getMock(); + $user = $this->createMock(IUser::class); $code = new BackupCode(); $code->setUsed(0); $code->setCode('HASHEDVALUE'); diff --git a/apps/user_ldap/img/app-dark.svg b/apps/user_ldap/img/app-dark.svg new file mode 100644 index 00000000000..54939fab4f2 --- /dev/null +++ b/apps/user_ldap/img/app-dark.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.0" viewBox="0 0 16 16"> + <path style="block-progression:tb;color:#000000;text-transform:none;text-indent:0" fill="#000" d="m8.4036 1c-1.7312 0-3.1998 1.2661-3.1998 2.9 0.012287 0.51643 0.058473 1.1532 0.36664 2.5v0.033333l0.033328 0.033333c0.098928 0.28338 0.24289 0.44549 0.4333 0.66666s0.41742 0.48149 0.63328 0.69999c0.025397 0.025708 0.041676 0.041633 0.066656 0.066677 0.04281 0.18631 0.094672 0.38681 0.13332 0.56666 0.10284 0.47851 0.092296 0.81737 0.066668 0.93332-0.74389 0.26121-1.6694 0.57228-2.4998 0.93332-0.46622 0.2027-0.8881 0.3837-1.2332 0.59999-0.34513 0.2163-0.68837 0.37971-0.79994 0.86666-0.16004 0.63293-0.19866 0.7539-0.39997 1.5333-0.027212 0.20914 0.083011 0.42961 0.26665 0.53333 1.5078 0.81451 3.824 1.1423 6.1329 1.1333s4.6066-0.35609 6.0662-1.1333c0.11739-0.07353 0.14304-0.10869 0.13332-0.2333-0.04365-0.68908-0.08154-1.3669-0.13332-1.7666-0.01807-0.09908-0.06492-0.19275-0.13332-0.26666-0.46366-0.5537-1.1564-0.89218-1.9665-1.2333-0.7396-0.31144-1.6067-0.63486-2.4665-0.99999-0.048123-0.10721-0.095926-0.41912 0-0.89999 0.025759-0.12912 0.066096-0.26742 0.099994-0.4 0.0808-0.090507 0.14378-0.16447 0.23332-0.26666 0.19096-0.21796 0.39614-0.44661 0.56662-0.66666s0.30996-0.40882 0.39997-0.66666l0.03333-0.033333c0.34839-1.4062 0.34857-1.9929 0.36664-2.5v-0.033333c0-1.6339-1.4686-2.9-3.1998-2.9z"/> +</svg> diff --git a/apps/user_ldap/l10n/fr.js b/apps/user_ldap/l10n/fr.js index cbbe871d9cc..d07010761eb 100644 --- a/apps/user_ldap/l10n/fr.js +++ b/apps/user_ldap/l10n/fr.js @@ -10,7 +10,7 @@ OC.L10N.register( "No action specified" : "Aucune action spécifiée", "No configuration specified" : "Aucune configuration spécifiée", "No data specified" : "Aucune donnée spécifiée", - " Could not set configuration %s" : "Impossible de spécifier la configuration %s", + " Could not set configuration %s" : "Impossible d'appliquer la configuration %s", "Action does not exist" : "L'action n'existe pas", "The Base DN appears to be wrong" : "Le DN de base est erroné", "Testing configuration…" : "Test de configuration", @@ -36,7 +36,7 @@ OC.L10N.register( "LDAP Operations error. Anonymous bind might not be allowed." : "Erreur LDAP. La connexion anonyme au serveur n'est probablement pas acceptée.", "Saving failed. Please make sure the database is in Operation. Reload before continuing." : "La sauvegarde a échoué. Veuillez vérifier que la base de données est opérationnelle. Rechargez avant de poursuivre.", "Switching the mode will enable automatic LDAP queries. Depending on your LDAP size they may take a while. Do you still want to switch the mode?" : "Changer de mode activera les requêtes LDAP automatiques. Selon la taille de votre annuaire LDAP, cela peut prendre du temps. Voulez-vous toujours changer de mode ?", - "Mode switch" : "Changer de mode", + "Mode switch" : "Basculer de mode", "Select attributes" : "Sélectionner les attributs", "User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>" : "Utilisateur introuvable. Veuillez vérifier les attributs de login et le nom d'utilisateur. Filtre effectif (à copier-coller pour valider en ligne de commande):<br/>", "User found and settings verified." : "Utilisateur trouvé et paramètres vérifiés.", @@ -122,7 +122,7 @@ OC.L10N.register( "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." : "Non recommandé, à utiliser à des fins de tests uniquement. Si la connexion ne fonctionne qu'avec cette option, importez le certificat SSL du serveur LDAP dans le serveur %s.", "Cache Time-To-Live" : "Durée de vie du cache (TTL)", "in seconds. A change empties the cache." : "en secondes. Tout changement vide le cache.", - "Directory Settings" : "Paramètres du répertoire", + "Directory Settings" : "Paramètres du dossier", "User Display Name Field" : "Champ \"nom d'affichage\" de l'utilisateur", "The LDAP attribute to use to generate the user's display name." : "L'attribut LDAP utilisé pour générer le nom d'affichage de l'utilisateur.", "2nd User Display Name Field" : "Second attribut pour le nom d'affichage", diff --git a/apps/user_ldap/l10n/fr.json b/apps/user_ldap/l10n/fr.json index e31c5f7fbe2..72feb90e314 100644 --- a/apps/user_ldap/l10n/fr.json +++ b/apps/user_ldap/l10n/fr.json @@ -8,7 +8,7 @@ "No action specified" : "Aucune action spécifiée", "No configuration specified" : "Aucune configuration spécifiée", "No data specified" : "Aucune donnée spécifiée", - " Could not set configuration %s" : "Impossible de spécifier la configuration %s", + " Could not set configuration %s" : "Impossible d'appliquer la configuration %s", "Action does not exist" : "L'action n'existe pas", "The Base DN appears to be wrong" : "Le DN de base est erroné", "Testing configuration…" : "Test de configuration", @@ -34,7 +34,7 @@ "LDAP Operations error. Anonymous bind might not be allowed." : "Erreur LDAP. La connexion anonyme au serveur n'est probablement pas acceptée.", "Saving failed. Please make sure the database is in Operation. Reload before continuing." : "La sauvegarde a échoué. Veuillez vérifier que la base de données est opérationnelle. Rechargez avant de poursuivre.", "Switching the mode will enable automatic LDAP queries. Depending on your LDAP size they may take a while. Do you still want to switch the mode?" : "Changer de mode activera les requêtes LDAP automatiques. Selon la taille de votre annuaire LDAP, cela peut prendre du temps. Voulez-vous toujours changer de mode ?", - "Mode switch" : "Changer de mode", + "Mode switch" : "Basculer de mode", "Select attributes" : "Sélectionner les attributs", "User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>" : "Utilisateur introuvable. Veuillez vérifier les attributs de login et le nom d'utilisateur. Filtre effectif (à copier-coller pour valider en ligne de commande):<br/>", "User found and settings verified." : "Utilisateur trouvé et paramètres vérifiés.", @@ -120,7 +120,7 @@ "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." : "Non recommandé, à utiliser à des fins de tests uniquement. Si la connexion ne fonctionne qu'avec cette option, importez le certificat SSL du serveur LDAP dans le serveur %s.", "Cache Time-To-Live" : "Durée de vie du cache (TTL)", "in seconds. A change empties the cache." : "en secondes. Tout changement vide le cache.", - "Directory Settings" : "Paramètres du répertoire", + "Directory Settings" : "Paramètres du dossier", "User Display Name Field" : "Champ \"nom d'affichage\" de l'utilisateur", "The LDAP attribute to use to generate the user's display name." : "L'attribut LDAP utilisé pour générer le nom d'affichage de l'utilisateur.", "2nd User Display Name Field" : "Second attribut pour le nom d'affichage", diff --git a/apps/user_ldap/l10n/id.js b/apps/user_ldap/l10n/id.js index 8c62d7df617..7f256c26649 100644 --- a/apps/user_ldap/l10n/id.js +++ b/apps/user_ldap/l10n/id.js @@ -40,12 +40,15 @@ OC.L10N.register( "Select attributes" : "Pilih atribut", "User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>" : "Pengguna tidak ditemukan. Mohon periksa atribut login dan nama pengguna Anda. Penyaring efektif (salin dan tempel berikut untuk validasi baris perintah):\n<br/>", "User found and settings verified." : "Pengguna ditemukan dan pengaturan terverifikasi.", + "Settings verified, but more than one user found. Only the first will be able to login. Consider a more narrow filter." : "Pengaturan terverifikasi, tapi lebih dari satu pengguna ditemukan. Hanya pengguna pertama yang dapat masuk log. Pertimbangkan lebih mempersempit penyaringan.", "An unspecified error occurred. Please check the settings and the log." : "Terjadi kesalahan yang tidak disebutkan. Mohon periksa pengaturan dan log.", "The search filter is invalid, probably due to syntax issues like uneven number of opened and closed brackets. Please revise." : "Penyaring pencarian tidak sah, kemungkinan karena masalah sintaks seperti jumlah kurung buka dan tutup tidak sama. Mohon diperiksa.", "A connection error to LDAP / AD occurred, please check host, port and credentials." : "Terjadi kesalahan sambungan ke LDAP / AD, mohon periksa host, port dan kredensial.", "The %uid placeholder is missing. It will be replaced with the login name when querying LDAP / AD." : "Placeholder %uid tidak ada. Placeholder akan digantikan dengan nama login saat melakukan kueri LDAP / AD.", "Please provide a login name to test against" : "Mohon berikan nama login untuk mengujinya kembali", "The group box was disabled, because the LDAP / AD server does not support memberOf." : "Kotak grup telah dinonaktifkan, karena server LDAP / AD tidak mendukung keanggotaan.", + "Password change rejected. Hint: " : "Perubahan sandi ditolak. Petunjuk:", + "LDAP / AD integration" : "Integrasi LDAP / AD", "_%s group found_::_%s groups found_" : ["%s grup ditemukan"], "_%s user found_::_%s users found_" : ["%s pengguna ditemukan"], "Could not detect user display name attribute. Please specify it yourself in advanced ldap settings." : "Tidak mendeteksi atribut nama tampilan pengguna. Silakan menentukannya sendiri di pengaturan ldap lanjutan.", @@ -140,6 +143,9 @@ OC.L10N.register( "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "Ketika dihidupkan, grup yang berisi grup akan didukung. (Hanya bekerja jika atribut anggota grup berisi DN.)", "Paging chunksize" : "Paging chunksize", "Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" : "Chunksize digunakan untuk pencarian paged LDAP yang mengembalikan hasil secara massal seperti enumerasi pengguna dan grup. (Atur dengan nilai 0 untuk menonaktifkan pencarian paged LDAP dalam situasi tersebut.)", + "Enable LDAP password changes per user" : "Aktifkan perubahan sandi LDAP per pengguna", + "Allow LDAP users to change their password and allow Super Administrators and Group Administrators to change the password of their LDAP users. Only works when access control policies are configured accordingly on the LDAP server. As passwords are sent in plaintext to the LDAP server, transport encryption must be used and password hashing should be configured on the LDAP server." : "Perbolehkan pengguna LDAP mengubah sandi mereka dan perbolehkan Administrator Super dan Administrator Grup untuk mengubah sandi pengguna LDAP mereka. Hanya bekerja ketika kebijaksanaan akses kontrol terconfigurasi berdasarkan server LDAP. Sebagaimana sandi dikirim dalam plain teks ke server LDAP, pengiriman enkripsi harus digunakan dan hashing sandi harus terkonfigurasi di server LDAP.", + "(New password is sent as plain text to LDAP)" : "(Sandi baru dikirim sebagai plain teks ke LDAP)", "Special Attributes" : "Atribut Khusus", "Quota Field" : "Kolom Kuota", "Quota Default" : "Kuota Baku", diff --git a/apps/user_ldap/l10n/id.json b/apps/user_ldap/l10n/id.json index a356fdac06b..7fc32321558 100644 --- a/apps/user_ldap/l10n/id.json +++ b/apps/user_ldap/l10n/id.json @@ -38,12 +38,15 @@ "Select attributes" : "Pilih atribut", "User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>" : "Pengguna tidak ditemukan. Mohon periksa atribut login dan nama pengguna Anda. Penyaring efektif (salin dan tempel berikut untuk validasi baris perintah):\n<br/>", "User found and settings verified." : "Pengguna ditemukan dan pengaturan terverifikasi.", + "Settings verified, but more than one user found. Only the first will be able to login. Consider a more narrow filter." : "Pengaturan terverifikasi, tapi lebih dari satu pengguna ditemukan. Hanya pengguna pertama yang dapat masuk log. Pertimbangkan lebih mempersempit penyaringan.", "An unspecified error occurred. Please check the settings and the log." : "Terjadi kesalahan yang tidak disebutkan. Mohon periksa pengaturan dan log.", "The search filter is invalid, probably due to syntax issues like uneven number of opened and closed brackets. Please revise." : "Penyaring pencarian tidak sah, kemungkinan karena masalah sintaks seperti jumlah kurung buka dan tutup tidak sama. Mohon diperiksa.", "A connection error to LDAP / AD occurred, please check host, port and credentials." : "Terjadi kesalahan sambungan ke LDAP / AD, mohon periksa host, port dan kredensial.", "The %uid placeholder is missing. It will be replaced with the login name when querying LDAP / AD." : "Placeholder %uid tidak ada. Placeholder akan digantikan dengan nama login saat melakukan kueri LDAP / AD.", "Please provide a login name to test against" : "Mohon berikan nama login untuk mengujinya kembali", "The group box was disabled, because the LDAP / AD server does not support memberOf." : "Kotak grup telah dinonaktifkan, karena server LDAP / AD tidak mendukung keanggotaan.", + "Password change rejected. Hint: " : "Perubahan sandi ditolak. Petunjuk:", + "LDAP / AD integration" : "Integrasi LDAP / AD", "_%s group found_::_%s groups found_" : ["%s grup ditemukan"], "_%s user found_::_%s users found_" : ["%s pengguna ditemukan"], "Could not detect user display name attribute. Please specify it yourself in advanced ldap settings." : "Tidak mendeteksi atribut nama tampilan pengguna. Silakan menentukannya sendiri di pengaturan ldap lanjutan.", @@ -138,6 +141,9 @@ "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "Ketika dihidupkan, grup yang berisi grup akan didukung. (Hanya bekerja jika atribut anggota grup berisi DN.)", "Paging chunksize" : "Paging chunksize", "Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" : "Chunksize digunakan untuk pencarian paged LDAP yang mengembalikan hasil secara massal seperti enumerasi pengguna dan grup. (Atur dengan nilai 0 untuk menonaktifkan pencarian paged LDAP dalam situasi tersebut.)", + "Enable LDAP password changes per user" : "Aktifkan perubahan sandi LDAP per pengguna", + "Allow LDAP users to change their password and allow Super Administrators and Group Administrators to change the password of their LDAP users. Only works when access control policies are configured accordingly on the LDAP server. As passwords are sent in plaintext to the LDAP server, transport encryption must be used and password hashing should be configured on the LDAP server." : "Perbolehkan pengguna LDAP mengubah sandi mereka dan perbolehkan Administrator Super dan Administrator Grup untuk mengubah sandi pengguna LDAP mereka. Hanya bekerja ketika kebijaksanaan akses kontrol terconfigurasi berdasarkan server LDAP. Sebagaimana sandi dikirim dalam plain teks ke server LDAP, pengiriman enkripsi harus digunakan dan hashing sandi harus terkonfigurasi di server LDAP.", + "(New password is sent as plain text to LDAP)" : "(Sandi baru dikirim sebagai plain teks ke LDAP)", "Special Attributes" : "Atribut Khusus", "Quota Field" : "Kolom Kuota", "Quota Default" : "Kuota Baku", diff --git a/apps/user_ldap/l10n/sq.js b/apps/user_ldap/l10n/sq.js index dd53169a6bd..2f09cd96511 100644 --- a/apps/user_ldap/l10n/sq.js +++ b/apps/user_ldap/l10n/sq.js @@ -46,6 +46,7 @@ OC.L10N.register( "The %uid placeholder is missing. It will be replaced with the login name when querying LDAP / AD." : "Vendmbajtësja %uid mungon. Do të zëvendësohet me emrin e hyrjes, kur të kërkohet te LDAP / AD.", "Please provide a login name to test against" : "Ju lutemi, jepni një emër hyrjesh që të ritestohet", "The group box was disabled, because the LDAP / AD server does not support memberOf." : "Kutia e grupeve u çaktivizua, ngaqë shërbyesi LDAP / AD nuk mbulon memberOf.", + "LDAP / AD integration" : "Integrimi LDAP / AD", "_%s group found_::_%s groups found_" : ["U gjet %s grup","U gjetën %s grupe"], "_%s user found_::_%s users found_" : ["U gjet %s përdorues","U gjetën %s përdorues"], "Could not detect user display name attribute. Please specify it yourself in advanced ldap settings." : "S’u zbulua dot atribut emri përdoruesi në ekran. Ju lutemi, caktojeni ju vetë te rregullime e mëtejshme për LDAP.", @@ -140,6 +141,7 @@ OC.L10N.register( "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "Kur aktivizohet, grupet që përmbajnë grupe mbulohen. (Funksionon vetëm nëse atributi për anëtar grupi përmban DN-ra.)", "Paging chunksize" : "Madhësi copash faqosjeje", "Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" : "Madhësi copash të përdorura për kërkime LDAP të sistemuara në faqe, kërkime që japin përfundime të papërpunuara, të tilla si numër përdoruesish ose grupesh. (Caktimi si 0 i çaktivizon kërkimet e faqosura LDAP për këto raste.)", + "(New password is sent as plain text to LDAP)" : "(Fjalëkalimi i ri është dërgur si text i thjeshtë te LDAP)", "Special Attributes" : "Atribute Speciale", "Quota Field" : "Fushë Kuotash", "Quota Default" : "Parazgjedhje Kuotash", diff --git a/apps/user_ldap/l10n/sq.json b/apps/user_ldap/l10n/sq.json index 135a2f27170..053ae0f5a2d 100644 --- a/apps/user_ldap/l10n/sq.json +++ b/apps/user_ldap/l10n/sq.json @@ -44,6 +44,7 @@ "The %uid placeholder is missing. It will be replaced with the login name when querying LDAP / AD." : "Vendmbajtësja %uid mungon. Do të zëvendësohet me emrin e hyrjes, kur të kërkohet te LDAP / AD.", "Please provide a login name to test against" : "Ju lutemi, jepni një emër hyrjesh që të ritestohet", "The group box was disabled, because the LDAP / AD server does not support memberOf." : "Kutia e grupeve u çaktivizua, ngaqë shërbyesi LDAP / AD nuk mbulon memberOf.", + "LDAP / AD integration" : "Integrimi LDAP / AD", "_%s group found_::_%s groups found_" : ["U gjet %s grup","U gjetën %s grupe"], "_%s user found_::_%s users found_" : ["U gjet %s përdorues","U gjetën %s përdorues"], "Could not detect user display name attribute. Please specify it yourself in advanced ldap settings." : "S’u zbulua dot atribut emri përdoruesi në ekran. Ju lutemi, caktojeni ju vetë te rregullime e mëtejshme për LDAP.", @@ -138,6 +139,7 @@ "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" : "Kur aktivizohet, grupet që përmbajnë grupe mbulohen. (Funksionon vetëm nëse atributi për anëtar grupi përmban DN-ra.)", "Paging chunksize" : "Madhësi copash faqosjeje", "Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" : "Madhësi copash të përdorura për kërkime LDAP të sistemuara në faqe, kërkime që japin përfundime të papërpunuara, të tilla si numër përdoruesish ose grupesh. (Caktimi si 0 i çaktivizon kërkimet e faqosura LDAP për këto raste.)", + "(New password is sent as plain text to LDAP)" : "(Fjalëkalimi i ri është dërgur si text i thjeshtë te LDAP)", "Special Attributes" : "Atribute Speciale", "Quota Field" : "Fushë Kuotash", "Quota Default" : "Parazgjedhje Kuotash", diff --git a/apps/user_ldap/l10n/sv.js b/apps/user_ldap/l10n/sv.js index aba8488f0d1..9a1768fe01e 100644 --- a/apps/user_ldap/l10n/sv.js +++ b/apps/user_ldap/l10n/sv.js @@ -44,6 +44,7 @@ OC.L10N.register( "A connection error to LDAP / AD occurred, please check host, port and credentials." : "Ett anslutningsfel till LDAP / AD uppstod. Var god granska värd, port och inloggningsuppgifter.", "Please provide a login name to test against" : "Vänligen ange ett inloggningsnamn att försöka ansluta med", "Password change rejected. Hint: " : "Lösenordsbyte nekad. Anledning/tips: ", + "LDAP / AD integration" : "LDAP / AD integration", "_%s group found_::_%s groups found_" : ["%s grupp hittad","%s grupper hittade"], "_%s user found_::_%s users found_" : ["%s användare hittad","%s användare hittade"], "Could not detect user display name attribute. Please specify it yourself in advanced ldap settings." : "Kunde inte upptäcka attributet användarvisningsnamn. Vänligen ange det själv i de avancerade LDAP-inställningarna.", diff --git a/apps/user_ldap/l10n/sv.json b/apps/user_ldap/l10n/sv.json index 8f5b48cbf7e..a4019761f96 100644 --- a/apps/user_ldap/l10n/sv.json +++ b/apps/user_ldap/l10n/sv.json @@ -42,6 +42,7 @@ "A connection error to LDAP / AD occurred, please check host, port and credentials." : "Ett anslutningsfel till LDAP / AD uppstod. Var god granska värd, port och inloggningsuppgifter.", "Please provide a login name to test against" : "Vänligen ange ett inloggningsnamn att försöka ansluta med", "Password change rejected. Hint: " : "Lösenordsbyte nekad. Anledning/tips: ", + "LDAP / AD integration" : "LDAP / AD integration", "_%s group found_::_%s groups found_" : ["%s grupp hittad","%s grupper hittade"], "_%s user found_::_%s users found_" : ["%s användare hittad","%s användare hittade"], "Could not detect user display name attribute. Please specify it yourself in advanced ldap settings." : "Kunde inte upptäcka attributet användarvisningsnamn. Vänligen ange det själv i de avancerade LDAP-inställningarna.", diff --git a/apps/user_ldap/lib/Settings/Section.php b/apps/user_ldap/lib/Settings/Section.php index 82d8d0c84fa..86d293d3879 100644 --- a/apps/user_ldap/lib/Settings/Section.php +++ b/apps/user_ldap/lib/Settings/Section.php @@ -24,13 +24,21 @@ namespace OCA\User_LDAP\Settings; use OCP\IL10N; -use OCP\Settings\ISection; +use OCP\IURLGenerator; +use OCP\Settings\IIconSection; -class Section implements ISection { +class Section implements IIconSection { /** @var IL10N */ private $l; + /** @var IURLGenerator */ + private $url; - public function __construct(IL10N $l) { + /** + * @param IURLGenerator $url + * @param IL10N $l + */ + public function __construct(IURLGenerator $url, IL10N $l) { + $this->url = $url; $this->l = $l; } @@ -64,4 +72,11 @@ class Section implements ISection { public function getPriority() { return 25; } + + /** + * {@inheritdoc} + */ + public function getIcon() { + return $this->url->imagePath('user_ldap', 'app-dark.svg'); + } } diff --git a/apps/user_ldap/tests/Settings/SectionTest.php b/apps/user_ldap/tests/Settings/SectionTest.php index 2d2165b8e56..5f565e89933 100644 --- a/apps/user_ldap/tests/Settings/SectionTest.php +++ b/apps/user_ldap/tests/Settings/SectionTest.php @@ -25,19 +25,24 @@ namespace OCA\User_LDAP\Tests\Settings; use OCA\User_LDAP\Settings\Section; use OCP\IL10N; +use OCP\IURLGenerator; use Test\TestCase; class SectionTest extends TestCase { - /** @var IL10N */ + /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */ + private $url; + /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ private $l; /** @var Section */ private $section; public function setUp() { parent::setUp(); - $this->l = $this->getMockBuilder('\OCP\IL10N')->getMock(); + $this->url = $this->createMock(IURLGenerator::class); + $this->l = $this->createMock(IL10N::class); $this->section = new Section( + $this->url, $this->l ); } @@ -59,4 +64,13 @@ class SectionTest extends TestCase { public function testGetPriority() { $this->assertSame(25, $this->section->getPriority()); } + + public function testGetIcon() { + $this->url->expects($this->once()) + ->method('imagePath') + ->with('user_ldap', 'app-dark.svg') + ->willReturn('icon'); + + $this->assertSame('icon', $this->section->getIcon()); + } } diff --git a/apps/workflowengine/lib/Settings/Section.php b/apps/workflowengine/lib/Settings/Section.php index df8bb807134..b46f9a4a35f 100644 --- a/apps/workflowengine/lib/Settings/Section.php +++ b/apps/workflowengine/lib/Settings/Section.php @@ -24,13 +24,21 @@ namespace OCA\WorkflowEngine\Settings; use OCP\IL10N; -use OCP\Settings\ISection; +use OCP\IURLGenerator; +use OCP\Settings\IIconSection; -class Section implements ISection { +class Section implements IIconSection { /** @var IL10N */ private $l; + /** @var IURLGenerator */ + private $url; - public function __construct(IL10N $l) { + /** + * @param IURLGenerator $url + * @param IL10N $l + */ + public function __construct(IURLGenerator $url, IL10N $l) { + $this->url = $url; $this->l = $l; } @@ -54,4 +62,11 @@ class Section implements ISection { public function getPriority() { return 55; } + + /** + * {@inheritdoc} + */ + public function getIcon() { + return $this->url->imagePath('core', 'actions/tag.svg'); + } } |