summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/dashboard/l10n/de.js1
-rw-r--r--apps/dashboard/l10n/de.json1
-rw-r--r--apps/dashboard/l10n/hu.js1
-rw-r--r--apps/dashboard/l10n/hu.json1
-rw-r--r--apps/dav/composer/composer/autoload_classmap.php2
-rw-r--r--apps/dav/composer/composer/autoload_static.php2
-rw-r--r--apps/dav/l10n/de.js2
-rw-r--r--apps/dav/l10n/de.json2
-rw-r--r--apps/dav/l10n/pt_BR.js17
-rw-r--r--apps/dav/l10n/pt_BR.json17
-rw-r--r--apps/dav/lib/CalDAV/CalDavBackend.php151
-rw-r--r--apps/dav/lib/Connector/Sabre/ChecksumUpdatePlugin.php83
-rw-r--r--apps/dav/lib/Connector/Sabre/Directory.php16
-rw-r--r--apps/dav/lib/Connector/Sabre/File.php19
-rw-r--r--apps/dav/lib/Connector/Sabre/FilesPlugin.php1
-rw-r--r--apps/dav/lib/Connector/Sabre/Node.php25
-rw-r--r--apps/dav/lib/Connector/Sabre/ServerFactory.php1
-rw-r--r--apps/dav/lib/Connector/Sabre/SharesPlugin.php15
-rw-r--r--apps/dav/lib/Profiler/ProfilerPlugin.php47
-rw-r--r--apps/dav/lib/Server.php33
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php44
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/FileTest.php67
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php7
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php9
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php15
-rw-r--r--apps/federatedfilesharing/lib/Controller/RequestHandlerController.php18
-rw-r--r--apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php10
-rw-r--r--apps/files/js/fileactions.js2
-rw-r--r--apps/files/js/files.js6
-rw-r--r--apps/files/js/sidebarpreviewtext.js2
-rw-r--r--apps/files/l10n/ru.js2
-rw-r--r--apps/files/l10n/ru.json2
-rw-r--r--apps/files/lib/Controller/AjaxController.php1
-rw-r--r--apps/files_external/appinfo/info.xml2
-rw-r--r--apps/files_external/js/settings.js2
-rw-r--r--apps/files_external/l10n/hu.js1
-rw-r--r--apps/files_external/l10n/hu.json1
-rw-r--r--apps/files_external/lib/Migration/Version1011Date20200630192246.php2
-rw-r--r--apps/files_external/lib/Migration/Version1016Date20220324154536.php54
-rw-r--r--apps/files_sharing/appinfo/info.xml2
-rw-r--r--apps/files_sharing/composer/composer/autoload_classmap.php1
-rw-r--r--apps/files_sharing/composer/composer/autoload_static.php1
-rw-r--r--apps/files_sharing/js/public.js4
-rw-r--r--apps/files_sharing/l10n/cs.js2
-rw-r--r--apps/files_sharing/l10n/cs.json2
-rw-r--r--apps/files_sharing/l10n/de.js1
-rw-r--r--apps/files_sharing/l10n/de.json1
-rw-r--r--apps/files_sharing/l10n/de_DE.js2
-rw-r--r--apps/files_sharing/l10n/de_DE.json2
-rw-r--r--apps/files_sharing/l10n/es.js1
-rw-r--r--apps/files_sharing/l10n/es.json1
-rw-r--r--apps/files_sharing/l10n/eu.js1
-rw-r--r--apps/files_sharing/l10n/eu.json1
-rw-r--r--apps/files_sharing/l10n/fr.js1
-rw-r--r--apps/files_sharing/l10n/fr.json1
-rw-r--r--apps/files_sharing/l10n/hu.js3
-rw-r--r--apps/files_sharing/l10n/hu.json3
-rw-r--r--apps/files_sharing/l10n/it.js1
-rw-r--r--apps/files_sharing/l10n/it.json1
-rw-r--r--apps/files_sharing/l10n/pl.js2
-rw-r--r--apps/files_sharing/l10n/pl.json2
-rw-r--r--apps/files_sharing/l10n/pt_BR.js6
-rw-r--r--apps/files_sharing/l10n/pt_BR.json6
-rw-r--r--apps/files_sharing/l10n/sk.js1
-rw-r--r--apps/files_sharing/l10n/sk.json1
-rw-r--r--apps/files_sharing/l10n/sv.js1
-rw-r--r--apps/files_sharing/l10n/sv.json1
-rw-r--r--apps/files_sharing/l10n/tr.js2
-rw-r--r--apps/files_sharing/l10n/tr.json2
-rw-r--r--apps/files_sharing/l10n/zh_HK.js2
-rw-r--r--apps/files_sharing/l10n/zh_HK.json2
-rw-r--r--apps/files_sharing/l10n/zh_TW.js2
-rw-r--r--apps/files_sharing/l10n/zh_TW.json2
-rw-r--r--apps/files_sharing/lib/Controller/ShareAPIController.php35
-rw-r--r--apps/files_sharing/lib/Migration/Version24000Date20220404142216.php56
-rw-r--r--apps/files_sharing/lib/SharedStorage.php41
-rw-r--r--apps/files_sharing/tests/ApiTest.php3
-rw-r--r--apps/files_sharing/tests/CapabilitiesTest.php12
-rw-r--r--apps/files_sharing/tests/Controller/ShareAPIControllerTest.php46
-rw-r--r--apps/files_trashbin/appinfo/info.xml1
-rw-r--r--apps/files_trashbin/composer/composer/autoload_classmap.php1
-rw-r--r--apps/files_trashbin/composer/composer/autoload_static.php1
-rw-r--r--apps/files_trashbin/composer/composer/installed.php4
-rw-r--r--apps/files_trashbin/lib/Command/RestoreAllFiles.php161
-rw-r--r--apps/files_versions/lib/Storage.php5
-rw-r--r--apps/settings/l10n/de.js3
-rw-r--r--apps/settings/l10n/de.json3
-rw-r--r--apps/settings/l10n/hu.js13
-rw-r--r--apps/settings/l10n/hu.json13
-rw-r--r--apps/settings/l10n/pt_BR.js6
-rw-r--r--apps/settings/l10n/pt_BR.json6
-rw-r--r--apps/settings/lib/Settings/Admin/Sharing.php9
-rw-r--r--apps/settings/src/admin.js6
-rw-r--r--apps/settings/templates/settings/admin/additional-mail.php2
-rw-r--r--apps/settings/templates/settings/admin/sharing.php12
-rw-r--r--apps/settings/tests/Settings/Admin/SharingTest.php4
-rw-r--r--apps/settings/tests/UserMigration/AccountMigratorTest.php120
-rw-r--r--apps/settings/tests/UserMigration/assets/account-complex.json1
-rw-r--r--apps/settings/tests/UserMigration/assets/account.json1
-rw-r--r--apps/systemtags/l10n/hu.js72
-rw-r--r--apps/systemtags/l10n/hu.json72
-rw-r--r--apps/updatenotification/l10n/cs.js1
-rw-r--r--apps/updatenotification/l10n/cs.json1
-rw-r--r--apps/updatenotification/l10n/de_DE.js1
-rw-r--r--apps/updatenotification/l10n/de_DE.json1
-rw-r--r--apps/updatenotification/l10n/hu.js2
-rw-r--r--apps/updatenotification/l10n/hu.json2
-rw-r--r--apps/updatenotification/l10n/pl.js1
-rw-r--r--apps/updatenotification/l10n/pl.json1
-rw-r--r--apps/updatenotification/l10n/tr.js1
-rw-r--r--apps/updatenotification/l10n/tr.json1
-rw-r--r--apps/updatenotification/l10n/zh_HK.js1
-rw-r--r--apps/updatenotification/l10n/zh_HK.json1
-rw-r--r--apps/updatenotification/l10n/zh_TW.js1
-rw-r--r--apps/updatenotification/l10n/zh_TW.json1
-rw-r--r--apps/user_ldap/appinfo/info.xml1
-rw-r--r--apps/user_ldap/composer/composer/autoload_classmap.php2
-rw-r--r--apps/user_ldap/composer/composer/autoload_static.php2
-rw-r--r--apps/user_ldap/css/settings.css8
-rw-r--r--apps/user_ldap/lib/Command/CreateEmptyConfig.php1
-rw-r--r--apps/user_ldap/lib/Command/ResetGroup.php111
-rw-r--r--apps/user_ldap/lib/Configuration.php11
-rw-r--r--apps/user_ldap/lib/Controller/ConfigAPIController.php1
-rw-r--r--apps/user_ldap/lib/DataCollector/LdapDataCollector.php50
-rw-r--r--apps/user_ldap/lib/GroupPluginManager.php28
-rw-r--r--apps/user_ldap/lib/Group_LDAP.php27
-rw-r--r--apps/user_ldap/lib/Group_Proxy.php10
-rw-r--r--apps/user_ldap/lib/LDAP.php32
-rw-r--r--apps/user_ldap/lib/Migration/Version1120Date20210917155206.php2
-rw-r--r--apps/user_ldap/lib/Migration/Version1141Date20220323143801.php2
-rw-r--r--apps/user_ldap/lib/UserPluginManager.php7
-rw-r--r--apps/user_ldap/lib/Wizard.php2
-rw-r--r--apps/user_ldap/tests/GroupLDAPPluginTest.php16
-rw-r--r--apps/user_ldap/tests/Group_LDAPTest.php4
-rw-r--r--apps/weather_status/l10n/cs.js24
-rw-r--r--apps/weather_status/l10n/cs.json24
-rw-r--r--apps/weather_status/l10n/de.js34
-rw-r--r--apps/weather_status/l10n/de.json34
-rw-r--r--apps/weather_status/l10n/de_DE.js24
-rw-r--r--apps/weather_status/l10n/de_DE.json24
-rw-r--r--apps/weather_status/l10n/es.js6
-rw-r--r--apps/weather_status/l10n/es.json6
-rw-r--r--apps/weather_status/l10n/eu.js12
-rw-r--r--apps/weather_status/l10n/eu.json12
-rw-r--r--apps/weather_status/l10n/fr.js12
-rw-r--r--apps/weather_status/l10n/fr.json12
-rw-r--r--apps/weather_status/l10n/hu.js5
-rw-r--r--apps/weather_status/l10n/hu.json5
-rw-r--r--apps/weather_status/l10n/it.js12
-rw-r--r--apps/weather_status/l10n/it.json12
-rw-r--r--apps/weather_status/l10n/nl.js12
-rw-r--r--apps/weather_status/l10n/nl.json12
-rw-r--r--apps/weather_status/l10n/pl.js24
-rw-r--r--apps/weather_status/l10n/pl.json24
-rw-r--r--apps/weather_status/l10n/pt_BR.js12
-rw-r--r--apps/weather_status/l10n/pt_BR.json12
-rw-r--r--apps/weather_status/l10n/ru.js12
-rw-r--r--apps/weather_status/l10n/ru.json12
-rw-r--r--apps/weather_status/l10n/sk.js12
-rw-r--r--apps/weather_status/l10n/sk.json12
-rw-r--r--apps/weather_status/l10n/sv.js12
-rw-r--r--apps/weather_status/l10n/sv.json12
-rw-r--r--apps/weather_status/l10n/tr.js30
-rw-r--r--apps/weather_status/l10n/tr.json30
-rw-r--r--apps/weather_status/l10n/zh_CN.js12
-rw-r--r--apps/weather_status/l10n/zh_CN.json12
-rw-r--r--apps/weather_status/l10n/zh_HK.js24
-rw-r--r--apps/weather_status/l10n/zh_HK.json24
-rw-r--r--apps/weather_status/l10n/zh_TW.js24
-rw-r--r--apps/weather_status/l10n/zh_TW.json24
-rw-r--r--apps/weather_status/src/App.vue36
-rw-r--r--apps/workflowengine/lib/Listener/LoadAdditionalSettingsScriptsListener.php11
172 files changed, 1640 insertions, 803 deletions
diff --git a/apps/dashboard/l10n/de.js b/apps/dashboard/l10n/de.js
index 597f2f2da41..36a3272f682 100644
--- a/apps/dashboard/l10n/de.js
+++ b/apps/dashboard/l10n/de.js
@@ -3,6 +3,7 @@ OC.L10N.register(
{
"Dashboard" : "Dashboard",
"Dashboard app" : "Dashboard-App",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an\noverview of your upcoming appointments, urgent emails, chat messages,\nincoming tickets, latest tweets and much more! Users can add the widgets\nthey like and change the background to their liking." : "Starte informiert in den Tag\n\nDas Nextcloud-Dashboard ist Dein Ausgangspunkt für den Tag und gibt Dir\neinen Überblick über Deine anstehenden Termine, dringende E-Mails, Chatnachrichten, eingehende Tickets, neuste Tweets und vieles mehr! Benutzer können die Widgets hinzufügen, die sie mögen und den Hintergrund nach ihren Wünschen angepassen.",
"Customize" : "Anpassen",
"Edit widgets" : "Widgets bearbeiten",
"Get more widgets from the App Store" : "Hole Dir weitere Widgets aus dem App-Store",
diff --git a/apps/dashboard/l10n/de.json b/apps/dashboard/l10n/de.json
index 4c739962c82..f67aa520e4d 100644
--- a/apps/dashboard/l10n/de.json
+++ b/apps/dashboard/l10n/de.json
@@ -1,6 +1,7 @@
{ "translations": {
"Dashboard" : "Dashboard",
"Dashboard app" : "Dashboard-App",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an\noverview of your upcoming appointments, urgent emails, chat messages,\nincoming tickets, latest tweets and much more! Users can add the widgets\nthey like and change the background to their liking." : "Starte informiert in den Tag\n\nDas Nextcloud-Dashboard ist Dein Ausgangspunkt für den Tag und gibt Dir\neinen Überblick über Deine anstehenden Termine, dringende E-Mails, Chatnachrichten, eingehende Tickets, neuste Tweets und vieles mehr! Benutzer können die Widgets hinzufügen, die sie mögen und den Hintergrund nach ihren Wünschen angepassen.",
"Customize" : "Anpassen",
"Edit widgets" : "Widgets bearbeiten",
"Get more widgets from the App Store" : "Hole Dir weitere Widgets aus dem App-Store",
diff --git a/apps/dashboard/l10n/hu.js b/apps/dashboard/l10n/hu.js
index 60f8dc13316..56f4c874be9 100644
--- a/apps/dashboard/l10n/hu.js
+++ b/apps/dashboard/l10n/hu.js
@@ -3,6 +3,7 @@ OC.L10N.register(
{
"Dashboard" : "Irányítópult",
"Dashboard app" : "Irányítópult alkalmazás",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an\noverview of your upcoming appointments, urgent emails, chat messages,\nincoming tickets, latest tweets and much more! Users can add the widgets\nthey like and change the background to their liking." : "Kezdje informáltan a napot\n\nA Nextcloud irányítópult a napja kezdőpontja, áttekintést nyújtva a közelgő találkozókról, sürgős levelekről, csevegőüzenetekről, hibajegyekről, a legfrissebb tweetekről és sok másról. A felhasználók modulokat adhatnak hozzá, és tetszés szerint változtathatják a hátteret.",
"Customize" : "Testreszabás",
"Edit widgets" : "Modulok szerkesztése",
"Get more widgets from the App Store" : "További modulok letöltése az alkalmazástárból.",
diff --git a/apps/dashboard/l10n/hu.json b/apps/dashboard/l10n/hu.json
index 68b49daf28a..366388bcaa2 100644
--- a/apps/dashboard/l10n/hu.json
+++ b/apps/dashboard/l10n/hu.json
@@ -1,6 +1,7 @@
{ "translations": {
"Dashboard" : "Irányítópult",
"Dashboard app" : "Irányítópult alkalmazás",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an\noverview of your upcoming appointments, urgent emails, chat messages,\nincoming tickets, latest tweets and much more! Users can add the widgets\nthey like and change the background to their liking." : "Kezdje informáltan a napot\n\nA Nextcloud irányítópult a napja kezdőpontja, áttekintést nyújtva a közelgő találkozókról, sürgős levelekről, csevegőüzenetekről, hibajegyekről, a legfrissebb tweetekről és sok másról. A felhasználók modulokat adhatnak hozzá, és tetszés szerint változtathatják a hátteret.",
"Customize" : "Testreszabás",
"Edit widgets" : "Modulok szerkesztése",
"Get more widgets from the App Store" : "További modulok letöltése az alkalmazástárból.",
diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php
index 55c3f16135a..5f7815a9bfc 100644
--- a/apps/dav/composer/composer/autoload_classmap.php
+++ b/apps/dav/composer/composer/autoload_classmap.php
@@ -145,6 +145,7 @@ return array(
'OCA\\DAV\\Connector\\Sabre\\BlockLegacyClientPlugin' => $baseDir . '/../lib/Connector/Sabre/BlockLegacyClientPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\CachingTree' => $baseDir . '/../lib/Connector/Sabre/CachingTree.php',
'OCA\\DAV\\Connector\\Sabre\\ChecksumList' => $baseDir . '/../lib/Connector/Sabre/ChecksumList.php',
+ 'OCA\\DAV\\Connector\\Sabre\\ChecksumUpdatePlugin' => $baseDir . '/../lib/Connector/Sabre/ChecksumUpdatePlugin.php',
'OCA\\DAV\\Connector\\Sabre\\CommentPropertiesPlugin' => $baseDir . '/../lib/Connector/Sabre/CommentPropertiesPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\CopyEtagHeaderPlugin' => $baseDir . '/../lib/Connector/Sabre/CopyEtagHeaderPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\DavAclPlugin' => $baseDir . '/../lib/Connector/Sabre/DavAclPlugin.php',
@@ -272,6 +273,7 @@ return array(
'OCA\\DAV\\Migration\\Version1016Date20201109085907' => $baseDir . '/../lib/Migration/Version1016Date20201109085907.php',
'OCA\\DAV\\Migration\\Version1017Date20210216083742' => $baseDir . '/../lib/Migration/Version1017Date20210216083742.php',
'OCA\\DAV\\Migration\\Version1018Date20210312100735' => $baseDir . '/../lib/Migration/Version1018Date20210312100735.php',
+ 'OCA\\DAV\\Profiler\\ProfilerPlugin' => $baseDir . '/../lib/Profiler/ProfilerPlugin.php',
'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningNode' => $baseDir . '/../lib/Provisioning/Apple/AppleProvisioningNode.php',
'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningPlugin' => $baseDir . '/../lib/Provisioning/Apple/AppleProvisioningPlugin.php',
'OCA\\DAV\\RootCollection' => $baseDir . '/../lib/RootCollection.php',
diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php
index da68370094e..1f57b8b043a 100644
--- a/apps/dav/composer/composer/autoload_static.php
+++ b/apps/dav/composer/composer/autoload_static.php
@@ -160,6 +160,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Connector\\Sabre\\BlockLegacyClientPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/BlockLegacyClientPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\CachingTree' => __DIR__ . '/..' . '/../lib/Connector/Sabre/CachingTree.php',
'OCA\\DAV\\Connector\\Sabre\\ChecksumList' => __DIR__ . '/..' . '/../lib/Connector/Sabre/ChecksumList.php',
+ 'OCA\\DAV\\Connector\\Sabre\\ChecksumUpdatePlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/ChecksumUpdatePlugin.php',
'OCA\\DAV\\Connector\\Sabre\\CommentPropertiesPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/CommentPropertiesPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\CopyEtagHeaderPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/CopyEtagHeaderPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\DavAclPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/DavAclPlugin.php',
@@ -287,6 +288,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Migration\\Version1016Date20201109085907' => __DIR__ . '/..' . '/../lib/Migration/Version1016Date20201109085907.php',
'OCA\\DAV\\Migration\\Version1017Date20210216083742' => __DIR__ . '/..' . '/../lib/Migration/Version1017Date20210216083742.php',
'OCA\\DAV\\Migration\\Version1018Date20210312100735' => __DIR__ . '/..' . '/../lib/Migration/Version1018Date20210312100735.php',
+ 'OCA\\DAV\\Profiler\\ProfilerPlugin' => __DIR__ . '/..' . '/../lib/Profiler/ProfilerPlugin.php',
'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningNode' => __DIR__ . '/..' . '/../lib/Provisioning/Apple/AppleProvisioningNode.php',
'OCA\\DAV\\Provisioning\\Apple\\AppleProvisioningPlugin' => __DIR__ . '/..' . '/../lib/Provisioning/Apple/AppleProvisioningPlugin.php',
'OCA\\DAV\\RootCollection' => __DIR__ . '/..' . '/../lib/RootCollection.php',
diff --git a/apps/dav/l10n/de.js b/apps/dav/l10n/de.js
index 170f4bd6495..aeaa3de4ca4 100644
--- a/apps/dav/l10n/de.js
+++ b/apps/dav/l10n/de.js
@@ -161,6 +161,8 @@ OC.L10N.register(
"Hence they will not be available immediately after enabling but will show up after some time." : "Die Einträge werden nicht sofort angezeigt. Nach der Aktivierung wird es ein wenig dauern bis zur Anzeige.",
"Send notifications for events" : "Sende Benachrichtigungen für Termine",
"Notifications are sent via background jobs, so these must occur often enough." : "Benachrichtigungen werden von Hintergrundjobs versendet, so dass diese häufig genug ausgeführt werden müssen.",
+ "Send reminder notifications to calendar sharees as well" : "Erinnerungsbenachrichtigungen auch an die freigegebenen Kalender senden",
+ "Reminders are always sent to organizers and attendees." : "Erinnerungen werden immer an Organisatoren und Teilnehmer gesendet.",
"Enable notifications for events via push" : "Benachrichtigungen für Termine per Push aktivieren",
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Installiere außerdem die {calendarappstoreopen}Kalender-App{linkclose} oder {calendardocopen}verbinde Deinen Desktop & Mobilgerät zur Synchronisierung ↗{linkclose}.",
"Please make sure to properly set up {emailopen}the email server{linkclose}." : "Bitte stelle sicher, dass Du {emailopen}den E-Mail Server{linkclose} ordnungsgemäß einrichtest.",
diff --git a/apps/dav/l10n/de.json b/apps/dav/l10n/de.json
index c9f193288f3..885e1d922eb 100644
--- a/apps/dav/l10n/de.json
+++ b/apps/dav/l10n/de.json
@@ -159,6 +159,8 @@
"Hence they will not be available immediately after enabling but will show up after some time." : "Die Einträge werden nicht sofort angezeigt. Nach der Aktivierung wird es ein wenig dauern bis zur Anzeige.",
"Send notifications for events" : "Sende Benachrichtigungen für Termine",
"Notifications are sent via background jobs, so these must occur often enough." : "Benachrichtigungen werden von Hintergrundjobs versendet, so dass diese häufig genug ausgeführt werden müssen.",
+ "Send reminder notifications to calendar sharees as well" : "Erinnerungsbenachrichtigungen auch an die freigegebenen Kalender senden",
+ "Reminders are always sent to organizers and attendees." : "Erinnerungen werden immer an Organisatoren und Teilnehmer gesendet.",
"Enable notifications for events via push" : "Benachrichtigungen für Termine per Push aktivieren",
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Installiere außerdem die {calendarappstoreopen}Kalender-App{linkclose} oder {calendardocopen}verbinde Deinen Desktop & Mobilgerät zur Synchronisierung ↗{linkclose}.",
"Please make sure to properly set up {emailopen}the email server{linkclose}." : "Bitte stelle sicher, dass Du {emailopen}den E-Mail Server{linkclose} ordnungsgemäß einrichtest.",
diff --git a/apps/dav/l10n/pt_BR.js b/apps/dav/l10n/pt_BR.js
index 9c27b589fe3..bd1c369268d 100644
--- a/apps/dav/l10n/pt_BR.js
+++ b/apps/dav/l10n/pt_BR.js
@@ -108,6 +108,23 @@ OC.L10N.register(
"{actor} updated contact {card} in address book {addressbook}" : "{actor} updated contact {card} no livro de endereço {addressbook}",
"You updated contact {card} in address book {addressbook}" : "Você atualizou o contato {card} no livro de endereços {addressbook}",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "O <strong>contato</strong> ou <strong>livro de endereço</strong> foi modificado",
+ "File is not updatable: %1$s" : "O arquivo não é atualizável: %1$s",
+ "Could not write to final file, canceled by hook" : "Não foi possível gravar no arquivo final, cancelado pelo gancho",
+ "Could not write file contents" : "Não foi possível gravar o conteúdo do arquivo",
+ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
+ "Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Erro ao copiar o arquivo para o local de destino (copiado: %1$s, tamanho de arquivo esperado: %2$s)",
+ "Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "Tamanho de arquivo esperado de %1$s mas lido (do cliente Nextcloud) e gravado (no armazenamento Nextcloud) %2$s. Pode ser um problema de rede no lado de envio ou um problema de gravação no armazenamento no lado do servidor.",
+ "Could not rename part file to final file, canceled by hook" : "Não foi possível renomear o arquivo de parte para o arquivo final, cancelado pelo gancho",
+ "Could not rename part file to final file" : "Não foi possível renomear o arquivo de parte para o arquivo final",
+ "Failed to check file size: %1$s" : "Falha ao verificar o tamanho do arquivo: %1$s",
+ "Could not open file" : "Não pode abrir o arquivo",
+ "Encryption not ready: %1$s" : "A criptografia não está pronta: %1$s",
+ "Failed to open file: %1$s" : "Falha ao abrir arquivo: %1$s",
+ "Failed to unlink: %1$s" : "Falha ao desvincular: %1$s",
+ "Invalid chunk name" : "Nome do bloco inválido",
+ "Could not rename part file assembled from chunks" : "Não foi possível renomear parte do arquivo montado a partir de pedaços",
+ "Failed to write file contents: %1$s" : "Falha ao gravar o conteúdo do arquivo:%1$s",
+ "File not found: %1$s" : "Arquivo não encontrado:%1$s",
"System is in maintenance mode." : "O sistema está em modo de manutenção",
"Upgrade needed" : "Upgrade necessário",
"Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Seu %s precisa estar configurado para usar HTTPS a fim de usar o CalDAV e o CardDAV com o iOS/macOS.",
diff --git a/apps/dav/l10n/pt_BR.json b/apps/dav/l10n/pt_BR.json
index 4b497d13741..ffa2f55511e 100644
--- a/apps/dav/l10n/pt_BR.json
+++ b/apps/dav/l10n/pt_BR.json
@@ -106,6 +106,23 @@
"{actor} updated contact {card} in address book {addressbook}" : "{actor} updated contact {card} no livro de endereço {addressbook}",
"You updated contact {card} in address book {addressbook}" : "Você atualizou o contato {card} no livro de endereços {addressbook}",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "O <strong>contato</strong> ou <strong>livro de endereço</strong> foi modificado",
+ "File is not updatable: %1$s" : "O arquivo não é atualizável: %1$s",
+ "Could not write to final file, canceled by hook" : "Não foi possível gravar no arquivo final, cancelado pelo gancho",
+ "Could not write file contents" : "Não foi possível gravar o conteúdo do arquivo",
+ "_%n byte_::_%n bytes_" : ["%n byte","%n bytes"],
+ "Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Erro ao copiar o arquivo para o local de destino (copiado: %1$s, tamanho de arquivo esperado: %2$s)",
+ "Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "Tamanho de arquivo esperado de %1$s mas lido (do cliente Nextcloud) e gravado (no armazenamento Nextcloud) %2$s. Pode ser um problema de rede no lado de envio ou um problema de gravação no armazenamento no lado do servidor.",
+ "Could not rename part file to final file, canceled by hook" : "Não foi possível renomear o arquivo de parte para o arquivo final, cancelado pelo gancho",
+ "Could not rename part file to final file" : "Não foi possível renomear o arquivo de parte para o arquivo final",
+ "Failed to check file size: %1$s" : "Falha ao verificar o tamanho do arquivo: %1$s",
+ "Could not open file" : "Não pode abrir o arquivo",
+ "Encryption not ready: %1$s" : "A criptografia não está pronta: %1$s",
+ "Failed to open file: %1$s" : "Falha ao abrir arquivo: %1$s",
+ "Failed to unlink: %1$s" : "Falha ao desvincular: %1$s",
+ "Invalid chunk name" : "Nome do bloco inválido",
+ "Could not rename part file assembled from chunks" : "Não foi possível renomear parte do arquivo montado a partir de pedaços",
+ "Failed to write file contents: %1$s" : "Falha ao gravar o conteúdo do arquivo:%1$s",
+ "File not found: %1$s" : "Arquivo não encontrado:%1$s",
"System is in maintenance mode." : "O sistema está em modo de manutenção",
"Upgrade needed" : "Upgrade necessário",
"Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Seu %s precisa estar configurado para usar HTTPS a fim de usar o CalDAV e o CardDAV com o iOS/macOS.",
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index d949f32c1fc..f0d332adab5 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -97,6 +97,7 @@ use Sabre\VObject\Reader;
use Sabre\VObject\Recur\EventIterator;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
+use function array_column;
use function array_merge;
use function array_values;
use function explode;
@@ -104,6 +105,7 @@ use function is_array;
use function is_resource;
use function pathinfo;
use function rewind;
+use function settype;
use function sprintf;
use function str_replace;
use function strtolower;
@@ -142,20 +144,19 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
public const CLASSIFICATION_CONFIDENTIAL = 2;
/**
- * List of CalDAV properties, and how they map to database field names
+ * List of CalDAV properties, and how they map to database field names and their type
* Add your own properties by simply adding on to this array.
*
- * Note that only string-based properties are supported here.
- *
* @var array
+ * @psalm-var array<string, string[]>
*/
public $propertyMap = [
- '{DAV:}displayname' => 'displayname',
- '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'description',
- '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => 'timezone',
- '{http://apple.com/ns/ical/}calendar-order' => 'calendarorder',
- '{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor',
- '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => 'deleted_at',
+ '{DAV:}displayname' => ['displayname', 'string'],
+ '{urn:ietf:params:xml:ns:caldav}calendar-description' => ['description', 'string'],
+ '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => ['timezone', 'string'],
+ '{http://apple.com/ns/ical/}calendar-order' => ['calendarorder', 'int'],
+ '{http://apple.com/ns/ical/}calendar-color' => ['calendarcolor', 'string'],
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => ['deleted_at', 'int'],
];
/**
@@ -164,13 +165,13 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* @var array
*/
public $subscriptionPropertyMap = [
- '{DAV:}displayname' => 'displayname',
- '{http://apple.com/ns/ical/}refreshrate' => 'refreshrate',
- '{http://apple.com/ns/ical/}calendar-order' => 'calendarorder',
- '{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor',
- '{http://calendarserver.org/ns/}subscribed-strip-todos' => 'striptodos',
- '{http://calendarserver.org/ns/}subscribed-strip-alarms' => 'stripalarms',
- '{http://calendarserver.org/ns/}subscribed-strip-attachments' => 'stripattachments',
+ '{DAV:}displayname' => ['displayname', 'string'],
+ '{http://apple.com/ns/ical/}refreshrate' => ['refreshrate', 'string'],
+ '{http://apple.com/ns/ical/}calendar-order' => ['calendarorder', 'int'],
+ '{http://apple.com/ns/ical/}calendar-color' => ['calendarcolor', 'string'],
+ '{http://calendarserver.org/ns/}subscribed-strip-todos' => ['striptodos', 'bool'],
+ '{http://calendarserver.org/ns/}subscribed-strip-alarms' => ['stripalarms', 'string'],
+ '{http://calendarserver.org/ns/}subscribed-strip-attachments' => ['stripattachments', 'string'],
];
/**
@@ -351,7 +352,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
public function getCalendarsForUser($principalUri) {
$principalUriOriginal = $principalUri;
$principalUri = $this->convertPrincipal($principalUri, true);
- $fields = array_values($this->propertyMap);
+ $fields = array_column($this->propertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
$fields[] = 'synctoken';
@@ -392,10 +393,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}owner-principal' => $this->convertPrincipal($principalUri, !$this->legacyEndpoint),
];
- foreach ($this->propertyMap as $xmlName => $dbName) {
- $calendar[$xmlName] = $row[$dbName];
- }
-
+ $calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);
@@ -411,7 +409,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$principals[] = $principalUri;
- $fields = array_values($this->propertyMap);
+ $fields = array_column($this->propertyMap, 0);
$fields[] = 'a.id';
$fields[] = 'a.uri';
$fields[] = 'a.synctoken';
@@ -469,10 +467,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$readOnlyPropertyName => $readOnly,
];
- foreach ($this->propertyMap as $xmlName => $dbName) {
- $calendar[$xmlName] = $row[$dbName];
- }
-
+ $calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);
@@ -489,7 +484,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
*/
public function getUsersOwnCalendars($principalUri) {
$principalUri = $this->convertPrincipal($principalUri, true);
- $fields = array_values($this->propertyMap);
+ $fields = array_column($this->propertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
$fields[] = 'synctoken';
@@ -518,10 +513,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'{' . Plugin::NS_CALDAV . '}supported-calendar-component-set' => new SupportedCalendarComponentSet($components),
'{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'),
];
- foreach ($this->propertyMap as $xmlName => $dbName) {
- $calendar[$xmlName] = $row[$dbName];
- }
+ $calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);
@@ -556,7 +549,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* @return array
*/
public function getPublicCalendars() {
- $fields = array_values($this->propertyMap);
+ $fields = array_column($this->propertyMap, 0);
$fields[] = 'a.id';
$fields[] = 'a.uri';
$fields[] = 'a.synctoken';
@@ -595,10 +588,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}public' => (int)$row['access'] === self::ACCESS_PUBLIC,
];
- foreach ($this->propertyMap as $xmlName => $dbName) {
- $calendar[$xmlName] = $row[$dbName];
- }
-
+ $calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);
@@ -617,7 +607,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* @throws NotFound
*/
public function getPublicCalendar($uri) {
- $fields = array_values($this->propertyMap);
+ $fields = array_column($this->propertyMap, 0);
$fields[] = 'a.id';
$fields[] = 'a.uri';
$fields[] = 'a.synctoken';
@@ -663,10 +653,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'{' . \OCA\DAV\DAV\Sharing\Plugin::NS_OWNCLOUD . '}public' => (int)$row['access'] === self::ACCESS_PUBLIC,
];
- foreach ($this->propertyMap as $xmlName => $dbName) {
- $calendar[$xmlName] = $row[$dbName];
- }
-
+ $calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);
@@ -679,7 +666,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* @return array|null
*/
public function getCalendarByUri($principal, $uri) {
- $fields = array_values($this->propertyMap);
+ $fields = array_column($this->propertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
$fields[] = 'synctoken';
@@ -717,10 +704,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'),
];
- foreach ($this->propertyMap as $xmlName => $dbName) {
- $calendar[$xmlName] = $row[$dbName];
- }
-
+ $calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);
@@ -732,7 +716,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* @return array|null
*/
public function getCalendarById($calendarId) {
- $fields = array_values($this->propertyMap);
+ $fields = array_column($this->propertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
$fields[] = 'synctoken';
@@ -769,10 +753,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'{' . Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'),
];
- foreach ($this->propertyMap as $xmlName => $dbName) {
- $calendar[$xmlName] = $row[$dbName];
- }
-
+ $calendar = $this->rowToCalendar($row, $calendar);
$calendar = $this->addOwnerPrincipalToCalendar($calendar);
$calendar = $this->addResourceTypeToCalendar($row, $calendar);
@@ -783,7 +764,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* @param $subscriptionId
*/
public function getSubscriptionById($subscriptionId) {
- $fields = array_values($this->subscriptionPropertyMap);
+ $fields = array_column($this->subscriptionPropertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
$fields[] = 'source';
@@ -815,13 +796,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0',
];
- foreach ($this->subscriptionPropertyMap as $xmlName => $dbName) {
- if (!is_null($row[$dbName])) {
- $subscription[$xmlName] = $row[$dbName];
- }
- }
-
- return $subscription;
+ return $this->rowToSubscription($row, $subscription);
}
/**
@@ -863,7 +838,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$values['transparent'] = (int) ($properties[$transp]->getValue() === 'transparent');
}
- foreach ($this->propertyMap as $xmlName => $dbName) {
+ foreach ($this->propertyMap as $xmlName => [$dbName, $type]) {
if (isset($properties[$xmlName])) {
$values[$dbName] = $properties[$xmlName];
}
@@ -912,7 +887,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$newValues[$fieldName] = (int) ($propertyValue->getValue() === 'transparent');
break;
default:
- $fieldName = $this->propertyMap[$propertyName];
+ $fieldName = $this->propertyMap[$propertyName][0];
$newValues[$fieldName] = $propertyValue;
break;
}
@@ -1109,7 +1084,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'size' => (int) $row['size'],
'component' => strtolower($row['componenttype']),
'classification' => (int) $row['classification'],
- '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'],
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'] === null ? $row['deleted_at'] : (int) $row['deleted_at'],
];
}
$stmt->closeCursor();
@@ -1148,7 +1123,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'size' => (int)$row['size'],
'component' => strtolower($row['componenttype']),
'classification' => (int)$row['classification'],
- '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'],
+ '{' . \OCA\DAV\DAV\Sharing\Plugin::NS_NEXTCLOUD . '}deleted-at' => $row['deleted_at'] === null ? $row['deleted_at'] : (int) $row['deleted_at'],
];
}
$stmt->closeCursor();
@@ -2452,7 +2427,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
* @return array
*/
public function getSubscriptionsForUser($principalUri) {
- $fields = array_values($this->subscriptionPropertyMap);
+ $fields = array_column($this->subscriptionPropertyMap, 0);
$fields[] = 'id';
$fields[] = 'uri';
$fields[] = 'source';
@@ -2480,13 +2455,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
'{http://sabredav.org/ns}sync-token' => $row['synctoken']?$row['synctoken']:'0',
];
- foreach ($this->subscriptionPropertyMap as $xmlName => $dbName) {
- if (!is_null($row[$dbName])) {
- $subscription[$xmlName] = $row[$dbName];
- }
- }
-
- $subscriptions[] = $subscription;
+ $subscriptions[] = $this->rowToSubscription($row, $subscription);
}
return $subscriptions;
@@ -2517,7 +2486,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$propertiesBoolean = ['striptodos', 'stripalarms', 'stripattachments'];
- foreach ($this->subscriptionPropertyMap as $xmlName => $dbName) {
+ foreach ($this->subscriptionPropertyMap as $xmlName => [$dbName, $type]) {
if (array_key_exists($xmlName, $properties)) {
$values[$dbName] = $properties[$xmlName];
if (in_array($dbName, $propertiesBoolean)) {
@@ -2579,7 +2548,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
if ($propertyName === '{http://calendarserver.org/ns/}source') {
$newValues['source'] = $propertyValue->getHref();
} else {
- $fieldName = $this->subscriptionPropertyMap[$propertyName];
+ $fieldName = $this->subscriptionPropertyMap[$propertyName][0];
$newValues[$fieldName] = $propertyValue;
}
}
@@ -3263,4 +3232,42 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
}
return $calendar;
}
+
+ /**
+ * Amend the calendar info with database row data
+ *
+ * @param array $row
+ * @param array $calendar
+ *
+ * @return array
+ */
+ private function rowToCalendar($row, array $calendar): array {
+ foreach ($this->propertyMap as $xmlName => [$dbName, $type]) {
+ $value = $row[$dbName];
+ if ($value !== null) {
+ settype($value, $type);
+ }
+ $calendar[$xmlName] = $value;
+ }
+ return $calendar;
+ }
+
+ /**
+ * Amend the subscription info with database row data
+ *
+ * @param array $row
+ * @param array $subscription
+ *
+ * @return array
+ */
+ private function rowToSubscription($row, array $subscription): array {
+ foreach ($this->subscriptionPropertyMap as $xmlName => [$dbName, $type]) {
+ $value = $row[$dbName];
+ if ($value !== null) {
+ settype($value, $type);
+ }
+ $subscription[$xmlName] = $value;
+ }
+ return $subscription;
+ }
}
diff --git a/apps/dav/lib/Connector/Sabre/ChecksumUpdatePlugin.php b/apps/dav/lib/Connector/Sabre/ChecksumUpdatePlugin.php
new file mode 100644
index 00000000000..3247259357f
--- /dev/null
+++ b/apps/dav/lib/Connector/Sabre/ChecksumUpdatePlugin.php
@@ -0,0 +1,83 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2021 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\DAV\Connector\Sabre;
+
+use Sabre\DAV\ServerPlugin;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+
+class ChecksumUpdatePlugin extends ServerPlugin {
+ /**
+ * @var \Sabre\DAV\Server
+ */
+ protected $server;
+
+ public function initialize(\Sabre\DAV\Server $server) {
+ $this->server = $server;
+ $server->on('method:PATCH', [$this, 'httpPatch']);
+ }
+
+ public function getPluginName(): string {
+ return 'checksumupdate';
+ }
+
+ public function getHTTPMethods($path): array {
+ $tree = $this->server->tree;
+
+ if ($tree->nodeExists($path)) {
+ $node = $tree->getNodeForPath($path);
+ if ($node instanceof File) {
+ return ['PATCH'];
+ }
+ }
+
+ return [];
+ }
+
+ public function getFeatures(): array {
+ return ['nextcloud-checksum-update'];
+ }
+
+ public function httpPatch(RequestInterface $request, ResponseInterface $response) {
+ $path = $request->getPath();
+
+ $node = $this->server->tree->getNodeForPath($path);
+ if ($node instanceof File) {
+ $type = strtolower(
+ (string)$request->getHeader('X-Recalculate-Hash')
+ );
+
+ $hash = $node->hash($type);
+ if ($hash) {
+ $checksum = strtoupper($type) . ':' . $hash;
+ $node->setChecksum($checksum);
+ $response->addHeader('OC-Checksum', $checksum);
+ $response->setHeader('Content-Length', '0');
+ $response->setStatus(204);
+
+ return false;
+ }
+ }
+ }
+}
diff --git a/apps/dav/lib/Connector/Sabre/Directory.php b/apps/dav/lib/Connector/Sabre/Directory.php
index 3ae4416d363..8b616b0cb8a 100644
--- a/apps/dav/lib/Connector/Sabre/Directory.php
+++ b/apps/dav/lib/Connector/Sabre/Directory.php
@@ -38,6 +38,7 @@ use OCA\DAV\Connector\Sabre\Exception\FileLocked;
use OCA\DAV\Connector\Sabre\Exception\Forbidden;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
use OCP\Files\FileInfo;
+use OCP\Files\Folder;
use OCP\Files\ForbiddenException;
use OCP\Files\InvalidPathException;
use OCP\Files\NotPermittedException;
@@ -144,7 +145,9 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node implements \Sabre\DAV\ICol
$info = $this->fileView->getFileInfo($this->path . '/' . $name);
if (!$info) {
// use a dummy FileInfo which is acceptable here since it will be refreshed after the put is complete
- $info = new \OC\Files\FileInfo($path, null, null, [], null);
+ $info = new \OC\Files\FileInfo($path, null, null, [
+ 'type' => FileInfo::TYPE_FILE
+ ], null);
}
$node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
@@ -233,7 +236,7 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node implements \Sabre\DAV\ICol
throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
}
- if ($info['mimetype'] === 'httpd/unix-directory') {
+ if ($info->getMimeType() === FileInfo::MIMETYPE_FOLDER) {
$node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this->tree, $this->shareManager);
} else {
$node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info, $this->shareManager);
@@ -261,7 +264,7 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node implements \Sabre\DAV\ICol
// the caller believe that the collection itself does not exist
throw new Forbidden('No read permissions');
}
- $folderContent = $this->fileView->getDirectoryContent($this->path);
+ $folderContent = $this->getNode()->getDirectoryListing();
} catch (LockedException $e) {
throw new Locked();
}
@@ -327,8 +330,7 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node implements \Sabre\DAV\ICol
return $this->quotaInfo;
}
try {
- $info = $this->fileView->getFileInfo($this->path, false);
- $storageInfo = \OC_Helper::getStorageInfo($this->info->getPath(), $info);
+ $storageInfo = \OC_Helper::getStorageInfo($this->info->getPath(), $this->info, false);
if ($storageInfo['quota'] === \OCP\Files\FileInfo::SPACE_UNLIMITED) {
$free = \OCP\Files\FileInfo::SPACE_UNLIMITED;
} else {
@@ -475,4 +477,8 @@ class Directory extends \OCA\DAV\Connector\Sabre\Node implements \Sabre\DAV\ICol
return false;
}
+
+ public function getNode(): Folder {
+ return $this->node;
+ }
}
diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php
index 4768fc3dc44..a46ca372be7 100644
--- a/apps/dav/lib/Connector/Sabre/File.php
+++ b/apps/dav/lib/Connector/Sabre/File.php
@@ -388,11 +388,9 @@ class File extends Node implements IFile {
if (isset($this->request->server['HTTP_OC_CHECKSUM'])) {
$checksum = trim($this->request->server['HTTP_OC_CHECKSUM']);
- $this->fileView->putFileInfo($this->path, ['checksum' => $checksum]);
- $this->refreshInfo();
+ $this->setChecksum($checksum);
} elseif ($this->getChecksum() !== null && $this->getChecksum() !== '') {
- $this->fileView->putFileInfo($this->path, ['checksum' => '']);
- $this->refreshInfo();
+ $this->setChecksum('');
}
} catch (StorageNotAvailableException $e) {
throw new ServiceUnavailable($this->l10n->t('Failed to check file size: %1$s', [$e->getMessage()]), 0, $e);
@@ -741,9 +739,22 @@ class File extends Node implements IFile {
return $this->info->getChecksum();
}
+ public function setChecksum(string $checksum) {
+ $this->fileView->putFileInfo($this->path, ['checksum' => $checksum]);
+ $this->refreshInfo();
+ }
+
protected function header($string) {
if (!\OC::$CLI) {
\header($string);
}
}
+
+ public function hash(string $type) {
+ return $this->fileView->hash($type, $this->path);
+ }
+
+ public function getNode(): \OCP\Files\File {
+ return $this->node;
+ }
}
diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
index 017b1d31841..180f05c0e7e 100644
--- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
@@ -291,6 +291,7 @@ class FilesPlugin extends ServerPlugin {
$response->addHeader('OC-Checksum', $checksum);
}
}
+ $response->addHeader('X-Accel-Buffering', 'no');
}
/**
diff --git a/apps/dav/lib/Connector/Sabre/Node.php b/apps/dav/lib/Connector/Sabre/Node.php
index 79b4db0e327..e4517068f42 100644
--- a/apps/dav/lib/Connector/Sabre/Node.php
+++ b/apps/dav/lib/Connector/Sabre/Node.php
@@ -36,9 +36,12 @@
namespace OCA\DAV\Connector\Sabre;
use OC\Files\Mount\MoveableMount;
+use OC\Files\Node\File;
+use OC\Files\Node\Folder;
use OC\Files\View;
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
use OCP\Files\FileInfo;
+use OCP\Files\IRootFolder;
use OCP\Files\StorageNotAvailableException;
use OCP\Share\IShare;
use OCP\Share\Exceptions\ShareNotFound;
@@ -75,6 +78,8 @@ abstract class Node implements \Sabre\DAV\INode {
*/
protected $shareManager;
+ protected \OCP\Files\Node $node;
+
/**
* Sets up the node, expects a full path name
*
@@ -91,10 +96,26 @@ abstract class Node implements \Sabre\DAV\INode {
} else {
$this->shareManager = \OC::$server->getShareManager();
}
+ if ($info instanceof Folder || $info instanceof File) {
+ $this->node = $info;
+ } else {
+ $root = \OC::$server->get(IRootFolder::class);
+ if ($info->getType() === FileInfo::TYPE_FOLDER) {
+ $this->node = new Folder($root, $view, $this->path, $info);
+ } else {
+ $this->node = new File($root, $view, $this->path, $info);
+ }
+ }
}
protected function refreshInfo() {
$this->info = $this->fileView->getFileInfo($this->path);
+ $root = \OC::$server->get(IRootFolder::class);
+ if ($this->info->getType() === FileInfo::TYPE_FOLDER) {
+ $this->node = new Folder($root, $this->fileView, $this->path, $this->info);
+ } else {
+ $this->node = new File($root, $this->fileView, $this->path, $this->info);
+ }
}
/**
@@ -403,6 +424,10 @@ abstract class Node implements \Sabre\DAV\INode {
return $this->info;
}
+ public function getNode(): \OCP\Files\Node {
+ return $this->node;
+ }
+
protected function sanitizeMtime($mtimeFromRequest) {
return MtimeSanitizer::sanitizeMtime($mtimeFromRequest);
}
diff --git a/apps/dav/lib/Connector/Sabre/ServerFactory.php b/apps/dav/lib/Connector/Sabre/ServerFactory.php
index 095fb631c2b..b13dbd20ca9 100644
--- a/apps/dav/lib/Connector/Sabre/ServerFactory.php
+++ b/apps/dav/lib/Connector/Sabre/ServerFactory.php
@@ -180,6 +180,7 @@ class ServerFactory {
)
);
$server->addPlugin(new \OCA\DAV\Connector\Sabre\QuotaPlugin($view, true));
+ $server->addPlugin(new \OCA\DAV\Connector\Sabre\ChecksumUpdatePlugin());
if ($this->userSession->isLoggedIn()) {
$server->addPlugin(new \OCA\DAV\Connector\Sabre\TagsPlugin($objectTree, $this->tagManager));
diff --git a/apps/dav/lib/Connector/Sabre/SharesPlugin.php b/apps/dav/lib/Connector/Sabre/SharesPlugin.php
index d482aa4b510..57c91e05a8c 100644
--- a/apps/dav/lib/Connector/Sabre/SharesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/SharesPlugin.php
@@ -165,7 +165,7 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin {
// if we already cached the folder this file is in we know there are no shares for this file
if (array_search($parentPath, $this->cachedFolders) === false) {
try {
- $node = $this->userFolder->get($sabreNode->getPath());
+ $node = $sabreNode->getNode();
} catch (NotFoundException $e) {
return [];
}
@@ -201,18 +201,7 @@ class SharesPlugin extends \Sabre\DAV\ServerPlugin {
!is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME))
)
) {
- try {
- $folderNode = $this->userFolder->get($sabreNode->getPath());
- } catch (NotFoundException $e) {
- // If the folder can't be properly found just return
- return;
- }
-
- if (!($folderNode instanceof Folder)) {
- // Safety check
- return;
- }
-
+ $folderNode = $sabreNode->getNode();
$this->cachedFolders[] = $sabreNode->getPath();
$childShares = $this->getSharesFolder($folderNode);
foreach ($childShares as $id => $shares) {
diff --git a/apps/dav/lib/Profiler/ProfilerPlugin.php b/apps/dav/lib/Profiler/ProfilerPlugin.php
new file mode 100644
index 00000000000..672ca4010b7
--- /dev/null
+++ b/apps/dav/lib/Profiler/ProfilerPlugin.php
@@ -0,0 +1,47 @@
+<?php declare(strict_types = 1);
+/**
+ * @copyright 2021 Carl Schwan <carl@carlschwan.eu>
+ *
+ * @author Carl Schwan <carl@carlschwan.eu>
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\DAV\Profiler;
+
+use OCP\IRequest;
+use Sabre\DAV\Server;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+
+class ProfilerPlugin extends \Sabre\DAV\ServerPlugin {
+ private IRequest $request;
+
+ public function __construct(IRequest $request) {
+ $this->request = $request;
+ }
+
+ /** @return void */
+ public function initialize(Server $server) {
+ $server->on('afterMethod:*', [$this, 'afterMethod']);
+ }
+
+ /** @return void */
+ public function afterMethod(RequestInterface $request, ResponseInterface $response) {
+ $response->addHeader('X-Debug-Token', $this->request->getId());
+ }
+}
diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php
index 759d39c0233..589e6c2bd6c 100644
--- a/apps/dav/lib/Server.php
+++ b/apps/dav/lib/Server.php
@@ -36,6 +36,9 @@ namespace OCA\DAV;
use OCA\DAV\Connector\Sabre\RequestIdHeaderPlugin;
use OCP\Diagnostics\IEventLogger;
+use OCP\Profiler\IProfiler;
+use OCA\DAV\Profiler\ProfilerPlugin;
+use OCP\AppFramework\Http\Response;
use Psr\Log\LoggerInterface;
use OCA\DAV\AppInfo\PluginManager;
use OCA\DAV\CalDAV\BirthdayService;
@@ -49,6 +52,7 @@ use OCA\DAV\Connector\Sabre\Auth;
use OCA\DAV\Connector\Sabre\BearerAuth;
use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin;
use OCA\DAV\Connector\Sabre\CachingTree;
+use OCA\DAV\Connector\Sabre\ChecksumUpdatePlugin;
use OCA\DAV\Connector\Sabre\CommentPropertiesPlugin;
use OCA\DAV\Connector\Sabre\CopyEtagHeaderPlugin;
use OCA\DAV\Connector\Sabre\DavAclPlugin;
@@ -78,17 +82,19 @@ use Sabre\DAV\UUIDUtil;
use SearchDAV\DAV\SearchPlugin;
class Server {
+ private IRequest $request;
+ private string $baseUri;
+ public Connector\Sabre\Server $server;
+ private IProfiler $profiler;
+
+ public function __construct(IRequest $request, string $baseUri) {
+ $this->profiler = \OC::$server->get(IProfiler::class);
+ if ($this->profiler->isEnabled()) {
+ /** @var IEventLogger $eventLogger */
+ $eventLogger = \OC::$server->get(IEventLogger::class);
+ $eventLogger->start('runtime', 'DAV Runtime');
+ }
- /** @var IRequest */
- private $request;
-
- /** @var string */
- private $baseUri;
-
- /** @var Connector\Sabre\Server */
- public $server;
-
- public function __construct(IRequest $request, $baseUri) {
$this->request = $request;
$this->baseUri = $baseUri;
$logger = \OC::$server->getLogger();
@@ -115,6 +121,7 @@ class Server {
$this->server->httpRequest->setUrl($this->request->getRequestUri());
$this->server->setBaseUri($this->baseUri);
+ $this->server->addPlugin(new ProfilerPlugin($this->request));
$this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig()));
$this->server->addPlugin(new AnonymousOptionsPlugin());
$authPlugin = new Plugin();
@@ -247,6 +254,7 @@ class Server {
!\OC::$server->getConfig()->getSystemValue('debug', false)
)
);
+ $this->server->addPlugin(new ChecksumUpdatePlugin());
$this->server->addPlugin(
new \Sabre\DAV\PropertyStorage\Plugin(
@@ -343,6 +351,11 @@ class Server {
$eventLogger->start('dav_server_exec', '');
$this->server->exec();
$eventLogger->end('dav_server_exec');
+ if ($this->profiler->isEnabled()) {
+ $eventLogger->end('runtime');
+ $profile = $this->profiler->collect(\OC::$server->get(IRequest::class), new Response());
+ $this->profiler->saveProfile($profile);
+ }
}
private function requestIsForSubtree(array $subTrees): bool {
diff --git a/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php b/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php
index 024a6432d01..e8297c2ac66 100644
--- a/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/DirectoryTest.php
@@ -29,6 +29,7 @@
namespace OCA\DAV\Tests\Unit\Connector\Sabre;
use OC\Files\FileInfo;
+use OC\Files\Node\Node;
use OC\Files\Storage\Wrapper\Quota;
use OCA\DAV\Connector\Sabre\Directory;
use OCP\Files\ForbiddenException;
@@ -82,9 +83,12 @@ class DirectoryTest extends \Test\TestCase {
$this->view = $this->createMock('OC\Files\View');
$this->info = $this->createMock('OC\Files\FileInfo');
- $this->info->expects($this->any())
- ->method('isReadable')
+ $this->info->method('isReadable')
->willReturn(true);
+ $this->info->method('getType')
+ ->willReturn(Node::TYPE_FOLDER);
+ $this->info->method('getName')
+ ->willReturn("folder");
}
private function getDir($path = '/') {
@@ -186,17 +190,17 @@ class DirectoryTest extends \Test\TestCase {
$info2 = $this->getMockBuilder(FileInfo::class)
->disableOriginalConstructor()
->getMock();
- $info1->expects($this->any())
- ->method('getName')
+ $info1->method('getName')
->willReturn('first');
- $info1->expects($this->any())
- ->method('getEtag')
+ $info1->method('getPath')
+ ->willReturn('folder/first');
+ $info1->method('getEtag')
->willReturn('abc');
- $info2->expects($this->any())
- ->method('getName')
+ $info2->method('getName')
->willReturn('second');
- $info2->expects($this->any())
- ->method('getEtag')
+ $info2->method('getPath')
+ ->willReturn('folder/second');
+ $info2->method('getEtag')
->willReturn('def');
$this->view->expects($this->once())
@@ -299,10 +303,6 @@ class DirectoryTest extends \Test\TestCase {
->method('getMountPoint')
->willReturn($mountPoint);
- $this->view->expects($this->once())
- ->method('getFileInfo')
- ->willReturn($this->info);
-
$mountPoint->method('getMountPoint')
->willReturn('/user/files/mymountpoint');
@@ -344,10 +344,6 @@ class DirectoryTest extends \Test\TestCase {
$mountPoint->method('getMountPoint')
->willReturn('/user/files/mymountpoint');
- $this->view->expects($this->once())
- ->method('getFileInfo')
- ->willReturn($this->info);
-
$dir = new Directory($this->view, $this->info);
$this->assertEquals([200, 800], $dir->getQuotaInfo()); //200 used, 800 free
}
@@ -411,8 +407,12 @@ class DirectoryTest extends \Test\TestCase {
private function moveTest($source, $destination, $updatables, $deletables) {
$view = new TestViewDirectory($updatables, $deletables);
- $sourceInfo = new FileInfo($source, null, null, [], null);
- $targetInfo = new FileInfo(dirname($destination), null, null, [], null);
+ $sourceInfo = new FileInfo($source, null, null, [
+ 'type' => FileInfo::TYPE_FOLDER,
+ ], null);
+ $targetInfo = new FileInfo(dirname($destination), null, null, [
+ 'type' => FileInfo::TYPE_FOLDER,
+ ], null);
$sourceNode = new Directory($view, $sourceInfo);
$targetNode = $this->getMockBuilder(Directory::class)
@@ -437,8 +437,8 @@ class DirectoryTest extends \Test\TestCase {
$view = new TestViewDirectory($updatables, $deletables);
- $sourceInfo = new FileInfo($source, null, null, [], null);
- $targetInfo = new FileInfo(dirname($destination), null, null, [], null);
+ $sourceInfo = new FileInfo($source, null, null, ['type' => FileInfo::TYPE_FOLDER], null);
+ $targetInfo = new FileInfo(dirname($destination), null, null, ['type' => FileInfo::TYPE_FOLDER], null);
$sourceNode = new Directory($view, $sourceInfo);
$targetNode = $this->getMockBuilder(Directory::class)
diff --git a/apps/dav/tests/unit/Connector/Sabre/FileTest.php b/apps/dav/tests/unit/Connector/Sabre/FileTest.php
index d12a86f6e8d..9870a62845c 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FileTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FileTest.php
@@ -37,6 +37,7 @@ use OC\Files\Storage\Wrapper\PermissionsMask;
use OC\Files\View;
use OCA\DAV\Connector\Sabre\File;
use OCP\Constants;
+use OCP\Files\FileInfo;
use OCP\Files\ForbiddenException;
use OCP\Files\Storage;
use OCP\IConfig;
@@ -211,7 +212,8 @@ class FileTest extends TestCase {
->willReturnArgument(0);
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -272,7 +274,8 @@ class FileTest extends TestCase {
$_SERVER['HTTP_OC_CHUNKED'] = true;
$info = new \OC\Files\FileInfo('/test.txt-chunking-12345-2-0', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -282,7 +285,8 @@ class FileTest extends TestCase {
$file->releaseLock(ILockingProvider::LOCK_SHARED);
$info = new \OC\Files\FileInfo('/test.txt-chunking-12345-2-1', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -326,7 +330,10 @@ class FileTest extends TestCase {
$viewRoot . '/' . ltrim($path, '/'),
$this->getMockStorage(),
null,
- ['permissions' => \OCP\Constants::PERMISSION_ALL],
+ [
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
+ ],
null
);
@@ -690,7 +697,8 @@ class FileTest extends TestCase {
$_SERVER['REQUEST_METHOD'] = 'PUT';
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -723,7 +731,8 @@ class FileTest extends TestCase {
$view->lockFile('/test.txt', ILockingProvider::LOCK_EXCLUSIVE);
$info = new \OC\Files\FileInfo('/' . $this->user . '/files/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -758,7 +767,8 @@ class FileTest extends TestCase {
$_SERVER['HTTP_OC_CHUNKED'] = true;
$info = new \OC\Files\FileInfo('/' . $this->user . '/files/test.txt-chunking-12345-2-0', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
$file->acquireLock(ILockingProvider::LOCK_SHARED);
@@ -766,7 +776,8 @@ class FileTest extends TestCase {
$file->releaseLock(ILockingProvider::LOCK_SHARED);
$info = new \OC\Files\FileInfo('/' . $this->user . '/files/test.txt-chunking-12345-2-1', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -797,7 +808,8 @@ class FileTest extends TestCase {
->willReturnArgument(0);
$info = new \OC\Files\FileInfo('/*', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -836,7 +848,8 @@ class FileTest extends TestCase {
->willReturnArgument(0);
$info = new \OC\Files\FileInfo('/*', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
$file->setName('/super*star.txt');
@@ -863,7 +876,8 @@ class FileTest extends TestCase {
$_SERVER['REQUEST_METHOD'] = 'PUT';
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -897,7 +911,8 @@ class FileTest extends TestCase {
->willReturn(true);
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -915,7 +930,8 @@ class FileTest extends TestCase {
->getMock();
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => 0
+ 'permissions' => 0,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -938,7 +954,8 @@ class FileTest extends TestCase {
->willReturn(false);
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -961,7 +978,8 @@ class FileTest extends TestCase {
->willThrowException(new ForbiddenException('', true));
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -997,7 +1015,10 @@ class FileTest extends TestCase {
'/' . $this->user . '/files/' . $path,
$this->getMockStorage(),
null,
- ['permissions' => \OCP\Constants::PERMISSION_ALL],
+ [
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
+ ],
null
);
@@ -1129,7 +1150,8 @@ class FileTest extends TestCase {
->willReturn(false);
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -1149,7 +1171,8 @@ class FileTest extends TestCase {
->willThrowException(new ForbiddenException('', true));
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_ALL
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -1168,7 +1191,8 @@ class FileTest extends TestCase {
->method('fopen');
$info = new \OC\Files\FileInfo('/test.txt', $this->getMockStorage(), null, [
- 'permissions' => \OCP\Constants::PERMISSION_CREATE // no read perm
+ 'permissions' => \OCP\Constants::PERMISSION_CREATE, // no read perm
+ 'type' => FileInfo::TYPE_FOLDER,
], null);
$file = new \OCA\DAV\Connector\Sabre\File($view, $info);
@@ -1215,7 +1239,10 @@ class FileTest extends TestCase {
'/' . $this->user . '/files/' . $path,
$this->getMockStorage(),
null,
- ['permissions' => \OCP\Constants::PERMISSION_ALL],
+ [
+ 'permissions' => \OCP\Constants::PERMISSION_ALL,
+ 'type' => FileInfo::TYPE_FOLDER,
+ ],
null
);
diff --git a/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
index 201b2b863ab..777a730ffd1 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
@@ -590,9 +590,12 @@ class FilesPluginTest extends TestCase {
->willReturn($isClumsyAgent);
$response
- ->expects($this->once())
+ ->expects($this->exactly(2))
->method('addHeader')
- ->with('Content-Disposition', $contentDispositionHeader);
+ ->withConsecutive(
+ ['Content-Disposition', $contentDispositionHeader],
+ ['X-Accel-Buffering', 'no']
+ );
$this->plugin->httpGet($request, $response);
}
diff --git a/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php b/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php
index 7416cf7a3f7..5f516cec113 100644
--- a/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/ObjectTreeTest.php
@@ -167,17 +167,14 @@ class ObjectTreeTest extends \Test\TestCase {
$fileInfo = $this->getMockBuilder(FileInfo::class)
->disableOriginalConstructor()
->getMock();
- $fileInfo->expects($this->once())
- ->method('getType')
+ $fileInfo->method('getType')
->willReturn($type);
- $fileInfo->expects($this->once())
- ->method('getName')
+ $fileInfo->method('getName')
->willReturn($outputFileName);
$fileInfo->method('getStorage')
->willReturn($this->createMock(\OC\Files\Storage\Common::class));
- $view->expects($this->once())
- ->method('getFileInfo')
+ $view->method('getFileInfo')
->with($fileInfoQueryPath)
->willReturn($fileInfo);
diff --git a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
index f528310e54c..a81226ccb5e 100644
--- a/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/SharesPluginTest.php
@@ -111,9 +111,7 @@ class SharesPluginTest extends \Test\TestCase {
->disableOriginalConstructor()
->getMock();
- $this->userFolder->expects($this->once())
- ->method('get')
- ->with('/subdir')
+ $sabreNode->method('getNode')
->willReturn($node);
$this->shareManager->expects($this->any())
@@ -180,16 +178,19 @@ class SharesPluginTest extends \Test\TestCase {
$node = $this->createMock(Folder::class);
$node->method('getId')
->willReturn(123);
- $node1 = $this->createMock(File::class);
+ $node1 = $this->createMock(\OC\Files\Node\File::class);
$node1->method('getId')
->willReturn(111);
- $node2 = $this->createMock(File::class);
+ $node2 = $this->createMock(\OC\Files\Node\File::class);
$node2->method('getId')
->willReturn(222);
- $this->userFolder->method('get')
- ->with('/subdir')
+ $sabreNode->method('getNode')
->willReturn($node);
+ $sabreNode1->method('getNode')
+ ->willReturn($node1);
+ $sabreNode2->method('getNode')
+ ->willReturn($node2);
$dummyShares = array_map(function ($type) {
$share = $this->getMockBuilder(IShare::class)->getMock();
diff --git a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
index f19e251fc7a..fe0c7a11ab7 100644
--- a/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
+++ b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
@@ -36,6 +36,7 @@ use OCP\AppFramework\OCS\OCSException;
use OCP\AppFramework\OCS\OCSForbiddenException;
use OCP\AppFramework\OCSController;
use OCP\Constants;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException;
use OCP\Federation\Exceptions\ProviderDoesNotExistsException;
use OCP\Federation\ICloudFederationFactory;
@@ -44,6 +45,7 @@ use OCP\Federation\ICloudIdManager;
use OCP\IDBConnection;
use OCP\IRequest;
use OCP\IUserManager;
+use OCP\Log\Audit\CriticalActionPerformedEvent;
use OCP\Share;
use OCP\Share\Exceptions\ShareNotFound;
use Psr\Log\LoggerInterface;
@@ -83,6 +85,9 @@ class RequestHandlerController extends OCSController {
/** @var ICloudFederationProviderManager */
private $cloudFederationProviderManager;
+ /** @var IEventDispatcher */
+ private $eventDispatcher;
+
public function __construct(string $appName,
IRequest $request,
FederatedShareProvider $federatedShareProvider,
@@ -94,7 +99,8 @@ class RequestHandlerController extends OCSController {
ICloudIdManager $cloudIdManager,
LoggerInterface $logger,
ICloudFederationFactory $cloudFederationFactory,
- ICloudFederationProviderManager $cloudFederationProviderManager
+ ICloudFederationProviderManager $cloudFederationProviderManager,
+ IEventDispatcher $eventDispatcher
) {
parent::__construct($appName, $request);
@@ -108,6 +114,7 @@ class RequestHandlerController extends OCSController {
$this->logger = $logger;
$this->cloudFederationFactory = $cloudFederationFactory;
$this->cloudFederationProviderManager = $cloudFederationProviderManager;
+ $this->eventDispatcher = $eventDispatcher;
}
/**
@@ -156,6 +163,11 @@ class RequestHandlerController extends OCSController {
try {
$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
$provider->shareReceived($share);
+ if ($sharedByFederatedId === $ownerFederatedId) {
+ $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('A new federated share with "%s" was created by "%s" and shared with "%s"', [$name, $ownerFederatedId, $shareWith]));
+ } else {
+ $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('A new federated share with "%s" was shared by "%s" (resource owner is: "%s") and shared with "%s"', [$name, $sharedByFederatedId, $ownerFederatedId, $shareWith]));
+ }
} catch (ProviderDoesNotExistsException $e) {
throw new OCSException('Server does not support federated cloud sharing', 503);
} catch (ProviderCouldNotAddShareException $e) {
@@ -243,6 +255,7 @@ class RequestHandlerController extends OCSController {
try {
$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
$provider->notificationReceived('SHARE_ACCEPTED', $id, $notification);
+ $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('Federated share with id "%s" was accepted', [$id]));
} catch (ProviderDoesNotExistsException $e) {
throw new OCSException('Server does not support federated cloud sharing', 503);
} catch (ShareNotFound $e) {
@@ -275,6 +288,7 @@ class RequestHandlerController extends OCSController {
try {
$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
$provider->notificationReceived('SHARE_DECLINED', $id, $notification);
+ $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('Federated share with id "%s" was declined', [$id]));
} catch (ProviderDoesNotExistsException $e) {
throw new OCSException('Server does not support federated cloud sharing', 503);
} catch (ShareNotFound $e) {
@@ -307,6 +321,7 @@ class RequestHandlerController extends OCSController {
$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
$notification = ['sharedSecret' => $token];
$provider->notificationReceived('SHARE_UNSHARED', $id, $notification);
+ $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('Federated share with id "%s" was unshared', [$id]));
} catch (\Exception $e) {
$this->logger->debug('processing unshare notification failed: ' . $e->getMessage(), ['exception' => $e]);
}
@@ -381,6 +396,7 @@ class RequestHandlerController extends OCSController {
$ocmPermissions = $this->ncPermissions2ocmPermissions((int)$ncPermissions);
$notification = ['sharedSecret' => $token, 'permission' => $ocmPermissions];
$provider->notificationReceived('RESHARE_CHANGE_PERMISSION', $id, $notification);
+ $this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent('Federated share with id "%s" has updated permissions "%s"', [$id, implode(', ', $ocmPermissions)]));
} catch (\Exception $e) {
$this->logger->debug($e->getMessage(), ['exception' => $e]);
throw new OCSBadRequestException();
diff --git a/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php b/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php
index 0cb91fac1ae..77f7fde70fa 100644
--- a/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php
+++ b/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php
@@ -34,6 +34,7 @@ use OCP\Federation\ICloudFederationProvider;
use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\ICloudFederationShare;
use OCP\Federation\ICloudIdManager;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\IDBConnection;
use OCP\IRequest;
use OCP\IUserManager;
@@ -100,6 +101,9 @@ class RequestHandlerControllerTest extends \Test\TestCase {
/** @var ICloudFederationShare|\PHPUnit\Framework\MockObject\MockObject */
private $cloudFederationShare;
+ /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */
+ private $eventDispatcher;
+
protected function setUp(): void {
$this->share = $this->getMockBuilder(IShare::class)->getMock();
$this->federatedShareProvider = $this->getMockBuilder('OCA\FederatedFileSharing\FederatedShareProvider')
@@ -124,7 +128,8 @@ class RequestHandlerControllerTest extends \Test\TestCase {
$this->cloudFederationProviderManager = $this->createMock(ICloudFederationProviderManager::class);
$this->cloudFederationProvider = $this->createMock(ICloudFederationProvider::class);
$this->cloudFederationShare = $this->createMock(ICloudFederationShare::class);
-
+ $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
+ $this->eventDispatcher->expects($this->any())->method('dispatchTyped');
$this->logger = $this->createMock(LoggerInterface::class);
@@ -140,7 +145,8 @@ class RequestHandlerControllerTest extends \Test\TestCase {
$this->cloudIdManager,
$this->logger,
$this->cloudFederationFactory,
- $this->cloudFederationProviderManager
+ $this->cloudFederationProviderManager,
+ $this->eventDispatcher
);
}
diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js
index 505ab21c10c..8790eae9c98 100644
--- a/apps/files/js/fileactions.js
+++ b/apps/files/js/fileactions.js
@@ -557,7 +557,7 @@
// recreate fileactions container
nameLinks = parent.children('a.name');
nameLinks.find('.fileactions, .nametext .action').remove();
- nameLinks.append('<span class="fileactions" />');
+ nameLinks.append('<span class="fileactions"></span>');
var defaultAction = this.getDefaultFileAction(
this.getCurrentMimeType(),
this.getCurrentType(),
diff --git a/apps/files/js/files.js b/apps/files/js/files.js
index 03778fb92f9..ae247584682 100644
--- a/apps/files/js/files.js
+++ b/apps/files/js/files.js
@@ -422,12 +422,12 @@ var createDragShadow = function(event) {
$(selectedFiles).each(function(i,elem) {
// TODO: refactor this with the table row creation code
- var newtr = $('<tr/>')
+ var newtr = $('<tr></tr>')
.attr('data-dir', dir)
.attr('data-file', elem.name)
.attr('data-origin', elem.origin);
- newtr.append($('<td class="filename" />').text(elem.name).css('background-size', 32));
- newtr.append($('<td class="size" />').text(OC.Util.humanFileSize(elem.size)));
+ newtr.append($('<td class="filename"></td>').text(elem.name).css('background-size', 32));
+ newtr.append($('<td class="size"></td>').text(OC.Util.humanFileSize(elem.size)));
tbody.append(newtr);
if (elem.type === 'dir') {
newtr.find('td.filename')
diff --git a/apps/files/js/sidebarpreviewtext.js b/apps/files/js/sidebarpreviewtext.js
index 3053cd6945d..f786a9a3e4d 100644
--- a/apps/files/js/sidebarpreviewtext.js
+++ b/apps/files/js/sidebarpreviewtext.js
@@ -25,7 +25,7 @@
$thumbnailDiv.removeClass('icon-loading icon-32');
$thumbnailContainer.addClass('large');
$thumbnailContainer.addClass('text');
- var $textPreview = $('<pre/>').text(content);
+ var $textPreview = $('<pre></pre>').text(content);
$thumbnailDiv.children('.stretcher').remove();
$thumbnailDiv.append($textPreview);
$thumbnailContainer.css("max-height", previewHeight);
diff --git a/apps/files/l10n/ru.js b/apps/files/l10n/ru.js
index d104e01a3e4..8acc311ea36 100644
--- a/apps/files/l10n/ru.js
+++ b/apps/files/l10n/ru.js
@@ -72,7 +72,7 @@ OC.L10N.register(
"{dirs} and {files}" : "{dirs} и {files}",
"_including %n hidden_::_including %n hidden_" : ["включая %n скрытый","включая %n скрытых","включая %n скрытых","включая %n скрытых"],
"You don’t have permission to upload or create files here" : "У вас нет прав на создание или загрузку файлов в эту папку.",
- "_Uploading %n file_::_Uploading %n files_" : ["Выгружа%nется файл","Выгружаются %n файла","Выгружаются %n файлов","Загружаются %n файлов"],
+ "_Uploading %n file_::_Uploading %n files_" : ["Передача %n файла","Передача %n файлов","Передача %n файлов","Передача %n файлов"],
"New" : "Новый",
"Select file range" : "Выбор диапазона файлов",
"{used} of {quota} used" : "использовано {used} из {quota}",
diff --git a/apps/files/l10n/ru.json b/apps/files/l10n/ru.json
index df48abba01d..1786e8c2eef 100644
--- a/apps/files/l10n/ru.json
+++ b/apps/files/l10n/ru.json
@@ -70,7 +70,7 @@
"{dirs} and {files}" : "{dirs} и {files}",
"_including %n hidden_::_including %n hidden_" : ["включая %n скрытый","включая %n скрытых","включая %n скрытых","включая %n скрытых"],
"You don’t have permission to upload or create files here" : "У вас нет прав на создание или загрузку файлов в эту папку.",
- "_Uploading %n file_::_Uploading %n files_" : ["Выгружа%nется файл","Выгружаются %n файла","Выгружаются %n файлов","Загружаются %n файлов"],
+ "_Uploading %n file_::_Uploading %n files_" : ["Передача %n файла","Передача %n файлов","Передача %n файлов","Передача %n файлов"],
"New" : "Новый",
"Select file range" : "Выбор диапазона файлов",
"{used} of {quota} used" : "использовано {used} из {quota}",
diff --git a/apps/files/lib/Controller/AjaxController.php b/apps/files/lib/Controller/AjaxController.php
index 000d950595d..cd26ab7a6f8 100644
--- a/apps/files/lib/Controller/AjaxController.php
+++ b/apps/files/lib/Controller/AjaxController.php
@@ -40,7 +40,6 @@ class AjaxController extends Controller {
* @NoAdminRequired
*/
public function getStorageStats(string $dir = '/'): JSONResponse {
- \OC_Util::setupFS();
try {
return new JSONResponse([
'status' => 'success',
diff --git a/apps/files_external/appinfo/info.xml b/apps/files_external/appinfo/info.xml
index ea8e29c0166..f9b2b8341ce 100644
--- a/apps/files_external/appinfo/info.xml
+++ b/apps/files_external/appinfo/info.xml
@@ -9,7 +9,7 @@ This application enables administrators to configure connections to external sto
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>
- <version>1.16.0</version>
+ <version>1.16.1</version>
<licence>agpl</licence>
<author>Robin Appelman</author>
<author>Michael Gapczynski</author>
diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js
index 01c2c3bc953..46092d57e67 100644
--- a/apps/files_external/js/settings.js
+++ b/apps/files_external/js/settings.js
@@ -141,7 +141,7 @@ function addSelect2 ($elements, userListLimit) {
return element.name;
},
formatResult: function (element) {
- var $result = $('<span><div class="avatardiv"/><span>'+escapeHTML(element.displayname)+'</span></span>');
+ var $result = $('<span><div class="avatardiv"></div><span>'+escapeHTML(element.displayname)+'</span></span>');
var $div = $result.find('.avatardiv')
.attr('data-type', element.type)
.attr('data-name', element.name)
diff --git a/apps/files_external/l10n/hu.js b/apps/files_external/l10n/hu.js
index 653d4717022..527dd726383 100644
--- a/apps/files_external/l10n/hu.js
+++ b/apps/files_external/l10n/hu.js
@@ -22,6 +22,7 @@ OC.L10N.register(
"Read only" : "Csak olvasható",
"Delete" : "Törlés",
"Admin defined" : "Rendszergazda által definiálva",
+ "Automatic status checking is disabled due to the large number of configured storages, click to check status" : "Az automatikus állapotellenőrzés a beállított tárolók nagy száma miatt ki van kapcsolva, kattintson az állapot ellenőrzéséhez",
"Are you sure you want to delete this external storage?" : "Biztos, hogy törli ezt a külső tárolót?",
"Delete storage?" : "Tároló törlése?",
"Saved" : "Mentve",
diff --git a/apps/files_external/l10n/hu.json b/apps/files_external/l10n/hu.json
index 5538e42226c..9323eee7cfc 100644
--- a/apps/files_external/l10n/hu.json
+++ b/apps/files_external/l10n/hu.json
@@ -20,6 +20,7 @@
"Read only" : "Csak olvasható",
"Delete" : "Törlés",
"Admin defined" : "Rendszergazda által definiálva",
+ "Automatic status checking is disabled due to the large number of configured storages, click to check status" : "Az automatikus állapotellenőrzés a beállított tárolók nagy száma miatt ki van kapcsolva, kattintson az állapot ellenőrzéséhez",
"Are you sure you want to delete this external storage?" : "Biztos, hogy törli ezt a külső tárolót?",
"Delete storage?" : "Tároló törlése?",
"Saved" : "Mentve",
diff --git a/apps/files_external/lib/Migration/Version1011Date20200630192246.php b/apps/files_external/lib/Migration/Version1011Date20200630192246.php
index 5ec289428fb..c2a53e346f1 100644
--- a/apps/files_external/lib/Migration/Version1011Date20200630192246.php
+++ b/apps/files_external/lib/Migration/Version1011Date20200630192246.php
@@ -116,7 +116,7 @@ class Version1011Date20200630192246 extends SimpleMigrationStep {
]);
$table->addColumn('value', Types::STRING, [
'notnull' => false,
- 'length' => 4096,
+ 'length' => 4000,
]);
$table->setPrimaryKey(['config_id']);
$table->addUniqueIndex(['mount_id', 'key'], 'config_mount_key');
diff --git a/apps/files_external/lib/Migration/Version1016Date20220324154536.php b/apps/files_external/lib/Migration/Version1016Date20220324154536.php
new file mode 100644
index 00000000000..a2a7ecaff17
--- /dev/null
+++ b/apps/files_external/lib/Migration/Version1016Date20220324154536.php
@@ -0,0 +1,54 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2022 Joas Schilling <coding@schilljs.com>
+ *
+ * @author Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCA\Files_External\Migration;
+
+use Closure;
+use OCP\DB\ISchemaWrapper;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+
+class Version1016Date20220324154536 extends SimpleMigrationStep {
+
+ /**
+ * @param IOutput $output
+ * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+ * @param array $options
+ * @return null|ISchemaWrapper
+ */
+ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
+ /** @var ISchemaWrapper $schema */
+ $schema = $schemaClosure();
+
+ $table = $schema->getTable('external_config');
+ $column = $table->getColumn('value');
+
+ if ($column->getLength() > 4000) {
+ $column->setLength(4000);
+ return $schema;
+ }
+
+ return null;
+ }
+}
diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml
index c1cb23cd68e..a2446f99163 100644
--- a/apps/files_sharing/appinfo/info.xml
+++ b/apps/files_sharing/appinfo/info.xml
@@ -9,7 +9,7 @@
Turning the feature off removes shared files and folders on the server for all share recipients, and also on the sync clients and mobile apps. More information is available in the Nextcloud Documentation.
</description>
- <version>1.16.0</version>
+ <version>1.16.1</version>
<licence>agpl</licence>
<author>Michael Gapczynski</author>
<author>Bjoern Schiessle</author>
diff --git a/apps/files_sharing/composer/composer/autoload_classmap.php b/apps/files_sharing/composer/composer/autoload_classmap.php
index 3a98cb4577f..95bee7323b7 100644
--- a/apps/files_sharing/composer/composer/autoload_classmap.php
+++ b/apps/files_sharing/composer/composer/autoload_classmap.php
@@ -68,6 +68,7 @@ return array(
'OCA\\Files_Sharing\\Migration\\Version11300Date20201120141438' => $baseDir . '/../lib/Migration/Version11300Date20201120141438.php',
'OCA\\Files_Sharing\\Migration\\Version21000Date20201223143245' => $baseDir . '/../lib/Migration/Version21000Date20201223143245.php',
'OCA\\Files_Sharing\\Migration\\Version22000Date20210216084241' => $baseDir . '/../lib/Migration/Version22000Date20210216084241.php',
+ 'OCA\\Files_Sharing\\Migration\\Version24000Date20220404142216' => $baseDir . '/../lib/Migration/Version24000Date20220404142216.php',
'OCA\\Files_Sharing\\MountProvider' => $baseDir . '/../lib/MountProvider.php',
'OCA\\Files_Sharing\\Notification\\Listener' => $baseDir . '/../lib/Notification/Listener.php',
'OCA\\Files_Sharing\\Notification\\Notifier' => $baseDir . '/../lib/Notification/Notifier.php',
diff --git a/apps/files_sharing/composer/composer/autoload_static.php b/apps/files_sharing/composer/composer/autoload_static.php
index b12c759a56e..dd8e9e2b7f9 100644
--- a/apps/files_sharing/composer/composer/autoload_static.php
+++ b/apps/files_sharing/composer/composer/autoload_static.php
@@ -83,6 +83,7 @@ class ComposerStaticInitFiles_Sharing
'OCA\\Files_Sharing\\Migration\\Version11300Date20201120141438' => __DIR__ . '/..' . '/../lib/Migration/Version11300Date20201120141438.php',
'OCA\\Files_Sharing\\Migration\\Version21000Date20201223143245' => __DIR__ . '/..' . '/../lib/Migration/Version21000Date20201223143245.php',
'OCA\\Files_Sharing\\Migration\\Version22000Date20210216084241' => __DIR__ . '/..' . '/../lib/Migration/Version22000Date20210216084241.php',
+ 'OCA\\Files_Sharing\\Migration\\Version24000Date20220404142216' => __DIR__ . '/..' . '/../lib/Migration/Version24000Date20220404142216.php',
'OCA\\Files_Sharing\\MountProvider' => __DIR__ . '/..' . '/../lib/MountProvider.php',
'OCA\\Files_Sharing\\Notification\\Listener' => __DIR__ . '/..' . '/../lib/Notification/Listener.php',
'OCA\\Files_Sharing\\Notification\\Notifier' => __DIR__ . '/..' . '/../lib/Notification/Notifier.php',
diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js
index 6b063896b7f..bfb035fb817 100644
--- a/apps/files_sharing/js/public.js
+++ b/apps/files_sharing/js/public.js
@@ -355,12 +355,12 @@ OCA.Sharing.PublicApp = {
},
_showTextPreview: function (data, previewHeight) {
- var textDiv = $('<div/>').addClass('text-preview');
+ var textDiv = $('<div></div>').addClass('text-preview');
textDiv.text(data);
textDiv.appendTo('#imgframe');
var divHeight = textDiv.height();
if (data.length > 999) {
- var ellipsis = $('<div/>').addClass('ellipsis');
+ var ellipsis = $('<div></div>').addClass('ellipsis');
ellipsis.html('(&#133;)');
ellipsis.appendTo('#imgframe');
}
diff --git a/apps/files_sharing/l10n/cs.js b/apps/files_sharing/l10n/cs.js
index e80b06f1fb4..6a09ad0601f 100644
--- a/apps/files_sharing/l10n/cs.js
+++ b/apps/files_sharing/l10n/cs.js
@@ -124,7 +124,7 @@ OC.L10N.register(
"Could not lock path" : "Nepodařilo se uzamknout popis umístění",
"Wrong or no update parameter given" : "Chyba nebo žádná aktualizace dle zadaných parametrů",
"Share must at least have READ or CREATE permissions" : "Je třeba, aby sdílení mělo alespoň oprávnění pro ČÍST nebo VYTVÁŘET",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Pokud je nastaveno oprávnění AKTUALIZOVAT nebo MAZAT je třeba, aby sdílení mělo oprávnění ČÍST.",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "Pokud je nastaveno oprávnění AKTUALIZOVAT nebo MAZAT je třeba, aby sdílení mělo oprávnění ČÍST",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "„Zaslání hesla prostřednictvím Nextcloud Talk“ pro sdílení souboru či složky se nezdařilo protože Nextcloud Talk není zapnuté.",
"shared by %s" : "sdílí %s",
"Download all files" : "Stáhnout všechny soubory",
diff --git a/apps/files_sharing/l10n/cs.json b/apps/files_sharing/l10n/cs.json
index c88349d580d..010c27d69d2 100644
--- a/apps/files_sharing/l10n/cs.json
+++ b/apps/files_sharing/l10n/cs.json
@@ -122,7 +122,7 @@
"Could not lock path" : "Nepodařilo se uzamknout popis umístění",
"Wrong or no update parameter given" : "Chyba nebo žádná aktualizace dle zadaných parametrů",
"Share must at least have READ or CREATE permissions" : "Je třeba, aby sdílení mělo alespoň oprávnění pro ČÍST nebo VYTVÁŘET",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Pokud je nastaveno oprávnění AKTUALIZOVAT nebo MAZAT je třeba, aby sdílení mělo oprávnění ČÍST.",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "Pokud je nastaveno oprávnění AKTUALIZOVAT nebo MAZAT je třeba, aby sdílení mělo oprávnění ČÍST",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "„Zaslání hesla prostřednictvím Nextcloud Talk“ pro sdílení souboru či složky se nezdařilo protože Nextcloud Talk není zapnuté.",
"shared by %s" : "sdílí %s",
"Download all files" : "Stáhnout všechny soubory",
diff --git a/apps/files_sharing/l10n/de.js b/apps/files_sharing/l10n/de.js
index b731cf03a84..6cc439d686e 100644
--- a/apps/files_sharing/l10n/de.js
+++ b/apps/files_sharing/l10n/de.js
@@ -123,7 +123,6 @@ OC.L10N.register(
"Could not lock path" : "Pfad konnte nicht gesperrt werden",
"Wrong or no update parameter given" : "Es wurde ein falscher oder kein Updateparameter angegeben",
"Share must at least have READ or CREATE permissions" : "Freigabe muss mindestens Lese- oder Erstell-Rechte haben",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Die Freigabe muss das Recht Lesen haben, wenn das Recht für Aktualisieren oder Löschen gesetzt ist.",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Senden des Passwortes über Nextcloud Talk\" zum Teilen einer Datei gescheitert, da Nextcloud Talk nicht verfügbar ist.",
"shared by %s" : "von %s geteilt",
"Download all files" : "Alle Dateien herunterladen",
diff --git a/apps/files_sharing/l10n/de.json b/apps/files_sharing/l10n/de.json
index 36790acd0a4..7840d3acbe2 100644
--- a/apps/files_sharing/l10n/de.json
+++ b/apps/files_sharing/l10n/de.json
@@ -121,7 +121,6 @@
"Could not lock path" : "Pfad konnte nicht gesperrt werden",
"Wrong or no update parameter given" : "Es wurde ein falscher oder kein Updateparameter angegeben",
"Share must at least have READ or CREATE permissions" : "Freigabe muss mindestens Lese- oder Erstell-Rechte haben",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Die Freigabe muss das Recht Lesen haben, wenn das Recht für Aktualisieren oder Löschen gesetzt ist.",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Senden des Passwortes über Nextcloud Talk\" zum Teilen einer Datei gescheitert, da Nextcloud Talk nicht verfügbar ist.",
"shared by %s" : "von %s geteilt",
"Download all files" : "Alle Dateien herunterladen",
diff --git a/apps/files_sharing/l10n/de_DE.js b/apps/files_sharing/l10n/de_DE.js
index 1cb10b7704e..5b4b7f31a3f 100644
--- a/apps/files_sharing/l10n/de_DE.js
+++ b/apps/files_sharing/l10n/de_DE.js
@@ -124,7 +124,7 @@ OC.L10N.register(
"Could not lock path" : "Pfad konnte nicht gesperrt werden",
"Wrong or no update parameter given" : "Es wurde ein falscher oder kein Updateparameter angegeben",
"Share must at least have READ or CREATE permissions" : "Freigabe muss mindestens LESEN- oder ERSTELLEN-Rechte haben",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Die Freigabe muss das Recht LESEN haben, wenn das Recht AKTUALISIEREN oder LÖSCHEN gesetzt ist.",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "Die Freigabe muss das Recht LESEN haben, wenn das Recht AKTUALISIEREN oder LÖSCHEN gesetzt ist",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Senden des Passwortes über Nextcloud Talk\" zum Teilen einer Datei gescheitert, da Nextcloud Talk nicht verfügbar ist.",
"shared by %s" : "von %s geteilt",
"Download all files" : "Alle Dateien herunterladen",
diff --git a/apps/files_sharing/l10n/de_DE.json b/apps/files_sharing/l10n/de_DE.json
index f12c03e8be9..c14d0f3ba9c 100644
--- a/apps/files_sharing/l10n/de_DE.json
+++ b/apps/files_sharing/l10n/de_DE.json
@@ -122,7 +122,7 @@
"Could not lock path" : "Pfad konnte nicht gesperrt werden",
"Wrong or no update parameter given" : "Es wurde ein falscher oder kein Updateparameter angegeben",
"Share must at least have READ or CREATE permissions" : "Freigabe muss mindestens LESEN- oder ERSTELLEN-Rechte haben",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Die Freigabe muss das Recht LESEN haben, wenn das Recht AKTUALISIEREN oder LÖSCHEN gesetzt ist.",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "Die Freigabe muss das Recht LESEN haben, wenn das Recht AKTUALISIEREN oder LÖSCHEN gesetzt ist",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Senden des Passwortes über Nextcloud Talk\" zum Teilen einer Datei gescheitert, da Nextcloud Talk nicht verfügbar ist.",
"shared by %s" : "von %s geteilt",
"Download all files" : "Alle Dateien herunterladen",
diff --git a/apps/files_sharing/l10n/es.js b/apps/files_sharing/l10n/es.js
index 266f22ff6e7..db1fffb1546 100644
--- a/apps/files_sharing/l10n/es.js
+++ b/apps/files_sharing/l10n/es.js
@@ -124,7 +124,6 @@ OC.L10N.register(
"Could not lock path" : "No se ha podido bloquear la ruta",
"Wrong or no update parameter given" : "No se ha suministrado un parametro correcto",
"Share must at least have READ or CREATE permissions" : "El recurso compartido debe tener al menos el permiso de LECTURA o CREACIÓN",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "El recurso compartido debe tener el permiso de LECTURA si el permiso de ACTUALIZAR o ELIMINAR está activado.",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"El envío de la contraseña por Nextcloud Talk\" para compartir un archivo o carpeta falló porque Nextcloud Talk no está habilitado.",
"shared by %s" : "compartido por %s",
"Download all files" : "Descargar todos los archivos",
diff --git a/apps/files_sharing/l10n/es.json b/apps/files_sharing/l10n/es.json
index 5eb24043838..cd4538810b7 100644
--- a/apps/files_sharing/l10n/es.json
+++ b/apps/files_sharing/l10n/es.json
@@ -122,7 +122,6 @@
"Could not lock path" : "No se ha podido bloquear la ruta",
"Wrong or no update parameter given" : "No se ha suministrado un parametro correcto",
"Share must at least have READ or CREATE permissions" : "El recurso compartido debe tener al menos el permiso de LECTURA o CREACIÓN",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "El recurso compartido debe tener el permiso de LECTURA si el permiso de ACTUALIZAR o ELIMINAR está activado.",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"El envío de la contraseña por Nextcloud Talk\" para compartir un archivo o carpeta falló porque Nextcloud Talk no está habilitado.",
"shared by %s" : "compartido por %s",
"Download all files" : "Descargar todos los archivos",
diff --git a/apps/files_sharing/l10n/eu.js b/apps/files_sharing/l10n/eu.js
index 324ba68e720..015c99450f0 100644
--- a/apps/files_sharing/l10n/eu.js
+++ b/apps/files_sharing/l10n/eu.js
@@ -124,7 +124,6 @@ OC.L10N.register(
"Could not lock path" : "Ezin izan da bidea blokeatu",
"Wrong or no update parameter given" : "Eguneraketa parametrorik ez da eman edo okerra da",
"Share must at least have READ or CREATE permissions" : "Partekatzeak gutxienez IRAKURRI edo SORTU egiteko baimenak behar ditu",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Partekatzeak IRAKURRI egiteko baimenak behar ditu, EGUNERATU edo EZABATU baimenak baldin badauzka.",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Nextcloud Talk-ek pasahitza bidaltzeak\" huts egin du ez dagoelako Nextcloud Talk gaituta fitxategi edo karpeta bat partekatzeko.",
"shared by %s" : "%s erabiltzaileak partekatua",
"Download all files" : "Deskargatu fitxategi guztiak",
diff --git a/apps/files_sharing/l10n/eu.json b/apps/files_sharing/l10n/eu.json
index a0e3ec3713d..7a64bb164d6 100644
--- a/apps/files_sharing/l10n/eu.json
+++ b/apps/files_sharing/l10n/eu.json
@@ -122,7 +122,6 @@
"Could not lock path" : "Ezin izan da bidea blokeatu",
"Wrong or no update parameter given" : "Eguneraketa parametrorik ez da eman edo okerra da",
"Share must at least have READ or CREATE permissions" : "Partekatzeak gutxienez IRAKURRI edo SORTU egiteko baimenak behar ditu",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Partekatzeak IRAKURRI egiteko baimenak behar ditu, EGUNERATU edo EZABATU baimenak baldin badauzka.",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Nextcloud Talk-ek pasahitza bidaltzeak\" huts egin du ez dagoelako Nextcloud Talk gaituta fitxategi edo karpeta bat partekatzeko.",
"shared by %s" : "%s erabiltzaileak partekatua",
"Download all files" : "Deskargatu fitxategi guztiak",
diff --git a/apps/files_sharing/l10n/fr.js b/apps/files_sharing/l10n/fr.js
index 6a57a95dfaf..ff4480866e0 100644
--- a/apps/files_sharing/l10n/fr.js
+++ b/apps/files_sharing/l10n/fr.js
@@ -123,7 +123,6 @@ OC.L10N.register(
"Could not lock path" : "Impossible de verrouiller le chemin",
"Wrong or no update parameter given" : "Mauvais ou aucun paramètre donné ",
"Share must at least have READ or CREATE permissions" : "Le partage nécessite de disposer à minima des permissions de LECTURE et de CREATION",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Le partage nécessite de disposer de la permission de LECTURE si les permissions de MODIFICATION et SUPPRESSION sont définies",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"L'envoi du mot de passe par Nextcloud Talk\" pour partager un fichier a échoué car Nextcloud Talk n'est pas activé",
"shared by %s" : "partagé par %s",
"Download all files" : "Télécharger tous les fichiers",
diff --git a/apps/files_sharing/l10n/fr.json b/apps/files_sharing/l10n/fr.json
index af86ece4acc..bec5504c88d 100644
--- a/apps/files_sharing/l10n/fr.json
+++ b/apps/files_sharing/l10n/fr.json
@@ -121,7 +121,6 @@
"Could not lock path" : "Impossible de verrouiller le chemin",
"Wrong or no update parameter given" : "Mauvais ou aucun paramètre donné ",
"Share must at least have READ or CREATE permissions" : "Le partage nécessite de disposer à minima des permissions de LECTURE et de CREATION",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Le partage nécessite de disposer de la permission de LECTURE si les permissions de MODIFICATION et SUPPRESSION sont définies",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"L'envoi du mot de passe par Nextcloud Talk\" pour partager un fichier a échoué car Nextcloud Talk n'est pas activé",
"shared by %s" : "partagé par %s",
"Download all files" : "Télécharger tous les fichiers",
diff --git a/apps/files_sharing/l10n/hu.js b/apps/files_sharing/l10n/hu.js
index 9539e51ffb0..d644dfe78db 100644
--- a/apps/files_sharing/l10n/hu.js
+++ b/apps/files_sharing/l10n/hu.js
@@ -101,6 +101,7 @@ OC.L10N.register(
"Wrong share ID, share doesn't exist" : "Hibás megosztási azonosító, a megosztás nem létezik",
"Could not delete share" : "A megosztás nem törölhető",
"Please specify a file or folder path" : "Adjon meg egy fájl- vagy mappaútvonalat",
+ "Wrong path, file/folder does not exist" : "Hibás útvonal, a fájl/mappa nem létezik",
"Could not create share" : "A megosztás nem hozható létre",
"Invalid permissions" : "Érvénytelen jogosultságok",
"Please specify a valid user" : "Adjon meg egy érvényes felhasználót",
@@ -123,7 +124,7 @@ OC.L10N.register(
"Could not lock path" : "Nem sikerült zárolni az útvonalat",
"Wrong or no update parameter given" : "Hibás vagy üres frissítési paraméter",
"Share must at least have READ or CREATE permissions" : "A megosztásnak legalább OLVASÁSI és LÉTREHOZÁSI engedéllyel kell rendelkeznie",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "A megosztásnak OLVASÁSI jogosultsággal kell rendelkeznie, ha a FRISSÍTÉSI vagy TÖRLÉSI jogosultság meg van adva.",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "A megosztásnak OLVASÁSI jogosultsággal kell rendelkeznie, ha a FRISSÍTÉSI vagy TÖRLÉSI jogosultság meg van adva",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "A „Jelszó kiküldése a Nextcloud Beszélgetéssel” nem sikerült a fájlnál vagy mappánál, mert a Nextcloud Beszélgetés nem engedélyezett.",
"shared by %s" : "megosztotta: %s",
"Download all files" : "Összes fájl letöltése",
diff --git a/apps/files_sharing/l10n/hu.json b/apps/files_sharing/l10n/hu.json
index b76f8830fdd..1a8da9691e9 100644
--- a/apps/files_sharing/l10n/hu.json
+++ b/apps/files_sharing/l10n/hu.json
@@ -99,6 +99,7 @@
"Wrong share ID, share doesn't exist" : "Hibás megosztási azonosító, a megosztás nem létezik",
"Could not delete share" : "A megosztás nem törölhető",
"Please specify a file or folder path" : "Adjon meg egy fájl- vagy mappaútvonalat",
+ "Wrong path, file/folder does not exist" : "Hibás útvonal, a fájl/mappa nem létezik",
"Could not create share" : "A megosztás nem hozható létre",
"Invalid permissions" : "Érvénytelen jogosultságok",
"Please specify a valid user" : "Adjon meg egy érvényes felhasználót",
@@ -121,7 +122,7 @@
"Could not lock path" : "Nem sikerült zárolni az útvonalat",
"Wrong or no update parameter given" : "Hibás vagy üres frissítési paraméter",
"Share must at least have READ or CREATE permissions" : "A megosztásnak legalább OLVASÁSI és LÉTREHOZÁSI engedéllyel kell rendelkeznie",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "A megosztásnak OLVASÁSI jogosultsággal kell rendelkeznie, ha a FRISSÍTÉSI vagy TÖRLÉSI jogosultság meg van adva.",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "A megosztásnak OLVASÁSI jogosultsággal kell rendelkeznie, ha a FRISSÍTÉSI vagy TÖRLÉSI jogosultság meg van adva",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "A „Jelszó kiküldése a Nextcloud Beszélgetéssel” nem sikerült a fájlnál vagy mappánál, mert a Nextcloud Beszélgetés nem engedélyezett.",
"shared by %s" : "megosztotta: %s",
"Download all files" : "Összes fájl letöltése",
diff --git a/apps/files_sharing/l10n/it.js b/apps/files_sharing/l10n/it.js
index 584dc5046fb..7912a08ec42 100644
--- a/apps/files_sharing/l10n/it.js
+++ b/apps/files_sharing/l10n/it.js
@@ -123,7 +123,6 @@ OC.L10N.register(
"Could not lock path" : "Impossibile bloccare il percorso",
"Wrong or no update parameter given" : "Parametro fornito non valido o non di aggiornamento",
"Share must at least have READ or CREATE permissions" : "La condivisione deve disporre almeno delle autorizzazioni READ o CREATE",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "La condivisione deve disporre dell'autorizzazione READ se l'autorizzazione è impostata su UPDATE o DELETE.",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Invio della password da Nextcloud Talk\" per condividere un file o una cartella non è riuscito poiché Nextcloud Talk non è attivato.",
"shared by %s" : "condiviso da %s",
"Download all files" : "Scarica tutti i file",
diff --git a/apps/files_sharing/l10n/it.json b/apps/files_sharing/l10n/it.json
index cd120855ba7..a854a69ea99 100644
--- a/apps/files_sharing/l10n/it.json
+++ b/apps/files_sharing/l10n/it.json
@@ -121,7 +121,6 @@
"Could not lock path" : "Impossibile bloccare il percorso",
"Wrong or no update parameter given" : "Parametro fornito non valido o non di aggiornamento",
"Share must at least have READ or CREATE permissions" : "La condivisione deve disporre almeno delle autorizzazioni READ o CREATE",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "La condivisione deve disporre dell'autorizzazione READ se l'autorizzazione è impostata su UPDATE o DELETE.",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Invio della password da Nextcloud Talk\" per condividere un file o una cartella non è riuscito poiché Nextcloud Talk non è attivato.",
"shared by %s" : "condiviso da %s",
"Download all files" : "Scarica tutti i file",
diff --git a/apps/files_sharing/l10n/pl.js b/apps/files_sharing/l10n/pl.js
index 0261570cb22..b1ba4da216b 100644
--- a/apps/files_sharing/l10n/pl.js
+++ b/apps/files_sharing/l10n/pl.js
@@ -124,7 +124,7 @@ OC.L10N.register(
"Could not lock path" : "Nie można zablokować ścieżki",
"Wrong or no update parameter given" : "Brakujący lub błędny parametr aktualizacji",
"Share must at least have READ or CREATE permissions" : "Udostępnienie musi mieć co najmniej uprawnienia do ODCZYTU lub TWORZENIA",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Udostępnienie musi mieć uprawnienie do ODCZYTU, jeśli ustawiono uprawnienie do AKTUALIZACJI lub USUWANIA.",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "Udostępnienie musi mieć uprawnienie do ODCZYTU, jeśli ustawiono uprawnienie do AKTUALIZACJI lub USUWANIA",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Wysyłanie hasła przez Nextcloud Talk\" w celu udostępnienia pliku lub katalogu nie powiodło się, ponieważ usługa Nextcloud Talk jest wyłączona.",
"shared by %s" : "udostępnione przez %s",
"Download all files" : "Pobierz wszystkie pliki",
diff --git a/apps/files_sharing/l10n/pl.json b/apps/files_sharing/l10n/pl.json
index 3aa92821fea..25fff976150 100644
--- a/apps/files_sharing/l10n/pl.json
+++ b/apps/files_sharing/l10n/pl.json
@@ -122,7 +122,7 @@
"Could not lock path" : "Nie można zablokować ścieżki",
"Wrong or no update parameter given" : "Brakujący lub błędny parametr aktualizacji",
"Share must at least have READ or CREATE permissions" : "Udostępnienie musi mieć co najmniej uprawnienia do ODCZYTU lub TWORZENIA",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Udostępnienie musi mieć uprawnienie do ODCZYTU, jeśli ustawiono uprawnienie do AKTUALIZACJI lub USUWANIA.",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "Udostępnienie musi mieć uprawnienie do ODCZYTU, jeśli ustawiono uprawnienie do AKTUALIZACJI lub USUWANIA",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Wysyłanie hasła przez Nextcloud Talk\" w celu udostępnienia pliku lub katalogu nie powiodło się, ponieważ usługa Nextcloud Talk jest wyłączona.",
"shared by %s" : "udostępnione przez %s",
"Download all files" : "Pobierz wszystkie pliki",
diff --git a/apps/files_sharing/l10n/pt_BR.js b/apps/files_sharing/l10n/pt_BR.js
index 963ba85fa8b..73194661c8b 100644
--- a/apps/files_sharing/l10n/pt_BR.js
+++ b/apps/files_sharing/l10n/pt_BR.js
@@ -122,6 +122,7 @@ OC.L10N.register(
"Could not lock node" : "Não foi possível bloquear o nó",
"Could not lock path" : "Não foi possível bloquear o caminho",
"Wrong or no update parameter given" : "O parâmetro da atualização fornecido está errado ou não existe",
+ "Share must at least have READ or CREATE permissions" : "O compartilhamento deve ter pelo menos permissões de LER ou CRIAR",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "O \"envio da senha pelo Bate Papo Nextcloud\" para compartilhar um arquivo ou pasta falhou porque o Bate Papo Nextcloud não está habilitado. ",
"shared by %s" : "compartilhado por %s",
"Download all files" : "Baixar todos os arquivos",
@@ -150,6 +151,11 @@ OC.L10N.register(
"Read only" : "Somente leitura",
"Allow upload and editing" : "Permitir envio e edição",
"File drop (upload only)" : "Soltar arquivo (somente envio)",
+ "Custom permissions" : "Permissões personalizadas",
+ "Read" : "Leitura",
+ "Upload" : "Enviar",
+ "Edit" : "Editar",
+ "Bundled permissions" : "Permissões agrupadas",
"Allow creating" : "Permitir criar",
"Allow deleting" : "Permitir excluir",
"Allow resharing" : "Permitir recompartilhar",
diff --git a/apps/files_sharing/l10n/pt_BR.json b/apps/files_sharing/l10n/pt_BR.json
index 9de304bfb1d..830f320bc72 100644
--- a/apps/files_sharing/l10n/pt_BR.json
+++ b/apps/files_sharing/l10n/pt_BR.json
@@ -120,6 +120,7 @@
"Could not lock node" : "Não foi possível bloquear o nó",
"Could not lock path" : "Não foi possível bloquear o caminho",
"Wrong or no update parameter given" : "O parâmetro da atualização fornecido está errado ou não existe",
+ "Share must at least have READ or CREATE permissions" : "O compartilhamento deve ter pelo menos permissões de LER ou CRIAR",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "O \"envio da senha pelo Bate Papo Nextcloud\" para compartilhar um arquivo ou pasta falhou porque o Bate Papo Nextcloud não está habilitado. ",
"shared by %s" : "compartilhado por %s",
"Download all files" : "Baixar todos os arquivos",
@@ -148,6 +149,11 @@
"Read only" : "Somente leitura",
"Allow upload and editing" : "Permitir envio e edição",
"File drop (upload only)" : "Soltar arquivo (somente envio)",
+ "Custom permissions" : "Permissões personalizadas",
+ "Read" : "Leitura",
+ "Upload" : "Enviar",
+ "Edit" : "Editar",
+ "Bundled permissions" : "Permissões agrupadas",
"Allow creating" : "Permitir criar",
"Allow deleting" : "Permitir excluir",
"Allow resharing" : "Permitir recompartilhar",
diff --git a/apps/files_sharing/l10n/sk.js b/apps/files_sharing/l10n/sk.js
index 9e20225c05e..8416798aea4 100644
--- a/apps/files_sharing/l10n/sk.js
+++ b/apps/files_sharing/l10n/sk.js
@@ -123,7 +123,6 @@ OC.L10N.register(
"Could not lock path" : "Nie je možné uzamknúť cestu",
"Wrong or no update parameter given" : "Zlý alebo žiadny zadaný parameter aktualizácie",
"Share must at least have READ or CREATE permissions" : "Zdieľanie musí mať aspoň povolenia READ alebo CREATE",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Ak je nastavené oprávnenie UPDATE alebo DELETE, zdieľanie musí mať povolenie READ.",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Odoslanie hesla cez Nextcloud Talk\" pre zdieľanie súboru alebo priečinka zlyhalo, pretože Nextcloud Talk nie je zapnutý.",
"shared by %s" : "Sprístupnil %s",
"Download all files" : "Stiahnuť všetky súbory",
diff --git a/apps/files_sharing/l10n/sk.json b/apps/files_sharing/l10n/sk.json
index 91f5c491822..174c967f203 100644
--- a/apps/files_sharing/l10n/sk.json
+++ b/apps/files_sharing/l10n/sk.json
@@ -121,7 +121,6 @@
"Could not lock path" : "Nie je možné uzamknúť cestu",
"Wrong or no update parameter given" : "Zlý alebo žiadny zadaný parameter aktualizácie",
"Share must at least have READ or CREATE permissions" : "Zdieľanie musí mať aspoň povolenia READ alebo CREATE",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Ak je nastavené oprávnenie UPDATE alebo DELETE, zdieľanie musí mať povolenie READ.",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Odoslanie hesla cez Nextcloud Talk\" pre zdieľanie súboru alebo priečinka zlyhalo, pretože Nextcloud Talk nie je zapnutý.",
"shared by %s" : "Sprístupnil %s",
"Download all files" : "Stiahnuť všetky súbory",
diff --git a/apps/files_sharing/l10n/sv.js b/apps/files_sharing/l10n/sv.js
index 605c517deaf..c1de6977dcb 100644
--- a/apps/files_sharing/l10n/sv.js
+++ b/apps/files_sharing/l10n/sv.js
@@ -123,7 +123,6 @@ OC.L10N.register(
"Could not lock path" : "Kunde inte låsa sökvägen",
"Wrong or no update parameter given" : "Fel eller ingen uppdateringsparameter angiven",
"Share must at least have READ or CREATE permissions" : "Delningen måste åtminstone ha LÄS- eller SKAPA-behörighet",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Delningen måste ha LÄS-behörighet om ÄNDRA- eller RADERA-behörighet är inställd.",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Skicka lösenord via Nextcloud Talk\" för att dela en fil eller mapp misslyckades eftersom Nextcloud Talk inte är aktiverat.",
"shared by %s" : "delad av %s",
"Download all files" : "Hämta alla filer",
diff --git a/apps/files_sharing/l10n/sv.json b/apps/files_sharing/l10n/sv.json
index b6d1fd03a98..a5abfa7de4d 100644
--- a/apps/files_sharing/l10n/sv.json
+++ b/apps/files_sharing/l10n/sv.json
@@ -121,7 +121,6 @@
"Could not lock path" : "Kunde inte låsa sökvägen",
"Wrong or no update parameter given" : "Fel eller ingen uppdateringsparameter angiven",
"Share must at least have READ or CREATE permissions" : "Delningen måste åtminstone ha LÄS- eller SKAPA-behörighet",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Delningen måste ha LÄS-behörighet om ÄNDRA- eller RADERA-behörighet är inställd.",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "\"Skicka lösenord via Nextcloud Talk\" för att dela en fil eller mapp misslyckades eftersom Nextcloud Talk inte är aktiverat.",
"shared by %s" : "delad av %s",
"Download all files" : "Hämta alla filer",
diff --git a/apps/files_sharing/l10n/tr.js b/apps/files_sharing/l10n/tr.js
index 54e6a199e29..b067e7b8964 100644
--- a/apps/files_sharing/l10n/tr.js
+++ b/apps/files_sharing/l10n/tr.js
@@ -124,7 +124,7 @@ OC.L10N.register(
"Could not lock path" : "Yol kilitlenemedi",
"Wrong or no update parameter given" : "Parametre yanlış ya da herhangi bir parametre belirtilmemiş",
"Share must at least have READ or CREATE permissions" : "Paylaşım için en az OKUMA ve OLUŞTURMA izinleri olmalıdır",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Paylaşım için GÜNCELLEME ya da SİLME izinleri ayarlanmış ise en az OKUMA izni olmalıdır.",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "UPDATE ya da DELETE izinleri verilmiş ise paylaşıma READ izni verilmelidir",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "Nextcloud Talk etkinleştirilmemiş olduğundan, paylaşım parolası Nextcloud Talk ile gönderilemedi.",
"shared by %s" : "%s tarafından paylaşıldı",
"Download all files" : "Tüm dosyaları indir",
diff --git a/apps/files_sharing/l10n/tr.json b/apps/files_sharing/l10n/tr.json
index f21f07124ad..334b00007c0 100644
--- a/apps/files_sharing/l10n/tr.json
+++ b/apps/files_sharing/l10n/tr.json
@@ -122,7 +122,7 @@
"Could not lock path" : "Yol kilitlenemedi",
"Wrong or no update parameter given" : "Parametre yanlış ya da herhangi bir parametre belirtilmemiş",
"Share must at least have READ or CREATE permissions" : "Paylaşım için en az OKUMA ve OLUŞTURMA izinleri olmalıdır",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "Paylaşım için GÜNCELLEME ya da SİLME izinleri ayarlanmış ise en az OKUMA izni olmalıdır.",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "UPDATE ya da DELETE izinleri verilmiş ise paylaşıma READ izni verilmelidir",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "Nextcloud Talk etkinleştirilmemiş olduğundan, paylaşım parolası Nextcloud Talk ile gönderilemedi.",
"shared by %s" : "%s tarafından paylaşıldı",
"Download all files" : "Tüm dosyaları indir",
diff --git a/apps/files_sharing/l10n/zh_HK.js b/apps/files_sharing/l10n/zh_HK.js
index bd30be52a8f..4c442bb621c 100644
--- a/apps/files_sharing/l10n/zh_HK.js
+++ b/apps/files_sharing/l10n/zh_HK.js
@@ -124,7 +124,7 @@ OC.L10N.register(
"Could not lock path" : "無法鎖定路徑",
"Wrong or no update parameter given" : "更新參數不正確或未提供",
"Share must at least have READ or CREATE permissions" : "分享必須至少具有 READ 或 CREATE 權限",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "如果設置了 UPDATE 或 DELETE 權限,則分享必須具有 READ 權限。",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "如果設置了 UPDATE 或 DELETE 權限,則分享必須具有 READ 權限",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "“通過 Nextcloud Talk 發送密碼”共享檔案或資料夾失敗,因為 Nextcloud Talk 未啟用。",
"shared by %s" : "分享自 %s",
"Download all files" : "下載所有檔案",
diff --git a/apps/files_sharing/l10n/zh_HK.json b/apps/files_sharing/l10n/zh_HK.json
index 140bd797a8b..eb536e6d11d 100644
--- a/apps/files_sharing/l10n/zh_HK.json
+++ b/apps/files_sharing/l10n/zh_HK.json
@@ -122,7 +122,7 @@
"Could not lock path" : "無法鎖定路徑",
"Wrong or no update parameter given" : "更新參數不正確或未提供",
"Share must at least have READ or CREATE permissions" : "分享必須至少具有 READ 或 CREATE 權限",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "如果設置了 UPDATE 或 DELETE 權限,則分享必須具有 READ 權限。",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "如果設置了 UPDATE 或 DELETE 權限,則分享必須具有 READ 權限",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "“通過 Nextcloud Talk 發送密碼”共享檔案或資料夾失敗,因為 Nextcloud Talk 未啟用。",
"shared by %s" : "分享自 %s",
"Download all files" : "下載所有檔案",
diff --git a/apps/files_sharing/l10n/zh_TW.js b/apps/files_sharing/l10n/zh_TW.js
index 661445e743d..da993c906bb 100644
--- a/apps/files_sharing/l10n/zh_TW.js
+++ b/apps/files_sharing/l10n/zh_TW.js
@@ -124,7 +124,7 @@ OC.L10N.register(
"Could not lock path" : "無法鎖定路徑",
"Wrong or no update parameter given" : "更新參數不正確或未提供",
"Share must at least have READ or CREATE permissions" : "分享必須至少有 READ 或 CREATE 權限",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "若設定了 UPDATE 或 DELETE 權限,則分享必須有 READ 權限。",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "若設定了 UPDATE 或 DELETE 權限,則分享必須有 READ 權限",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "「透過 Nextcloud Talk 傳送密碼」分享檔案或資料夾失敗,因為未啟用 Nextcloud Talk。",
"shared by %s" : "分享自 %s",
"Download all files" : "下載所有檔案",
diff --git a/apps/files_sharing/l10n/zh_TW.json b/apps/files_sharing/l10n/zh_TW.json
index ec2124e9914..c10c55a240d 100644
--- a/apps/files_sharing/l10n/zh_TW.json
+++ b/apps/files_sharing/l10n/zh_TW.json
@@ -122,7 +122,7 @@
"Could not lock path" : "無法鎖定路徑",
"Wrong or no update parameter given" : "更新參數不正確或未提供",
"Share must at least have READ or CREATE permissions" : "分享必須至少有 READ 或 CREATE 權限",
- "Share must have READ permission if UPDATE or DELETE permission is set." : "若設定了 UPDATE 或 DELETE 權限,則分享必須有 READ 權限。",
+ "Share must have READ permission if UPDATE or DELETE permission is set" : "若設定了 UPDATE 或 DELETE 權限,則分享必須有 READ 權限",
"\"Sending the password by Nextcloud Talk\" for sharing a file or folder failed because Nextcloud Talk is not enabled." : "「透過 Nextcloud Talk 傳送密碼」分享檔案或資料夾失敗,因為未啟用 Nextcloud Talk。",
"shared by %s" : "分享自 %s",
"Download all files" : "下載所有檔案",
diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php
index 6375ee3d703..069cba42bb6 100644
--- a/apps/files_sharing/lib/Controller/ShareAPIController.php
+++ b/apps/files_sharing/lib/Controller/ShareAPIController.php
@@ -44,6 +44,7 @@ declare(strict_types=1);
*/
namespace OCA\Files_Sharing\Controller;
+use OC\Files\FileInfo;
use OCA\Files_Sharing\Exceptions\SharingRightsException;
use OCA\Files_Sharing\External\Storage;
use OCA\Files\Helper;
@@ -469,12 +470,22 @@ class ShareAPIController extends OCSController {
$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
try {
- $path = $userFolder->get($path);
+ /** @var \OC\Files\Node\Node $node */
+ $node = $userFolder->get($path);
} catch (NotFoundException $e) {
throw new OCSNotFoundException($this->l->t('Wrong path, file/folder does not exist'));
}
- $share->setNode($path);
+ // a user can have access to a file through different paths, with differing permissions
+ // combine all permissions to determine if the user can share this file
+ $nodes = $userFolder->getById($node->getId());
+ foreach ($nodes as $nodeById) {
+ /** @var FileInfo $fileInfo */
+ $fileInfo = $node->getFileInfo();
+ $fileInfo['permissions'] |= $nodeById->getPermissions();
+ }
+
+ $share->setNode($node);
try {
$this->lock($share->getNode());
@@ -489,7 +500,7 @@ class ShareAPIController extends OCSController {
// Shares always require read permissions
$permissions |= Constants::PERMISSION_READ;
- if ($path instanceof \OCP\Files\File) {
+ if ($node instanceof \OCP\Files\File) {
// Single file shares should never have delete or create permissions
$permissions &= ~Constants::PERMISSION_DELETE;
$permissions &= ~Constants::PERMISSION_CREATE;
@@ -500,8 +511,8 @@ class ShareAPIController extends OCSController {
* We check the permissions via webdav. But the permissions of the mount point
* do not equal the share permissions. Here we fix that for federated mounts.
*/
- if ($path->getStorage()->instanceOfStorage(Storage::class)) {
- $permissions &= ~($permissions & ~$path->getPermissions());
+ if ($node->getStorage()->instanceOfStorage(Storage::class)) {
+ $permissions &= ~($permissions & ~$node->getPermissions());
}
if ($shareType === IShare::TYPE_USER) {
@@ -537,7 +548,7 @@ class ShareAPIController extends OCSController {
}
// Public upload can only be set for folders
- if ($path instanceof \OCP\Files\File) {
+ if ($node instanceof \OCP\Files\File) {
throw new OCSNotFoundException($this->l->t('Public upload is only possible for publicly shared folders'));
}
@@ -573,7 +584,7 @@ class ShareAPIController extends OCSController {
if ($sendPasswordByTalk === 'true') {
if (!$this->appManager->isEnabledForUser('spreed')) {
- throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$path->getPath()]));
+ throw new OCSForbiddenException($this->l->t('Sharing %s sending the password by Nextcloud Talk failed because Nextcloud Talk is not enabled', [$node->getPath()]));
}
$share->setSendPasswordByTalk(true);
@@ -590,7 +601,7 @@ class ShareAPIController extends OCSController {
}
} elseif ($shareType === IShare::TYPE_REMOTE) {
if (!$this->shareManager->outgoingServer2ServerSharesAllowed()) {
- throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
+ throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$node->getPath(), $shareType]));
}
if ($shareWith === null) {
@@ -609,7 +620,7 @@ class ShareAPIController extends OCSController {
}
} elseif ($shareType === IShare::TYPE_REMOTE_GROUP) {
if (!$this->shareManager->outgoingServer2ServerGroupSharesAllowed()) {
- throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$path->getPath(), $shareType]));
+ throw new OCSForbiddenException($this->l->t('Sharing %1$s failed because the back end does not allow shares from type %2$s', [$node->getPath(), $shareType]));
}
if ($shareWith === null) {
@@ -643,13 +654,13 @@ class ShareAPIController extends OCSController {
try {
$this->getRoomShareHelper()->createShare($share, $shareWith, $permissions, $expireDate);
} catch (QueryException $e) {
- throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()]));
+ throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$node->getPath()]));
}
} elseif ($shareType === IShare::TYPE_DECK) {
try {
$this->getDeckShareHelper()->createShare($share, $shareWith, $permissions, $expireDate);
} catch (QueryException $e) {
- throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$path->getPath()]));
+ throw new OCSForbiddenException($this->l->t('Sharing %s failed because the back end does not support room shares', [$node->getPath()]));
}
} else {
throw new OCSBadRequestException($this->l->t('Unknown share type'));
@@ -1119,7 +1130,7 @@ class ShareAPIController extends OCSController {
if (!$this->hasPermission($newPermissions, Constants::PERMISSION_READ) && (
$this->hasPermission($newPermissions, Constants::PERMISSION_UPDATE) || $this->hasPermission($newPermissions, Constants::PERMISSION_DELETE)
)) {
- throw new OCSBadRequestException($this->l->t('Share must have READ permission if UPDATE or DELETE permission is set.'));
+ throw new OCSBadRequestException($this->l->t('Share must have READ permission if UPDATE or DELETE permission is set'));
}
}
diff --git a/apps/files_sharing/lib/Migration/Version24000Date20220404142216.php b/apps/files_sharing/lib/Migration/Version24000Date20220404142216.php
new file mode 100644
index 00000000000..05176ebdae9
--- /dev/null
+++ b/apps/files_sharing/lib/Migration/Version24000Date20220404142216.php
@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
+ *
+ * @author Côme Chilliet <come.chilliet@nextcloud.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files_Sharing\Migration;
+
+use Closure;
+use OCP\DB\ISchemaWrapper;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+
+/**
+ * Auto-generated migration step: Please modify to your needs!
+ */
+class Version24000Date20220404142216 extends SimpleMigrationStep {
+ /**
+ * @param IOutput $output
+ * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
+ * @param array $options
+ * @return null|ISchemaWrapper
+ */
+ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
+ /** @var ISchemaWrapper $schema */
+ $schema = $schemaClosure();
+
+ $table = $schema->getTable('share_external');
+ $column = $table->getColumn('name');
+ if ($column->getLength() < 4000) {
+ $column->setLength(4000);
+ return $schema;
+ }
+ return null;
+ }
+}
diff --git a/apps/files_sharing/lib/SharedStorage.php b/apps/files_sharing/lib/SharedStorage.php
index 3ded20eb495..6a342f0bdbf 100644
--- a/apps/files_sharing/lib/SharedStorage.php
+++ b/apps/files_sharing/lib/SharedStorage.php
@@ -35,13 +35,15 @@ namespace OCA\Files_Sharing;
use OC\Files\Cache\FailedCache;
use OC\Files\Cache\NullWatcher;
use OC\Files\Cache\Watcher;
-use OC\Files\Filesystem;
+use OCP\Files\Folder;
+use OCP\Files\Node;
use OC\Files\Storage\FailedStorage;
use OC\Files\Storage\Wrapper\PermissionsMask;
use OC\User\NoUserException;
use OCA\Files_External\Config\ExternalMountPoint;
use OCP\Constants;
use OCP\Files\Cache\ICacheEntry;
+use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\Storage\IDisableEncryptionStorage;
use OCP\Files\Storage\IStorage;
@@ -88,6 +90,11 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto
/** @var boolean */
private $sharingDisabledForUser;
+ /** @var ?Folder $ownerUserFolder */
+ private $ownerUserFolder = null;
+
+ private string $sourcePath = '';
+
public function __construct($arguments) {
$this->ownerView = $arguments['ownerView'];
$this->logger = \OC::$server->getLogger();
@@ -129,14 +136,26 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto
}
$this->initialized = true;
try {
- Filesystem::initMountPoints($this->superShare->getShareOwner());
- $storageId = $this->superShare->getNodeCacheEntry() ? $this->superShare->getNodeCacheEntry()->getStorageId() : null;
- $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId(), $storageId);
- [$this->nonMaskedStorage, $this->rootPath] = $this->ownerView->resolvePath($sourcePath);
- $this->storage = new PermissionsMask([
- 'storage' => $this->nonMaskedStorage,
- 'mask' => $this->superShare->getPermissions(),
- ]);
+ /** @var IRootFolder $rootFolder */
+ $rootFolder = \OC::$server->get(IRootFolder::class);
+ $this->ownerUserFolder = $rootFolder->getUserFolder($this->superShare->getShareOwner());
+ $sourceId = $this->superShare->getNodeId();
+ $ownerNodes = $this->ownerUserFolder->getById($sourceId);
+ /** @var Node|false $ownerNode */
+ $ownerNode = current($ownerNodes);
+ if (!$ownerNode) {
+ $this->storage = new FailedStorage(['exception' => new NotFoundException("File by id $sourceId not found")]);
+ $this->cache = new FailedCache();
+ $this->rootPath = '';
+ } else {
+ $this->nonMaskedStorage = $ownerNode->getStorage();
+ $this->sourcePath = $ownerNode->getPath();
+ $this->rootPath = $ownerNode->getInternalPath();
+ $this->storage = new PermissionsMask([
+ 'storage' => $this->nonMaskedStorage,
+ 'mask' => $this->superShare->getPermissions(),
+ ]);
+ }
} catch (NotFoundException $e) {
// original file not accessible or deleted, set FailedStorage
$this->storage = new FailedStorage(['exception' => $e]);
@@ -444,7 +463,7 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto
$targetStorage->acquireLock($targetInternalPath, $type, $provider);
// lock the parent folders of the owner when locking the share as recipient
if ($path === '') {
- $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
+ $sourcePath = $this->ownerUserFolder->getRelativePath($this->sourcePath);
$this->ownerView->lockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
}
}
@@ -460,7 +479,7 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto
$targetStorage->releaseLock($targetInternalPath, $type, $provider);
// unlock the parent folders of the owner when unlocking the share as recipient
if ($path === '') {
- $sourcePath = $this->ownerView->getPath($this->superShare->getNodeId());
+ $sourcePath = $this->ownerUserFolder->getRelativePath($this->sourcePath);
$this->ownerView->unlockFile(dirname($sourcePath), ILockingProvider::LOCK_SHARED, true);
}
}
diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php
index f3a31578511..c7159e82163 100644
--- a/apps/files_sharing/tests/ApiTest.php
+++ b/apps/files_sharing/tests/ApiTest.php
@@ -383,6 +383,9 @@ class ApiTest extends TestCase {
}
public function testGetAllSharesWithMe() {
+ $this->loginAsUser(self::TEST_FILES_SHARING_API_USER2);
+ $this->logout();
+
$node1 = $this->userFolder->get($this->filename);
$share1 = $this->shareManager->newShare();
$share1->setNode($node1)
diff --git a/apps/files_sharing/tests/CapabilitiesTest.php b/apps/files_sharing/tests/CapabilitiesTest.php
index 093a04052b1..fcefc556203 100644
--- a/apps/files_sharing/tests/CapabilitiesTest.php
+++ b/apps/files_sharing/tests/CapabilitiesTest.php
@@ -139,6 +139,7 @@ class CapabilitiesTest extends \Test\TestCase {
$map = [
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_allow_links', 'yes', 'yes'],
+ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
];
$result = $this->getResults($map);
$this->assertIsArray($result['public']);
@@ -149,6 +150,7 @@ class CapabilitiesTest extends \Test\TestCase {
$map = [
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_allow_links', 'yes', 'yes'],
+ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
['core', 'shareapi_enforce_links_password', 'no', 'yes'],
];
$result = $this->getResults($map);
@@ -161,6 +163,7 @@ class CapabilitiesTest extends \Test\TestCase {
$map = [
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_allow_links', 'yes', 'yes'],
+ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
['core', 'shareapi_enforce_links_password', 'no', 'no'],
];
$result = $this->getResults($map);
@@ -174,6 +177,7 @@ class CapabilitiesTest extends \Test\TestCase {
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_allow_links', 'yes', 'yes'],
['core', 'shareapi_default_expire_date', 'no', 'no'],
+ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
];
$result = $this->getResults($map);
$this->assertArrayHasKey('expire_date', $result['public']);
@@ -188,6 +192,7 @@ class CapabilitiesTest extends \Test\TestCase {
['core', 'shareapi_default_expire_date', 'no', 'yes'],
['core', 'shareapi_expire_after_n_days', '7', '7'],
['core', 'shareapi_enforce_expire_date', 'no', 'no'],
+ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
];
$result = $this->getResults($map);
$this->assertArrayHasKey('expire_date', $result['public']);
@@ -203,6 +208,7 @@ class CapabilitiesTest extends \Test\TestCase {
['core', 'shareapi_allow_links', 'yes', 'yes'],
['core', 'shareapi_default_expire_date', 'no', 'yes'],
['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
+ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
];
$result = $this->getResults($map);
$this->assertArrayHasKey('expire_date', $result['public']);
@@ -215,6 +221,7 @@ class CapabilitiesTest extends \Test\TestCase {
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_allow_links', 'yes', 'yes'],
['core', 'shareapi_allow_public_notification', 'no', 'yes'],
+ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
];
$result = $this->getResults($map);
$this->assertTrue($result['public']['send_mail']);
@@ -225,6 +232,7 @@ class CapabilitiesTest extends \Test\TestCase {
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_allow_links', 'yes', 'yes'],
['core', 'shareapi_allow_public_notification', 'no', 'no'],
+ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
];
$result = $this->getResults($map);
$this->assertFalse($result['public']['send_mail']);
@@ -234,6 +242,7 @@ class CapabilitiesTest extends \Test\TestCase {
$map = [
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_allow_resharing', 'yes', 'yes'],
+ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
];
$result = $this->getResults($map);
$this->assertTrue($result['resharing']);
@@ -243,6 +252,7 @@ class CapabilitiesTest extends \Test\TestCase {
$map = [
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_allow_resharing', 'yes', 'no'],
+ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
];
$result = $this->getResults($map);
$this->assertFalse($result['resharing']);
@@ -253,6 +263,7 @@ class CapabilitiesTest extends \Test\TestCase {
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_allow_links', 'yes', 'yes'],
['core', 'shareapi_allow_public_upload', 'yes', 'yes'],
+ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
];
$result = $this->getResults($map);
$this->assertTrue($result['public']['upload']);
@@ -264,6 +275,7 @@ class CapabilitiesTest extends \Test\TestCase {
['core', 'shareapi_enabled', 'yes', 'yes'],
['core', 'shareapi_allow_links', 'yes', 'yes'],
['core', 'shareapi_allow_public_upload', 'yes', 'no'],
+ ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
];
$result = $this->getResults($map);
$this->assertFalse($result['public']['upload']);
diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
index 324862a746d..4b52f7a2a36 100644
--- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
@@ -1619,6 +1619,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$path->expects($this->once())
->method('lock')
@@ -1651,6 +1653,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$path->expects($this->once())
->method('lock')
@@ -1683,6 +1687,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$path->expects($this->once())
->method('lock')
->with(\OCP\Lock\ILockingProvider::LOCK_SHARED);
@@ -1733,6 +1739,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$this->userManager->method('userExists')->with('validUser')->willReturn(true);
@@ -1787,6 +1795,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$path->expects($this->once())
->method('lock')
@@ -1844,6 +1854,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
@@ -1896,6 +1908,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$this->groupManager->method('groupExists')->with('validGroup')->willReturn(true);
@@ -1926,6 +1940,8 @@ class ShareAPIControllerTest extends TestCase {
$path->method('getStorage')->willReturn($storage);
$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
+ $this->rootFolder->method('getById')
+ ->willReturn([]);
$this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare());
@@ -1945,6 +1961,8 @@ class ShareAPIControllerTest extends TestCase {
$path->method('getStorage')->willReturn($storage);
$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
+ $this->rootFolder->method('getById')
+ ->willReturn([]);
$this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare());
$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
@@ -1965,6 +1983,8 @@ class ShareAPIControllerTest extends TestCase {
$path->method('getStorage')->willReturn($storage);
$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
+ $this->rootFolder->method('getById')
+ ->willReturn([]);
$this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare());
$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
@@ -1984,6 +2004,8 @@ class ShareAPIControllerTest extends TestCase {
$path->method('getStorage')->willReturn($storage);
$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
+ $this->rootFolder->method('getById')
+ ->willReturn([]);
$this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare());
$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
@@ -2018,6 +2040,8 @@ class ShareAPIControllerTest extends TestCase {
$path->method('getStorage')->willReturn($storage);
$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
+ $this->rootFolder->method('getById')
+ ->willReturn([]);
$this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare());
$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
@@ -2052,6 +2076,8 @@ class ShareAPIControllerTest extends TestCase {
$path->method('getStorage')->willReturn($storage);
$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
+ $this->rootFolder->method('getById')
+ ->willReturn([]);
$this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare());
$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
@@ -2094,6 +2120,8 @@ class ShareAPIControllerTest extends TestCase {
$path->method('getPath')->willReturn('valid-path');
$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
+ $this->rootFolder->method('getById')
+ ->willReturn([]);
$this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare());
$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
@@ -2127,6 +2155,8 @@ class ShareAPIControllerTest extends TestCase {
$path->method('getStorage')->willReturn($storage);
$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
+ $this->rootFolder->method('getById')
+ ->willReturn([]);
$this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare());
$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
@@ -2168,6 +2198,8 @@ class ShareAPIControllerTest extends TestCase {
$path->method('getStorage')->willReturn($storage);
$this->rootFolder->method('getUserFolder')->with($this->currentUser)->willReturnSelf();
$this->rootFolder->method('get')->with('valid-path')->willReturn($path);
+ $this->rootFolder->method('getById')
+ ->willReturn([]);
$this->shareManager->method('newShare')->willReturn(\OC::$server->getShareManager()->newShare());
$this->shareManager->method('shareApiAllowLinks')->willReturn(true);
@@ -2216,6 +2248,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$this->userManager->method('userExists')->with('validUser')->willReturn(true);
@@ -2286,6 +2320,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$this->userManager->method('userExists')->with('validUser')->willReturn(true);
@@ -2338,6 +2374,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$path->expects($this->once())
->method('lock')
@@ -2421,6 +2459,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$path->expects($this->once())
->method('lock')
@@ -2461,6 +2501,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$path->expects($this->once())
->method('lock')
@@ -2541,6 +2583,8 @@ class ShareAPIControllerTest extends TestCase {
->method('get')
->with('valid-path')
->willReturn($path);
+ $userFolder->method('getById')
+ ->willReturn([]);
$this->userManager->method('userExists')->with('validUser')->willReturn(true);
@@ -2881,7 +2925,7 @@ class ShareAPIControllerTest extends TestCase {
*/
public function testUpdateLinkShareSetInvalidCRUDPermissions2($permissions) {
$this->expectException(\OCP\AppFramework\OCS\OCSBadRequestException::class);
- $this->expectExceptionMessage('Share must have READ permission if UPDATE or DELETE permission is set.');
+ $this->expectExceptionMessage('Share must have READ permission if UPDATE or DELETE permission is set');
$this->testUpdateLinkShareSetCRUDPermissions($permissions);
}
diff --git a/apps/files_trashbin/appinfo/info.xml b/apps/files_trashbin/appinfo/info.xml
index 91f89672b11..e5308a2e3fd 100644
--- a/apps/files_trashbin/appinfo/info.xml
+++ b/apps/files_trashbin/appinfo/info.xml
@@ -35,6 +35,7 @@ To prevent a user from running out of disk space, the Deleted files app will not
<command>OCA\Files_Trashbin\Command\CleanUp</command>
<command>OCA\Files_Trashbin\Command\ExpireTrash</command>
<command>OCA\Files_Trashbin\Command\Size</command>
+ <command>OCA\Files_Trashbin\Command\RestoreAllFiles</command>
</commands>
<sabre>
diff --git a/apps/files_trashbin/composer/composer/autoload_classmap.php b/apps/files_trashbin/composer/composer/autoload_classmap.php
index 7ce7e565c83..760044d4f87 100644
--- a/apps/files_trashbin/composer/composer/autoload_classmap.php
+++ b/apps/files_trashbin/composer/composer/autoload_classmap.php
@@ -13,6 +13,7 @@ return array(
'OCA\\Files_Trashbin\\Command\\CleanUp' => $baseDir . '/../lib/Command/CleanUp.php',
'OCA\\Files_Trashbin\\Command\\Expire' => $baseDir . '/../lib/Command/Expire.php',
'OCA\\Files_Trashbin\\Command\\ExpireTrash' => $baseDir . '/../lib/Command/ExpireTrash.php',
+ 'OCA\\Files_Trashbin\\Command\\RestoreAllFiles' => $baseDir . '/../lib/Command/RestoreAllFiles.php',
'OCA\\Files_Trashbin\\Command\\Size' => $baseDir . '/../lib/Command/Size.php',
'OCA\\Files_Trashbin\\Controller\\PreviewController' => $baseDir . '/../lib/Controller/PreviewController.php',
'OCA\\Files_Trashbin\\Events\\MoveToTrashEvent' => $baseDir . '/../lib/Events/MoveToTrashEvent.php',
diff --git a/apps/files_trashbin/composer/composer/autoload_static.php b/apps/files_trashbin/composer/composer/autoload_static.php
index 2f6d1936a28..ef52ac0e1e7 100644
--- a/apps/files_trashbin/composer/composer/autoload_static.php
+++ b/apps/files_trashbin/composer/composer/autoload_static.php
@@ -28,6 +28,7 @@ class ComposerStaticInitFiles_Trashbin
'OCA\\Files_Trashbin\\Command\\CleanUp' => __DIR__ . '/..' . '/../lib/Command/CleanUp.php',
'OCA\\Files_Trashbin\\Command\\Expire' => __DIR__ . '/..' . '/../lib/Command/Expire.php',
'OCA\\Files_Trashbin\\Command\\ExpireTrash' => __DIR__ . '/..' . '/../lib/Command/ExpireTrash.php',
+ 'OCA\\Files_Trashbin\\Command\\RestoreAllFiles' => __DIR__ . '/..' . '/../lib/Command/RestoreAllFiles.php',
'OCA\\Files_Trashbin\\Command\\Size' => __DIR__ . '/..' . '/../lib/Command/Size.php',
'OCA\\Files_Trashbin\\Controller\\PreviewController' => __DIR__ . '/..' . '/../lib/Controller/PreviewController.php',
'OCA\\Files_Trashbin\\Events\\MoveToTrashEvent' => __DIR__ . '/..' . '/../lib/Events/MoveToTrashEvent.php',
diff --git a/apps/files_trashbin/composer/composer/installed.php b/apps/files_trashbin/composer/composer/installed.php
index 5440719fa40..914fa1a857f 100644
--- a/apps/files_trashbin/composer/composer/installed.php
+++ b/apps/files_trashbin/composer/composer/installed.php
@@ -5,7 +5,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../',
'aliases' => array(),
- 'reference' => 'c6429e6cd19c57582364338362e543580821cf99',
+ 'reference' => 'ff67123569a861301d14f83f7b2310e9a518c46d',
'name' => '__root__',
'dev' => false,
),
@@ -16,7 +16,7 @@
'type' => 'library',
'install_path' => __DIR__ . '/../',
'aliases' => array(),
- 'reference' => 'c6429e6cd19c57582364338362e543580821cf99',
+ 'reference' => 'ff67123569a861301d14f83f7b2310e9a518c46d',
'dev_requirement' => false,
),
),
diff --git a/apps/files_trashbin/lib/Command/RestoreAllFiles.php b/apps/files_trashbin/lib/Command/RestoreAllFiles.php
new file mode 100644
index 00000000000..43e9363327b
--- /dev/null
+++ b/apps/files_trashbin/lib/Command/RestoreAllFiles.php
@@ -0,0 +1,161 @@
+<?php
+/**
+ * @copyright Copyright (c) 2021, Caitlin Hogan (cahogan16@gmail.com)
+ * @license AGPL-3.0
+ *
+ * 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\Files_Trashbin\Command;
+
+use OC\Core\Command\Base;
+use OCP\Files\IRootFolder;
+use OCP\IDBConnection;
+use OCP\IL10N;
+use OCP\IUserBackend;
+use OCA\Files_Trashbin\Trashbin;
+use OCA\Files_Trashbin\Helper;
+use OCP\IUserManager;
+use OCP\L10N\IFactory;
+use Symfony\Component\Console\Exception\InvalidOptionException;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class RestoreAllFiles extends Base {
+
+ /** @var IUserManager */
+ protected $userManager;
+
+ /** @var IRootFolder */
+ protected $rootFolder;
+
+ /** @var \OCP\IDBConnection */
+ protected $dbConnection;
+
+ /** @var IL10N */
+ protected $l10n;
+
+ /**
+ * @param IRootFolder $rootFolder
+ * @param IUserManager $userManager
+ * @param IDBConnection $dbConnection
+ */
+ public function __construct(IRootFolder $rootFolder, IUserManager $userManager, IDBConnection $dbConnection, IFactory $l10nFactory) {
+ parent::__construct();
+ $this->userManager = $userManager;
+ $this->rootFolder = $rootFolder;
+ $this->dbConnection = $dbConnection;
+ $this->l10n = $l10nFactory->get('files_trashbin');
+ }
+
+ protected function configure(): void {
+ parent::configure();
+ $this
+ ->setName('trashbin:restore')
+ ->setDescription('Restore all deleted files')
+ ->addArgument(
+ 'user_id',
+ InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
+ 'restore all deleted files of the given user(s)'
+ )
+ ->addOption(
+ 'all-users',
+ null,
+ InputOption::VALUE_NONE,
+ 'run action on all users'
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ /** @var string[] $users */
+ $users = $input->getArgument('user_id');
+ if ((!empty($users)) and ($input->getOption('all-users'))) {
+ throw new InvalidOptionException('Either specify a user_id or --all-users');
+ } elseif (!empty($users)) {
+ foreach ($users as $user) {
+ if ($this->userManager->userExists($user)) {
+ $output->writeln("Restoring deleted files for user <info>$user</info>");
+ $this->restoreDeletedFiles($user, $output);
+ } else {
+ $output->writeln("<error>Unknown user $user</error>");
+ return 1;
+ }
+ }
+ } elseif ($input->getOption('all-users')) {
+ $output->writeln('Restoring deleted files for all users');
+ foreach ($this->userManager->getBackends() as $backend) {
+ $name = get_class($backend);
+ if ($backend instanceof IUserBackend) {
+ $name = $backend->getBackendName();
+ }
+ $output->writeln("Restoring deleted files for users on backend <info>$name</info>");
+ $limit = 500;
+ $offset = 0;
+ do {
+ $users = $backend->getUsers('', $limit, $offset);
+ foreach ($users as $user) {
+ $output->writeln("<info>$user</info>");
+ $this->restoreDeletedFiles($user, $output);
+ }
+ $offset += $limit;
+ } while (count($users) >= $limit);
+ }
+ } else {
+ throw new InvalidOptionException('Either specify a user_id or --all-users');
+ }
+ return 0;
+ }
+
+ /**
+ * Restore deleted files for the given user
+ *
+ * @param string $uid
+ * @param OutputInterface $output
+ */
+ protected function restoreDeletedFiles(string $uid, OutputInterface $output): void {
+ \OC_Util::tearDownFS();
+ \OC_Util::setupFS($uid);
+ \OC_User::setUserId($uid);
+
+ $filesInTrash = Helper::getTrashFiles('/', $uid, 'mtime');
+ $trashCount = count($filesInTrash);
+ if ($trashCount == 0) {
+ $output->writeln("User has no deleted files in the trashbin");
+ return;
+ }
+ $output->writeln("Preparing to restore <info>$trashCount</info> files...");
+ $count = 0;
+ foreach ($filesInTrash as $trashFile) {
+ $filename = $trashFile->getName();
+ $timestamp = $trashFile->getMtime();
+ $humanTime = $this->l10n->l('datetime', $timestamp);
+ $output->write("File <info>$filename</info> originally deleted at <info>$humanTime</info> ");
+ $file = $filename . '.d' . $timestamp;
+ $location = Trashbin::getLocation($uid, $filename, (string) $timestamp);
+ if ($location === '.') {
+ $location = '';
+ }
+ $output->write("restoring to <info>/$location</info>:");
+ if (Trashbin::restore($file, $filename, $timestamp)) {
+ $count = $count + 1;
+ $output->writeln(" <info>success</info>");
+ } else {
+ $output->writeln(" <error>failed</error>");
+ }
+ }
+
+ $output->writeln("Successfully restored <info>$count</info> out of <info>$trashCount</info> files.");
+ }
+}
diff --git a/apps/files_versions/lib/Storage.php b/apps/files_versions/lib/Storage.php
index a6674ab244b..3f91e32ef95 100644
--- a/apps/files_versions/lib/Storage.php
+++ b/apps/files_versions/lib/Storage.php
@@ -543,9 +543,10 @@ class Storage {
});
foreach ($versions as $version) {
- \OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $version->getInternalPath(), 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
+ $internalPath = $version->getInternalPath();
+ \OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $internalPath, 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
$version->delete();
- \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $version->getInternalPath(), 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
+ \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $internalPath, 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
}
}
diff --git a/apps/settings/l10n/de.js b/apps/settings/l10n/de.js
index 366a2a12e83..c2b6a1167e1 100644
--- a/apps/settings/l10n/de.js
+++ b/apps/settings/l10n/de.js
@@ -219,7 +219,9 @@ OC.L10N.register(
"Copy" : "Kopieren",
"Could not copy app password. Please copy it manually." : "Das Passwort für die App konnte nicht kopiert werden. Bitte kopiere es manuell.",
"Profile" : "Profil",
+ "Enable or disable profile by default for new users." : "Profil für neue Benutzer standardmäßig aktivieren oder deaktivieren",
"Enable" : "Aktivieren",
+ "Unable to update profile default setting" : "Standardeinstellung des Profils kann nicht aktualisiert werden",
"Rename group" : "Gruppe umbenennen",
"Remove group" : "Gruppe entfernen",
"You are about to remove the group {group}. The users will NOT be deleted." : "Du bist dabei die Gruppe {group} zu löschen. Die Benutzer werden NICHT gelöscht.",
@@ -264,6 +266,7 @@ OC.L10N.register(
"Change scope level of {accountProperty}" : "Geltungsbereich von {accountProperty} ändern",
"Unable to update federation scope of the primary {accountProperty}" : "Der Federation-Bereich des primären {accountProperty} konnte nicht aktualisiert werden",
"Unable to update federation scope of additional {accountProperty}" : "Der Federation-Bereich des zusätzlichen {accountProperty} konnte nicht aktualisiert werden",
+ "Add additional email" : "Zusätzliche E-Mail-Adresse hinzufügen",
"Add" : "Hinzufügen",
"You do not have permissions to see the details of this user" : "Du hast keine Berechtigung, um auf die Details dieses Benutzers zu sehen",
"Add new password" : "Neues Passwort hinzufügen",
diff --git a/apps/settings/l10n/de.json b/apps/settings/l10n/de.json
index cba1547b11b..45e1313dda4 100644
--- a/apps/settings/l10n/de.json
+++ b/apps/settings/l10n/de.json
@@ -217,7 +217,9 @@
"Copy" : "Kopieren",
"Could not copy app password. Please copy it manually." : "Das Passwort für die App konnte nicht kopiert werden. Bitte kopiere es manuell.",
"Profile" : "Profil",
+ "Enable or disable profile by default for new users." : "Profil für neue Benutzer standardmäßig aktivieren oder deaktivieren",
"Enable" : "Aktivieren",
+ "Unable to update profile default setting" : "Standardeinstellung des Profils kann nicht aktualisiert werden",
"Rename group" : "Gruppe umbenennen",
"Remove group" : "Gruppe entfernen",
"You are about to remove the group {group}. The users will NOT be deleted." : "Du bist dabei die Gruppe {group} zu löschen. Die Benutzer werden NICHT gelöscht.",
@@ -262,6 +264,7 @@
"Change scope level of {accountProperty}" : "Geltungsbereich von {accountProperty} ändern",
"Unable to update federation scope of the primary {accountProperty}" : "Der Federation-Bereich des primären {accountProperty} konnte nicht aktualisiert werden",
"Unable to update federation scope of additional {accountProperty}" : "Der Federation-Bereich des zusätzlichen {accountProperty} konnte nicht aktualisiert werden",
+ "Add additional email" : "Zusätzliche E-Mail-Adresse hinzufügen",
"Add" : "Hinzufügen",
"You do not have permissions to see the details of this user" : "Du hast keine Berechtigung, um auf die Details dieses Benutzers zu sehen",
"Add new password" : "Neues Passwort hinzufügen",
diff --git a/apps/settings/l10n/hu.js b/apps/settings/l10n/hu.js
index 71098ba34f7..4072a4ea6a4 100644
--- a/apps/settings/l10n/hu.js
+++ b/apps/settings/l10n/hu.js
@@ -43,6 +43,7 @@ OC.L10N.register(
"You changed your email address" : "Megváltoztatta az e-mail címét",
"Your email address was changed by an administrator" : "Az e-mail címét megváltoztatta egy rendszergazda",
"You created app password \"{token}\"" : "Létrehozta a(z) „{token}” alkalmazásjelszót",
+ "An administrator created app password \"{token}\"" : "Egy rendszergazda létrehozta a(z) „{token}” alkalmazásjelszót",
"You deleted app password \"{token}\"" : "Törölte a(z) „{token}” alkalmazásjelszót",
"You renamed app password \"{token}\" to \"{newToken}\"" : "Átnevezted a(z) „{token}” alkalmazásjelszót erre: „{newToken}”",
"You granted filesystem access to app password \"{token}\"" : "Fájlrendszer-hozzáférést adott a(z) „{token}” alkalmazásjelszónak",
@@ -66,6 +67,14 @@ OC.L10N.register(
"Federated Cloud Sharing" : "Föderált felhőmegosztás",
"cURL is using an outdated %1$s version (%2$s). Please update your operating system or features such as %3$s will not work reliably." : "A cURL elavult %1$s verziót (%2$s) használ. Frissítse az operációs rendszert, vagy az egyes funkciók (mint például a %3$s) megbízhatatlanul fognak működni.",
"Could not determine if TLS version of cURL is outdated or not because an error happened during the HTTPS request against https://nextcloud.com. Please check the nextcloud log file for more details." : "Nem sikerült megállapítani, hogy a cURL TLS-verziója elavult-e vagy sem, mert hiba történt a https://nextcloud.com felé küldött HTTPS-kérés során. További részletekért, ellenőrizze a Nextcloud naplófájlját.",
+ "The PHP OPcache module is not loaded. For better performance it is recommended to load it into your PHP installation." : "A PHP OPcache modul nincs betöltve. A jobb teljesítmény érdekében javasoljuk, hogy töltse be a PHP telepítésébe.",
+ "OPcache is disabled. For better performance, it is recommended to apply <code>opcache.enable=1</code> to your PHP configuration." : "Az OPcache ki van kapcsolva. A jobb teljesítmény érdekében ajánlatos, hogy beállítsa az <code>opcache.enable=1</code> értéket a PHP konfigurációjába.",
+ "OPcache is configured to remove code comments. With OPcache enabled, <code>opcache.save_comments=1</code> must be set for Nextcloud to function." : "Az OPcache úgy van beállítva, hogy eltávolítja a kódban lévő megjegyzéseket. Ha az OPcache be van kapcsolva, akkor be kell állítani az <code>opcache.save_comments=1</code> értéket, hogy a Nextcloud működjön.",
+ "Nextcloud is not allowed to use the OPcache API. With OPcache enabled, it is highly recommended to include all Nextcloud directories with <code>opcache.restrict_api</code> or unset this setting to disable OPcache API restrictions, to prevent errors during Nextcloud core or app upgrades." : "A Nextcloud számára nem engedélyezett az OPcache API használata. Ha be van kapcsolva az OPcache, akkor erősen ajánlott, hogy a Nexcloud összes könyvtára szerepeljen az <code>opcache.restrict_api</code> beállításban, vagy kapcsolja ki, hogy letiltsa az OPcache API korlátozásait, hogy megakadályozza a Nextcloud magjának vagy alkalmazásainak frissítése során fellépő hibákat.",
+ "Nextcloud is not allowed to use the OPcache API. It is highly recommended to include all Nextcloud directories with <code>opcache.restrict_api</code> or unset this setting to disable OPcache API restrictions, to prevent errors during Nextcloud core or app upgrades." : "A Nextcloud számára nem engedélyezett az OPcache API használata. Erősen ajánlott, hogy a Nexcloud összes könyvtára szerepeljen az <code>opcache.restrict_api</code> beállításban, vagy kapcsolja ki, hogy letiltsa az OPcache API korlátozásait, hogy megakadályozza a Nextcloud magjának vagy alkalmazásainak frissítése során fellépő hibákat.",
+ "The maximum number of OPcache keys is nearly exceeded. To assure that all scripts can be hold in cache, it is recommended to apply <code>opcache.max_accelerated_files</code> to your PHP configuration with a value higher than <code>%s</code>." : "Majdnem túllépte az OPcache kulcsok legnagyobb számát. Hogy biztosítsa, hogy az összes parancsfájl tárolható legyen a gyorsítótárban, ajánlatos, hogy a(z) <code>%s</code> értéknél nagyobbra állítsa az <code>opcache.max_accelerated_files</code> beállítást a PHP konfigurációjában.",
+ "The OPcache buffer is nearly full. To assure that all scripts can be hold in cache, it is recommended to apply <code>opcache.memory_consumption</code> to your PHP configuration with a value higher than <code>%s</code>." : "Az OPcache puffer majdnem megtelt. Hogy biztosítsa, hogy az összes parancsfájl tárolható legyen a gyorsítótárban, ajánlatos, hogy a(z) <code>%s</code> értéknél nagyobbra állítsa az <code>opcache.max_accelerated_files</code> beállítást a PHP konfigurációjában.",
+ "The OPcache interned strings buffer is nearly full. To assure that repeating strings can be effectively cached, it is recommended to apply <code>opcache.interned_strings_buffer</code> to your PHP configuration with a value higher than <code>%s</code>." : "Az OPcache internalizált karakterláncokat tartalmazó puffere majdnem megtelt. Hogy biztosítsa, hogy az ismétlődő karakterláncok hatásosan gyorsítótárazhatók legyenek, ajánlatos, hogy a(z) <code>%s</code> értéknél nagyobbra állítsa az <code>opcache.interned_strings_buffer</code> beállítást a PHP konfigurációjában.",
"Invalid SMTP password." : "Érvénytelen SMTP-jelszó.",
"Email setting test" : "E-mail beállítás tesztelése",
"Well done, %s!" : "Szép munka, %s!",
@@ -218,7 +227,9 @@ OC.L10N.register(
"Copy" : "Másolás",
"Could not copy app password. Please copy it manually." : "Nem lehet az alkalmazásjelszót másolni. Másolja át kézileg.",
"Profile" : "Profil",
+ "Enable or disable profile by default for new users." : "A profil alapértelmezett engedélyezése vagy letiltása az új felhasználók számára.",
"Enable" : "Engedélyezés",
+ "Unable to update profile default setting" : "A profil alapértelmezett beállítása nem frissíthető",
"Rename group" : "Csoport átnevezése",
"Remove group" : "Csoport eltávolítása",
"You are about to remove the group {group}. The users will NOT be deleted." : "A(z) {group} csoport eltávolítására készül. A felhasználók NEM lesznek törölve.",
@@ -263,6 +274,7 @@ OC.L10N.register(
"Change scope level of {accountProperty}" : "A(z) {accountProperty} hatókörszintjének módosítása",
"Unable to update federation scope of the primary {accountProperty}" : "Az elsődleges {accountProperty} föderációs hatóköre nem frissíthető",
"Unable to update federation scope of additional {accountProperty}" : "A további {accountProperty} föderációs hatóköre nem frissíthető",
+ "Add additional email" : "További e-mail hozzáadása",
"Add" : "Hozzáadás",
"You do not have permissions to see the details of this user" : "Nincs jogosultsága megnézni a felhasználó részletes adatait",
"Add new password" : "Új jelszó hozzáadása",
@@ -469,6 +481,7 @@ OC.L10N.register(
"Remove image" : "Kép eltávolítása",
"png or jpg, max. 20 MB" : "png vagy jpg, legfeljebb 20 MB",
"Picture provided by original account" : "Az eredeti fiók által biztosított kép.",
+ "Please note that it can take up to 24 hours for the avatar to get updated everywhere." : "Vegye figyelembe, hogy akár 24 óráig is eltarthat, amíg a profilkép mindenhol frissül.",
"Choose as profile picture" : "Kiválasztás profilképként",
"You are a member of the following groups:" : "Ön a következő csoportok tagja:",
"You are using <strong>%s</strong>" : "Jelenleg használt: <strong>%s</strong>",
diff --git a/apps/settings/l10n/hu.json b/apps/settings/l10n/hu.json
index 4245091b0b5..eba92f19144 100644
--- a/apps/settings/l10n/hu.json
+++ b/apps/settings/l10n/hu.json
@@ -41,6 +41,7 @@
"You changed your email address" : "Megváltoztatta az e-mail címét",
"Your email address was changed by an administrator" : "Az e-mail címét megváltoztatta egy rendszergazda",
"You created app password \"{token}\"" : "Létrehozta a(z) „{token}” alkalmazásjelszót",
+ "An administrator created app password \"{token}\"" : "Egy rendszergazda létrehozta a(z) „{token}” alkalmazásjelszót",
"You deleted app password \"{token}\"" : "Törölte a(z) „{token}” alkalmazásjelszót",
"You renamed app password \"{token}\" to \"{newToken}\"" : "Átnevezted a(z) „{token}” alkalmazásjelszót erre: „{newToken}”",
"You granted filesystem access to app password \"{token}\"" : "Fájlrendszer-hozzáférést adott a(z) „{token}” alkalmazásjelszónak",
@@ -64,6 +65,14 @@
"Federated Cloud Sharing" : "Föderált felhőmegosztás",
"cURL is using an outdated %1$s version (%2$s). Please update your operating system or features such as %3$s will not work reliably." : "A cURL elavult %1$s verziót (%2$s) használ. Frissítse az operációs rendszert, vagy az egyes funkciók (mint például a %3$s) megbízhatatlanul fognak működni.",
"Could not determine if TLS version of cURL is outdated or not because an error happened during the HTTPS request against https://nextcloud.com. Please check the nextcloud log file for more details." : "Nem sikerült megállapítani, hogy a cURL TLS-verziója elavult-e vagy sem, mert hiba történt a https://nextcloud.com felé küldött HTTPS-kérés során. További részletekért, ellenőrizze a Nextcloud naplófájlját.",
+ "The PHP OPcache module is not loaded. For better performance it is recommended to load it into your PHP installation." : "A PHP OPcache modul nincs betöltve. A jobb teljesítmény érdekében javasoljuk, hogy töltse be a PHP telepítésébe.",
+ "OPcache is disabled. For better performance, it is recommended to apply <code>opcache.enable=1</code> to your PHP configuration." : "Az OPcache ki van kapcsolva. A jobb teljesítmény érdekében ajánlatos, hogy beállítsa az <code>opcache.enable=1</code> értéket a PHP konfigurációjába.",
+ "OPcache is configured to remove code comments. With OPcache enabled, <code>opcache.save_comments=1</code> must be set for Nextcloud to function." : "Az OPcache úgy van beállítva, hogy eltávolítja a kódban lévő megjegyzéseket. Ha az OPcache be van kapcsolva, akkor be kell állítani az <code>opcache.save_comments=1</code> értéket, hogy a Nextcloud működjön.",
+ "Nextcloud is not allowed to use the OPcache API. With OPcache enabled, it is highly recommended to include all Nextcloud directories with <code>opcache.restrict_api</code> or unset this setting to disable OPcache API restrictions, to prevent errors during Nextcloud core or app upgrades." : "A Nextcloud számára nem engedélyezett az OPcache API használata. Ha be van kapcsolva az OPcache, akkor erősen ajánlott, hogy a Nexcloud összes könyvtára szerepeljen az <code>opcache.restrict_api</code> beállításban, vagy kapcsolja ki, hogy letiltsa az OPcache API korlátozásait, hogy megakadályozza a Nextcloud magjának vagy alkalmazásainak frissítése során fellépő hibákat.",
+ "Nextcloud is not allowed to use the OPcache API. It is highly recommended to include all Nextcloud directories with <code>opcache.restrict_api</code> or unset this setting to disable OPcache API restrictions, to prevent errors during Nextcloud core or app upgrades." : "A Nextcloud számára nem engedélyezett az OPcache API használata. Erősen ajánlott, hogy a Nexcloud összes könyvtára szerepeljen az <code>opcache.restrict_api</code> beállításban, vagy kapcsolja ki, hogy letiltsa az OPcache API korlátozásait, hogy megakadályozza a Nextcloud magjának vagy alkalmazásainak frissítése során fellépő hibákat.",
+ "The maximum number of OPcache keys is nearly exceeded. To assure that all scripts can be hold in cache, it is recommended to apply <code>opcache.max_accelerated_files</code> to your PHP configuration with a value higher than <code>%s</code>." : "Majdnem túllépte az OPcache kulcsok legnagyobb számát. Hogy biztosítsa, hogy az összes parancsfájl tárolható legyen a gyorsítótárban, ajánlatos, hogy a(z) <code>%s</code> értéknél nagyobbra állítsa az <code>opcache.max_accelerated_files</code> beállítást a PHP konfigurációjában.",
+ "The OPcache buffer is nearly full. To assure that all scripts can be hold in cache, it is recommended to apply <code>opcache.memory_consumption</code> to your PHP configuration with a value higher than <code>%s</code>." : "Az OPcache puffer majdnem megtelt. Hogy biztosítsa, hogy az összes parancsfájl tárolható legyen a gyorsítótárban, ajánlatos, hogy a(z) <code>%s</code> értéknél nagyobbra állítsa az <code>opcache.max_accelerated_files</code> beállítást a PHP konfigurációjában.",
+ "The OPcache interned strings buffer is nearly full. To assure that repeating strings can be effectively cached, it is recommended to apply <code>opcache.interned_strings_buffer</code> to your PHP configuration with a value higher than <code>%s</code>." : "Az OPcache internalizált karakterláncokat tartalmazó puffere majdnem megtelt. Hogy biztosítsa, hogy az ismétlődő karakterláncok hatásosan gyorsítótárazhatók legyenek, ajánlatos, hogy a(z) <code>%s</code> értéknél nagyobbra állítsa az <code>opcache.interned_strings_buffer</code> beállítást a PHP konfigurációjában.",
"Invalid SMTP password." : "Érvénytelen SMTP-jelszó.",
"Email setting test" : "E-mail beállítás tesztelése",
"Well done, %s!" : "Szép munka, %s!",
@@ -216,7 +225,9 @@
"Copy" : "Másolás",
"Could not copy app password. Please copy it manually." : "Nem lehet az alkalmazásjelszót másolni. Másolja át kézileg.",
"Profile" : "Profil",
+ "Enable or disable profile by default for new users." : "A profil alapértelmezett engedélyezése vagy letiltása az új felhasználók számára.",
"Enable" : "Engedélyezés",
+ "Unable to update profile default setting" : "A profil alapértelmezett beállítása nem frissíthető",
"Rename group" : "Csoport átnevezése",
"Remove group" : "Csoport eltávolítása",
"You are about to remove the group {group}. The users will NOT be deleted." : "A(z) {group} csoport eltávolítására készül. A felhasználók NEM lesznek törölve.",
@@ -261,6 +272,7 @@
"Change scope level of {accountProperty}" : "A(z) {accountProperty} hatókörszintjének módosítása",
"Unable to update federation scope of the primary {accountProperty}" : "Az elsődleges {accountProperty} föderációs hatóköre nem frissíthető",
"Unable to update federation scope of additional {accountProperty}" : "A további {accountProperty} föderációs hatóköre nem frissíthető",
+ "Add additional email" : "További e-mail hozzáadása",
"Add" : "Hozzáadás",
"You do not have permissions to see the details of this user" : "Nincs jogosultsága megnézni a felhasználó részletes adatait",
"Add new password" : "Új jelszó hozzáadása",
@@ -467,6 +479,7 @@
"Remove image" : "Kép eltávolítása",
"png or jpg, max. 20 MB" : "png vagy jpg, legfeljebb 20 MB",
"Picture provided by original account" : "Az eredeti fiók által biztosított kép.",
+ "Please note that it can take up to 24 hours for the avatar to get updated everywhere." : "Vegye figyelembe, hogy akár 24 óráig is eltarthat, amíg a profilkép mindenhol frissül.",
"Choose as profile picture" : "Kiválasztás profilképként",
"You are a member of the following groups:" : "Ön a következő csoportok tagja:",
"You are using <strong>%s</strong>" : "Jelenleg használt: <strong>%s</strong>",
diff --git a/apps/settings/l10n/pt_BR.js b/apps/settings/l10n/pt_BR.js
index 1733a9a893f..fd3848144eb 100644
--- a/apps/settings/l10n/pt_BR.js
+++ b/apps/settings/l10n/pt_BR.js
@@ -72,6 +72,7 @@ OC.L10N.register(
"If you received this email, the email configuration seems to be correct." : "Se você recebeu este e-mail, é sinal que a configuração do servidor de e-mail está correta.",
"Email could not be sent. Check your mail server log" : "O e-mail não pôde ser enviado. Verifique o log do servidor de e-mail",
"A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Ocorreu um problema ao enviar o e-mail. Por favor, revise suas configurações. (Erro: %s)",
+ "You need to set your user email before being able to send test emails. Go to %s for that." : "Você precisa definir seu e-mail de usuário antes de poder enviar e-mails de teste. Vá a %s para isso.",
"Invalid user" : "Usuário inválido",
"Invalid mail address" : "Endereço de e-mail inválido",
"Settings saved" : "Configurações salvas",
@@ -126,6 +127,7 @@ OC.L10N.register(
"Verifying" : "Verificando",
"A background job is pending that checks for user imported SSL certificates. Please check back later." : "Um trabalho em segundo plano está pendente que verifica se há certificados SSL importados pelo usuário. Por favor, volte mais tarde.",
"There are some user imported SSL certificates present, that are not used anymore with Nextcloud 21. They can be imported on the command line via \"occ security:certificates:import\" command. Their paths inside the data directory are shown below." : "Existem alguns certificados SSL importados pelo usuário presentes, que não são mais usados com o Nextcloud 21. Eles podem ser importados na linha de comando através do comando \"occ security:certificates:import\". Seus caminhos dentro do diretório de dados são mostrados abaixo.",
+ "Invalid UUIDs of LDAP users or groups have been found. Please review your \"Override UUID detection\" settings in the Expert part of the LDAP configuration and use \"occ ldap:update-uuid\" to update them." : "UUIDs inválidos de usuários ou grupos LDAP foram encontrados. Revise suas configurações de \"Substituir detecção de UUID\" na parte Expert da configuração LDAP e use \"occ ldap:update-uuid\" para atualizá-las.",
"The old server-side-encryption format is enabled. We recommend disabling this." : "O antigo formato de criptografia do lado do servidor está ativado. Recomendamos desativar isso.",
"MariaDB version \"%s\" is used. Nextcloud 21 will no longer support this version and requires MariaDB 10.2 or higher." : "Está em uso o MariaDB versão \"%s\". O Nextcloud 21 terá mais suporte para essa versão e requer MariaDB 10.2 ou posterior.",
"MySQL version \"%s\" is used. Nextcloud 21 will no longer support this version and requires MySQL 8.0 or MariaDB 10.2 or higher." : "Está sendo usado a versão \"%s\" do MySQL. O Nextcloud 21 não suportará mais esta versão e irá requerer MySQL 8.0 ou MariaDB 10.2 ou superior. ",
@@ -166,6 +168,7 @@ OC.L10N.register(
"Featured" : "Destaques",
"Update to {update}" : "Atualizar para {update}",
"Update all" : "Atualizar todos",
+ "All apps are up-to-date." : "Todos os aplicativos estão atualizados.",
"Results from other categories" : "Resultados de outras categorias",
"No apps found for your version" : "Nenhum aplicativo encontrado para a sua versão",
"Disable all" : "Desativar tudo",
@@ -216,6 +219,7 @@ OC.L10N.register(
"Could not copy app password. Please copy it manually." : "Não foi possível copiar a senha do aplicativo. Copie-a manualmente.",
"Profile" : "Perfil",
"Enable" : "Ativar",
+ "Rename group" : "Renomear grupo",
"Remove group" : "Excluir grupo",
"You are about to remove the group {group}. The users will NOT be deleted." : "Você está prestes a remover o grupo {group}. Os usuários NÃO serão apagados.",
"Please confirm the group removal " : "Confirme a remoção do grupo",
@@ -385,6 +389,7 @@ OC.L10N.register(
"SMTP Username" : "Nome do Usuário SMTP",
"SMTP Password" : "Senha SMTP",
"Save" : "Salvar",
+ "Test and verify email settings" : "Testar e verificar as configurações de e-mail",
"Send email" : "Enviar e-mail",
"It's important for the security and performance of your instance that everything is configured correctly. To help you with that we are doing some automatic checks. Please see the linked documentation for more information." : "Para segurança e desempenho da sua instalação é importante que tudo esteja configurado corretamente. Para ajudá-lo com isso, estamos fazendo algumas verificações automáticas. Consulte a documentação para mais informações.",
"All checks passed." : "Todas as verificações passaram.",
@@ -464,6 +469,7 @@ OC.L10N.register(
"Remove image" : "Remover imagem",
"png or jpg, max. 20 MB" : "png ou jpg, max. 20 MB",
"Picture provided by original account" : "Imagem fornecida pela conta original",
+ "Please note that it can take up to 24 hours for the avatar to get updated everywhere." : "Observe que pode levar até 24 horas para que o avatar seja atualizado em todos os lugares.",
"Choose as profile picture" : "Escolha como imagem de perfil",
"You are a member of the following groups:" : "Você é membro dos seguintes grupos:",
"You are using <strong>%s</strong>" : "Você está usando <strong>%s</strong>",
diff --git a/apps/settings/l10n/pt_BR.json b/apps/settings/l10n/pt_BR.json
index 182679fee3b..572c97e7184 100644
--- a/apps/settings/l10n/pt_BR.json
+++ b/apps/settings/l10n/pt_BR.json
@@ -70,6 +70,7 @@
"If you received this email, the email configuration seems to be correct." : "Se você recebeu este e-mail, é sinal que a configuração do servidor de e-mail está correta.",
"Email could not be sent. Check your mail server log" : "O e-mail não pôde ser enviado. Verifique o log do servidor de e-mail",
"A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Ocorreu um problema ao enviar o e-mail. Por favor, revise suas configurações. (Erro: %s)",
+ "You need to set your user email before being able to send test emails. Go to %s for that." : "Você precisa definir seu e-mail de usuário antes de poder enviar e-mails de teste. Vá a %s para isso.",
"Invalid user" : "Usuário inválido",
"Invalid mail address" : "Endereço de e-mail inválido",
"Settings saved" : "Configurações salvas",
@@ -124,6 +125,7 @@
"Verifying" : "Verificando",
"A background job is pending that checks for user imported SSL certificates. Please check back later." : "Um trabalho em segundo plano está pendente que verifica se há certificados SSL importados pelo usuário. Por favor, volte mais tarde.",
"There are some user imported SSL certificates present, that are not used anymore with Nextcloud 21. They can be imported on the command line via \"occ security:certificates:import\" command. Their paths inside the data directory are shown below." : "Existem alguns certificados SSL importados pelo usuário presentes, que não são mais usados com o Nextcloud 21. Eles podem ser importados na linha de comando através do comando \"occ security:certificates:import\". Seus caminhos dentro do diretório de dados são mostrados abaixo.",
+ "Invalid UUIDs of LDAP users or groups have been found. Please review your \"Override UUID detection\" settings in the Expert part of the LDAP configuration and use \"occ ldap:update-uuid\" to update them." : "UUIDs inválidos de usuários ou grupos LDAP foram encontrados. Revise suas configurações de \"Substituir detecção de UUID\" na parte Expert da configuração LDAP e use \"occ ldap:update-uuid\" para atualizá-las.",
"The old server-side-encryption format is enabled. We recommend disabling this." : "O antigo formato de criptografia do lado do servidor está ativado. Recomendamos desativar isso.",
"MariaDB version \"%s\" is used. Nextcloud 21 will no longer support this version and requires MariaDB 10.2 or higher." : "Está em uso o MariaDB versão \"%s\". O Nextcloud 21 terá mais suporte para essa versão e requer MariaDB 10.2 ou posterior.",
"MySQL version \"%s\" is used. Nextcloud 21 will no longer support this version and requires MySQL 8.0 or MariaDB 10.2 or higher." : "Está sendo usado a versão \"%s\" do MySQL. O Nextcloud 21 não suportará mais esta versão e irá requerer MySQL 8.0 ou MariaDB 10.2 ou superior. ",
@@ -164,6 +166,7 @@
"Featured" : "Destaques",
"Update to {update}" : "Atualizar para {update}",
"Update all" : "Atualizar todos",
+ "All apps are up-to-date." : "Todos os aplicativos estão atualizados.",
"Results from other categories" : "Resultados de outras categorias",
"No apps found for your version" : "Nenhum aplicativo encontrado para a sua versão",
"Disable all" : "Desativar tudo",
@@ -214,6 +217,7 @@
"Could not copy app password. Please copy it manually." : "Não foi possível copiar a senha do aplicativo. Copie-a manualmente.",
"Profile" : "Perfil",
"Enable" : "Ativar",
+ "Rename group" : "Renomear grupo",
"Remove group" : "Excluir grupo",
"You are about to remove the group {group}. The users will NOT be deleted." : "Você está prestes a remover o grupo {group}. Os usuários NÃO serão apagados.",
"Please confirm the group removal " : "Confirme a remoção do grupo",
@@ -383,6 +387,7 @@
"SMTP Username" : "Nome do Usuário SMTP",
"SMTP Password" : "Senha SMTP",
"Save" : "Salvar",
+ "Test and verify email settings" : "Testar e verificar as configurações de e-mail",
"Send email" : "Enviar e-mail",
"It's important for the security and performance of your instance that everything is configured correctly. To help you with that we are doing some automatic checks. Please see the linked documentation for more information." : "Para segurança e desempenho da sua instalação é importante que tudo esteja configurado corretamente. Para ajudá-lo com isso, estamos fazendo algumas verificações automáticas. Consulte a documentação para mais informações.",
"All checks passed." : "Todas as verificações passaram.",
@@ -462,6 +467,7 @@
"Remove image" : "Remover imagem",
"png or jpg, max. 20 MB" : "png ou jpg, max. 20 MB",
"Picture provided by original account" : "Imagem fornecida pela conta original",
+ "Please note that it can take up to 24 hours for the avatar to get updated everywhere." : "Observe que pode levar até 24 horas para que o avatar seja atualizado em todos os lugares.",
"Choose as profile picture" : "Escolha como imagem de perfil",
"You are a member of the following groups:" : "Você é membro dos seguintes grupos:",
"You are using <strong>%s</strong>" : "Você está usando <strong>%s</strong>",
diff --git a/apps/settings/lib/Settings/Admin/Sharing.php b/apps/settings/lib/Settings/Admin/Sharing.php
index 15f74c40e1e..a5f85003fa4 100644
--- a/apps/settings/lib/Settings/Admin/Sharing.php
+++ b/apps/settings/lib/Settings/Admin/Sharing.php
@@ -72,6 +72,11 @@ class Sharing implements IDelegatedSettings {
$linksExcludeGroupsList = !is_null(json_decode($linksExcludedGroups))
? implode('|', json_decode($linksExcludedGroups, true)) : '';
+ $excludedPasswordGroups = $this->config->getAppValue('core', 'shareapi_enforce_links_password_excluded_groups', '');
+ $excludedPasswordGroupsList = !is_null(json_decode($excludedPasswordGroups))
+ ? implode('|', json_decode($excludedPasswordGroups, true)) : '';
+
+
$parameters = [
// Built-In Sharing
'sharingAppEnabled' => $this->appManager->isEnabledForUser('files_sharing'),
@@ -84,7 +89,9 @@ class Sharing implements IDelegatedSettings {
'restrictUserEnumerationToGroup' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no'),
'restrictUserEnumerationToPhone' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no'),
'restrictUserEnumerationFullMatch' => $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes'),
- 'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(),
+ 'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(false),
+ 'passwordExcludedGroups' => $excludedPasswordGroupsList,
+ 'passwordExcludedGroupsFeatureEnabled' => $this->config->getSystemValueBool('sharing.allow_disabled_password_enforcement_groups', false),
'onlyShareWithGroupMembers' => $this->shareManager->shareWithGroupMembersOnly(),
'shareAPIEnabled' => $this->config->getAppValue('core', 'shareapi_enabled', 'yes'),
'shareDefaultExpireDateSet' => $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no'),
diff --git a/apps/settings/src/admin.js b/apps/settings/src/admin.js
index 2a8c6bb1d0c..c3704eed42c 100644
--- a/apps/settings/src/admin.js
+++ b/apps/settings/src/admin.js
@@ -1,5 +1,5 @@
window.addEventListener('DOMContentLoaded', () => {
- $('#excludedGroups,#linksExcludedGroups').each((index, element) => {
+ $('#excludedGroups,#linksExcludedGroups,#passwordsExcludedGroups').each(function(index, element) {
OC.Settings.setupGroupsSelect($(element))
$(element).change((ev) => {
let groups = ev.val || []
@@ -93,6 +93,10 @@ window.addEventListener('DOMContentLoaded', () => {
$('#setDefaultRemoteExpireDate').toggleClass('hidden', !this.checked)
})
+ $('#enforceLinkPassword').change(function() {
+ $('#selectPasswordsExcludedGroups').toggleClass('hidden', !this.checked)
+ })
+
$('#publicShareDisclaimer').change(function() {
$('#publicShareDisclaimerText').toggleClass('hidden', !this.checked)
if (!this.checked) {
diff --git a/apps/settings/templates/settings/admin/additional-mail.php b/apps/settings/templates/settings/admin/additional-mail.php
index a7e8382de18..6b85fcbe867 100644
--- a/apps/settings/templates/settings/admin/additional-mail.php
+++ b/apps/settings/templates/settings/admin/additional-mail.php
@@ -140,7 +140,7 @@ $mail_sendmailmode = [
<input type="text" name="mail_smtphost" id="mail_smtphost" placeholder="smtp.example.com"
value="<?php p($_['mail_smtphost']) ?>" />
:
- <input type="text" name="mail_smtpport" id="mail_smtpport" placeholder="<?php p($l->t('Port'))?>"
+ <input type="text" inputmode="numeric" name="mail_smtpport" id="mail_smtpport" placeholder="<?php p($l->t('Port'))?>"
value="<?php p($_['mail_smtpport']) ?>" />
</p>
</form>
diff --git a/apps/settings/templates/settings/admin/sharing.php b/apps/settings/templates/settings/admin/sharing.php
index b699e152198..b51f9339166 100644
--- a/apps/settings/templates/settings/admin/sharing.php
+++ b/apps/settings/templates/settings/admin/sharing.php
@@ -120,6 +120,18 @@
} ?> />
<label for="enforceLinkPassword"><?php p($l->t('Enforce password protection'));?></label><br/>
+<?php if ($_['passwordExcludedGroupsFeatureEnabled']) { ?>
+ <div id="selectPasswordsExcludedGroups" class="indent <?php if (!$_['enforceLinkPassword']) { p('hidden'); } ?>">
+ <div class="indent">
+ <label for="shareapi_enforce_links_password_excluded_groups"><?php p($l->t('Exclude groups from password requirements:'));?>
+ <br />
+ <input name="shareapi_enforce_links_password_excluded_groups" id="passwordsExcludedGroups" value="<?php p($_['passwordExcludedGroups']) ?>" style="width: 400px" class="noJSAutoUpdate"/>
+ </div>
+ </div>
+<?php } ?>
+
+ <input type="checkbox" name="shareapi_default_expire_date" id="shareapiDefaultExpireDate" class="checkbox" value="1" <?php if ($_['shareDefaultExpireDateSet'] === 'yes') { print_unescaped('checked="checked"'); } ?> />
+
<input type="checkbox" name="shareapi_default_expire_date" id="shareapiDefaultExpireDate" class="checkbox"
value="1" <?php if ($_['shareDefaultExpireDateSet'] === 'yes') {
print_unescaped('checked="checked"');
diff --git a/apps/settings/tests/Settings/Admin/SharingTest.php b/apps/settings/tests/Settings/Admin/SharingTest.php
index 222be5fd9dc..3ac2e878434 100644
--- a/apps/settings/tests/Settings/Admin/SharingTest.php
+++ b/apps/settings/tests/Settings/Admin/SharingTest.php
@@ -135,6 +135,8 @@ class SharingTest extends TestCase {
'shareRemoteExpireAfterNDays' => '7',
'shareRemoteEnforceExpireDate' => 'no',
'allowLinksExcludeGroups' => '',
+ 'passwordExcludedGroups' => '',
+ 'passwordExcludedGroupsFeatureEnabled' => false,
],
''
);
@@ -208,6 +210,8 @@ class SharingTest extends TestCase {
'shareRemoteExpireAfterNDays' => '7',
'shareRemoteEnforceExpireDate' => 'no',
'allowLinksExcludeGroups' => '',
+ 'passwordExcludedGroups' => '',
+ 'passwordExcludedGroupsFeatureEnabled' => false,
],
''
);
diff --git a/apps/settings/tests/UserMigration/AccountMigratorTest.php b/apps/settings/tests/UserMigration/AccountMigratorTest.php
new file mode 100644
index 00000000000..c668bb9e6af
--- /dev/null
+++ b/apps/settings/tests/UserMigration/AccountMigratorTest.php
@@ -0,0 +1,120 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @copyright 2022 Christopher Ng <chrng8@gmail.com>
+ *
+ * @author Christopher Ng <chrng8@gmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Settings\Tests\UserMigration;
+
+use OCA\Settings\AppInfo\Application;
+use OCA\Settings\UserMigration\AccountMigrator;
+use OCP\Accounts\IAccountManager;
+use OCP\AppFramework\App;
+use OCP\IUserManager;
+use OCP\UserMigration\IExportDestination;
+use OCP\UserMigration\IImportSource;
+use PHPUnit\Framework\MockObject\MockObject;
+use Sabre\VObject\UUIDUtil;
+use Symfony\Component\Console\Output\OutputInterface;
+use Test\TestCase;
+
+/**
+ * @group DB
+ */
+class AccountMigratorTest extends TestCase {
+
+ private IUserManager $userManager;
+
+ private AccountMigrator $migrator;
+
+ /** @var IImportSource|MockObject */
+ private $importSource;
+
+ /** @var IExportDestination|MockObject */
+ private $exportDestination;
+
+ /** @var OutputInterface|MockObject */
+ private $output;
+
+ private const ASSETS_DIR = __DIR__ . '/assets/';
+
+ private const REGEX_ACCOUNT_FILE = '/' . Application::APP_ID . '\/' . '[a-z]+\.json' . '/';
+
+ protected function setUp(): void {
+ $app = new App(Application::APP_ID);
+ $container = $app->getContainer();
+
+ $this->userManager = $container->get(IUserManager::class);
+ $this->migrator = $container->get(AccountMigrator::class);
+
+ $this->importSource = $this->createMock(IImportSource::class);
+ $this->exportDestination = $this->createMock(IExportDestination::class);
+ $this->output = $this->createMock(OutputInterface::class);
+ }
+
+ public function dataImportExportAccount(): array {
+ return array_map(
+ fn (string $filename) => [
+ UUIDUtil::getUUID(),
+ json_decode(file_get_contents(self::ASSETS_DIR . $filename), true, 512, JSON_THROW_ON_ERROR),
+ ],
+ array_diff(
+ scandir(self::ASSETS_DIR),
+ // Exclude current and parent directories
+ ['.', '..'],
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider dataImportExportAccount
+ */
+ public function testImportExportAccount(string $userId, array $importData): void {
+ $user = $this->userManager->createUser($userId, 'topsecretpassword');
+ $exportData = $importData;
+ // Verification status of email will be set to in progress on import so we set the export data to reflect that
+ $exportData[IAccountManager::PROPERTY_EMAIL]['verified'] = IAccountManager::VERIFICATION_IN_PROGRESS;
+
+ $this->importSource
+ ->expects($this->once())
+ ->method('getMigratorVersion')
+ ->with(AccountMigrator::class)
+ ->willReturn(1);
+
+ $this->importSource
+ ->expects($this->once())
+ ->method('getFileContents')
+ ->with($this->matchesRegularExpression(self::REGEX_ACCOUNT_FILE))
+ ->willReturn(json_encode($importData));
+
+ $this->migrator->import($user, $this->importSource, $this->output);
+
+ $this->exportDestination
+ ->expects($this->once())
+ ->method('addFileContents')
+ ->with($this->matchesRegularExpression(self::REGEX_ACCOUNT_FILE), json_encode($exportData))
+ ->willReturn(true);
+
+ $this->migrator->export($user, $this->exportDestination, $this->output);
+ }
+}
diff --git a/apps/settings/tests/UserMigration/assets/account-complex.json b/apps/settings/tests/UserMigration/assets/account-complex.json
new file mode 100644
index 00000000000..4199b13b704
--- /dev/null
+++ b/apps/settings/tests/UserMigration/assets/account-complex.json
@@ -0,0 +1 @@
+{"displayname":{"name":"displayname","value":"Steve Smith","scope":"v2-local","verified":"0","verificationData":""},"address":{"name":"address","value":"123 Water St","scope":"v2-local","verified":"0","verificationData":""},"website":{"name":"website","value":"https:\/\/example.org","scope":"v2-local","verified":"0","verificationData":""},"email":{"name":"email","value":"steve@example.org","scope":"v2-federated","verified":"0","verificationData":""},"avatar":{"name":"avatar","value":"","scope":"v2-local","verified":"0","verificationData":""},"phone":{"name":"phone","value":"+12178515387","scope":"v2-private","verified":"0","verificationData":""},"twitter":{"name":"twitter","value":"steve","scope":"v2-federated","verified":"0","verificationData":""},"organisation":{"name":"organisation","value":"Mytery Machine","scope":"v2-private","verified":"0","verificationData":""},"role":{"name":"role","value":"Manager","scope":"v2-private","verified":"0","verificationData":""},"headline":{"name":"headline","value":"I am Steve","scope":"v2-local","verified":"0","verificationData":""},"biography":{"name":"biography","value":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris porttitor ullamcorper dictum. Sed fermentum ut ligula scelerisque semper. Aliquam interdum convallis tellus eu dapibus. Integer in justo sollicitudin, hendrerit ligula sit amet, blandit sem.\n\nSuspendisse consectetur ultrices accumsan. Quisque sagittis bibendum lectus ut placerat. Mauris tincidunt ornare neque, et pulvinar tortor porttitor eu.","scope":"v2-local","verified":"0","verificationData":""},"profile_enabled":{"name":"profile_enabled","value":"1","scope":"v2-local","verified":"0","verificationData":""},"additional_mail":[{"name":"additional_mail","value":"steve@example.com","scope":"v2-published","verified":"0","verificationData":""},{"name":"additional_mail","value":"steve@earth.world","scope":"v2-local","verified":"0","verificationData":""}]} \ No newline at end of file
diff --git a/apps/settings/tests/UserMigration/assets/account.json b/apps/settings/tests/UserMigration/assets/account.json
new file mode 100644
index 00000000000..7f53f28c4d3
--- /dev/null
+++ b/apps/settings/tests/UserMigration/assets/account.json
@@ -0,0 +1 @@
+{"displayname":{"name":"displayname","value":"Emma Jones","scope":"v2-federated","verified":"0","verificationData":""},"address":{"name":"address","value":"920 Grass St","scope":"v2-local","verified":"0","verificationData":""},"website":{"name":"website","value":"","scope":"v2-local","verified":"0","verificationData":""},"email":{"name":"email","value":"","scope":"v2-federated","verified":"0","verificationData":""},"avatar":{"name":"avatar","value":"","scope":"v2-federated","verified":"0","verificationData":""},"phone":{"name":"phone","value":"","scope":"v2-local","verified":"0","verificationData":""},"twitter":{"name":"twitter","value":"","scope":"v2-local","verified":"0","verificationData":""},"organisation":{"name":"organisation","value":"","scope":"v2-local","verified":"0","verificationData":""},"role":{"name":"role","value":"","scope":"v2-local","verified":"0","verificationData":""},"headline":{"name":"headline","value":"","scope":"v2-local","verified":"0","verificationData":""},"biography":{"name":"biography","value":"","scope":"v2-local","verified":"0","verificationData":""},"profile_enabled":{"name":"profile_enabled","value":"1","scope":"v2-local","verified":"0","verificationData":""},"additional_mail":[]} \ No newline at end of file
diff --git a/apps/systemtags/l10n/hu.js b/apps/systemtags/l10n/hu.js
index fdcf2649cb7..a69c72bae7c 100644
--- a/apps/systemtags/l10n/hu.js
+++ b/apps/systemtags/l10n/hu.js
@@ -4,54 +4,54 @@ OC.L10N.register(
"Tag name is empty" : "A címke neve üres",
"Update" : "Frissítés",
"Create" : "Létrehozás",
- "Select tag …" : "Címke választás...",
+ "Select tag …" : "Válasszon címkét…",
"System tag %1$s added by the system" : "A rendszer hozzáadta a(z) %1$s rendszercímkét",
- "Added system tag {systemtag}" : "{systemtag} rendszer címke hozzáadva",
- "Added system tag %1$s" : "%1$s rendszer címke eltávolítva",
- "%1$s added system tag %2$s" : "%1$s hozzáadta a ezt a rendszer címkét: %2$s",
- "{actor} added system tag {systemtag}" : "{actor} hozzáadta a ezt a rendszer címkét: {systemtag}",
+ "Added system tag {systemtag}" : "{systemtag} rendszercímke hozzáadva",
+ "Added system tag %1$s" : "%1$s rendszercímke hozzáadva",
+ "%1$s added system tag %2$s" : "%1$s hozzáadta a(z) %2$s rendszercímkét",
+ "{actor} added system tag {systemtag}" : "{actor} hozzáadta a(z) {systemtag} rendszercímkét",
"System tag %1$s removed by the system" : "A rendszer eltávolította a(z) %1$s rendszercímkét",
- "Removed system tag {systemtag}" : "{systemtag} rendszer címke eltávolítva",
- "Removed system tag %1$s" : "%1$s rendszer címke eltávolítva",
- "%1$s removed system tag %2$s" : "%1$s eltávolította ezt a rendszer címkét: %2$s",
- "{actor} removed system tag {systemtag}" : "{actor} eltávolította ezt a rendszer címkét: {systemtag}",
- "You created system tag %1$s" : "Létrehoztad ezt a rendszer címkét: %1$s",
- "You created system tag {systemtag}" : "Létrehoztad ezt a rendszer címkét: {systemtag}",
+ "Removed system tag {systemtag}" : "{systemtag} rendszercímke eltávolítva",
+ "Removed system tag %1$s" : "%1$s rendszercímke eltávolítva",
+ "%1$s removed system tag %2$s" : "%1$s eltávolította a(z) %2$s rendszercímkét",
+ "{actor} removed system tag {systemtag}" : "{actor} eltávolította a(z) {systemtag} rendszercímkét",
+ "You created system tag %1$s" : "Létrehozta a(z) %1$s rendszercímkét",
+ "You created system tag {systemtag}" : "Létrehozta a(z) {systemtag} rendszercímkét",
"%1$s created system tag %2$s" : "%1$s létrehozta ezt a rendszer címkét: %2$s",
- "{actor} created system tag {systemtag}" : "{actor} létrehozta ezt a rendszer címkét: {systemtag}",
- "You deleted system tag %1$s" : "Törölted ezt a rendszer címkét: %1$s",
- "You deleted system tag {systemtag}" : "Törölted ezt a rendszer címkét: {systemtag}",
- "%1$s deleted system tag %2$s" : "%1$s törölte ezt a rendszer címkét: %2$s",
- "{actor} deleted system tag {systemtag}" : "{actor} törölte ezt a rendszer címkét: {systemtag}",
- "You updated system tag %2$s to %1$s" : "%2$s rendszer címke frissítve erre: %1$s",
- "You updated system tag {oldsystemtag} to {newsystemtag}" : "{oldsystemtag} rendszer címke frissítve erre: {newsystemtag}",
- "%1$s updated system tag %3$s to %2$s" : "%1$s frissítette ezt a rendszer címkét erről: %3$s erre: %2$s",
- "{actor} updated system tag {oldsystemtag} to {newsystemtag}" : "{actor} frissítette ezt a rendszer címkét: {oldsystemtag} erre: {newsystemtag}",
- "System tag %2$s was added to %1$s by the system" : "A rendszer hozzáadta a(z) %2$s rendszercímkét a következőhöz: %1$s",
+ "{actor} created system tag {systemtag}" : "{actor} létrehozta a(z) {systemtag} rendszercímkét",
+ "You deleted system tag %1$s" : "Törölte a(z) %1$s rendszercímkét",
+ "You deleted system tag {systemtag}" : "Törölte a(z) {systemtag} rendszercímkét",
+ "%1$s deleted system tag %2$s" : "%1$s törölte a(z) %2$s rendszercímkét",
+ "{actor} deleted system tag {systemtag}" : "{actor} törölte a(z) {systemtag} rendszercímkét",
+ "You updated system tag %2$s to %1$s" : "Frissítette a(z) %2$s rendszercímkét a következőre: %1$s",
+ "You updated system tag {oldsystemtag} to {newsystemtag}" : "Frissítette a(z) {oldsystemtag} rendszercímkét a következőre: {newsystemtag}",
+ "%1$s updated system tag %3$s to %2$s" : "%1$s erre frissítette a(z) %3$s rendszercímkét: %2$s",
+ "{actor} updated system tag {oldsystemtag} to {newsystemtag}" : "{actor} erre frissítette a(z) {oldsystemtag} rendszercímkét: {newsystemtag}",
+ "System tag %2$s was added to %1$s by the system" : "A rendszer hozzáadta a(z) %2$s rendszercímkét a(z) %1$s fájlhoz",
"System tag {systemtag} was added to {file} by the system" : "A rendszer hozzáadta a(z) {systemtag} rendszercímkét a(z) {file} fájlhoz",
- "You added system tag %2$s to %1$s" : "Hozzáadtad ezt a rendszer címkét: %2$s ehhez: %1$s",
- "You added system tag {systemtag} to {file}" : "Hozzáadtad ezt a rendszer címkét: {systemtag} ehhez: {file}",
- "%1$s added system tag %3$s to %2$s" : "%1$s hozzáadta ezt a rendszer címkét: %3$s ehhez: %2$s",
- "{actor} added system tag {systemtag} to {file}" : "{actor} hozzáadta ezt a rendszer címkét: {systemtag} ehhez: {file}",
- "System tag %2$s was removed from %1$s by the system" : "A rendszer eltávolította a(z) %2$s rendszercímkét a(z) %1$s fájlból",
- "System tag {systemtag} was removed from {file} by the system" : "A rendszer eltávolította a(z) {systemtag} rendszercímkét a(z) {file} fájlból",
- "You removed system tag %2$s from %1$s" : "Eltávolítottad ezt a rendszer címkét: %2$s innen: %1$s",
- "You removed system tag {systemtag} from {file}" : "Eltávolítottad ezt a rendszer címkét: {systemtag} innen: {file}",
- "%1$s removed system tag %3$s from %2$s" : "%1$s eltávolította ezt a rendszer címkét: %3$s innen: %2$s",
- "{actor} removed system tag {systemtag} from {file}" : "{actor} eltávolította ezt a rendszer címkét: {systemtag} innen: {file}",
+ "You added system tag %2$s to %1$s" : "Hozzáadta a(z) %2$s rendszercímkét a(z) %1$s fájlhoz",
+ "You added system tag {systemtag} to {file}" : "Hozzáadta a(z) {systemtag} rendszercímkét a(z) {file} fájlhoz",
+ "%1$s added system tag %3$s to %2$s" : "%1$s hozzáadta a(z) %3$s rendszercímkét a(z) %2$s fájlhoz",
+ "{actor} added system tag {systemtag} to {file}" : "{actor} hozzáadta a(z) {systemtag} rendszercímkét a(z) {file} fájlhoz",
+ "System tag %2$s was removed from %1$s by the system" : "A rendszer eltávolította a(z) %2$s rendszercímkét a(z) %1$s fájlról",
+ "System tag {systemtag} was removed from {file} by the system" : "A rendszer eltávolította a(z) {systemtag} rendszercímkét a(z) {file} fájlról",
+ "You removed system tag %2$s from %1$s" : "Eltávolította a(z) %2$s rendszercímkét a(z) %1$s fájlról",
+ "You removed system tag {systemtag} from {file}" : "Eltávolította a(z) {systemtag} rendszercímkét a(z) {file} fájlról",
+ "%1$s removed system tag %3$s from %2$s" : "%1$s eltávolította a(z) %3$s rendszercímkét a(z) %2$s fájlról",
+ "{actor} removed system tag {systemtag} from {file}" : "{actor} eltávolította a(z) {systemtag} rendszercímkét a(z) {file} fájlról",
"%s (restricted)" : "%s (korlátozott)",
"%s (invisible)" : "%s (láthatatlan)",
- "<strong>System tags</strong> for a file have been modified" : "A fájl <strong>rendszer címkéje</strong> módosítva lett",
+ "<strong>System tags</strong> for a file have been modified" : "A fájl <strong>rendszercímkéi</strong> módosítva lettek",
"Tags" : "Címkék",
"Collaborative tags" : "Együttműködési címkék",
"Collaborative tagging functionality which shares tags among users." : "Együttműködő címkézési funkció, amely megosztja a címkéket a felhasználók között.",
"Collaborative tagging functionality which shares tags among users. Great for teams.\n\t(If you are a provider with a multi-tenancy installation, it is advised to deactivate this app as tags are shared.)" : "Együttműködő címkézési funkció, amely megosztja a címkéket a felhasználók között. Nagyszerű a csapatok számára.\n\t(Ha Ön több szervezet számára szolgáltatást nyújtó szolgáltató, akkor ajánlott deaktiválni ezt az alkalmazást, mivel a címkék meg vannak osztva.)",
"Tagged files" : "Címkézett fájlok",
- "Select tags to filter by" : "Kiválasztott címkék a szűrő által:",
+ "Select tags to filter by" : "Válasszon címkéket a szűréshez:",
"No tags found" : "Nem találhatók címkék",
- "Please select tags to filter by" : "Kéjük, válasszon ki címkét a szűréshez:",
- "No files found for the selected tags" : "Nem található fájl a kiválasztott címkéhez.",
- "Collaborative tags are available for all users. Restricted tags are visible to users but cannot be assigned by them. Invisible tags are for internal use, since users cannot see or assign them." : "A közreműködő címkék elérhetőek az összes felhasználó számára. A korlátozott címkék láthatóak a felhasználók által de nem rendelhetik azt semmihez. A láthatatlan címkék belső használatra vannak fenntartva, mivel a felhasználók nem látják ezeket és nem is tudják semmihez hozzárendelni őket.",
+ "Please select tags to filter by" : "Válasszon címkéket a szűréshez:",
+ "No files found for the selected tags" : "Nem található fájl a kiválasztott címkéhez",
+ "Collaborative tags are available for all users. Restricted tags are visible to users but cannot be assigned by them. Invisible tags are for internal use, since users cannot see or assign them." : "Az együttműködési címkék elérhetők az összes felhasználó számára. A korlátozott címkék láthatók a felhasználók által, de nem rendelhetik azt semmihez. A láthatatlan címkék belső használatra vannak fenntartva, mivel a felhasználók nem látják ezeket, és nem is tudják semmihez hozzárendelni őket.",
"Create a new tag" : "Új címke létrehozása",
"Name" : "Név",
"Public" : "Nyilvános",
diff --git a/apps/systemtags/l10n/hu.json b/apps/systemtags/l10n/hu.json
index b8a9f8dbfb7..65cbbcb77db 100644
--- a/apps/systemtags/l10n/hu.json
+++ b/apps/systemtags/l10n/hu.json
@@ -2,54 +2,54 @@
"Tag name is empty" : "A címke neve üres",
"Update" : "Frissítés",
"Create" : "Létrehozás",
- "Select tag …" : "Címke választás...",
+ "Select tag …" : "Válasszon címkét…",
"System tag %1$s added by the system" : "A rendszer hozzáadta a(z) %1$s rendszercímkét",
- "Added system tag {systemtag}" : "{systemtag} rendszer címke hozzáadva",
- "Added system tag %1$s" : "%1$s rendszer címke eltávolítva",
- "%1$s added system tag %2$s" : "%1$s hozzáadta a ezt a rendszer címkét: %2$s",
- "{actor} added system tag {systemtag}" : "{actor} hozzáadta a ezt a rendszer címkét: {systemtag}",
+ "Added system tag {systemtag}" : "{systemtag} rendszercímke hozzáadva",
+ "Added system tag %1$s" : "%1$s rendszercímke hozzáadva",
+ "%1$s added system tag %2$s" : "%1$s hozzáadta a(z) %2$s rendszercímkét",
+ "{actor} added system tag {systemtag}" : "{actor} hozzáadta a(z) {systemtag} rendszercímkét",
"System tag %1$s removed by the system" : "A rendszer eltávolította a(z) %1$s rendszercímkét",
- "Removed system tag {systemtag}" : "{systemtag} rendszer címke eltávolítva",
- "Removed system tag %1$s" : "%1$s rendszer címke eltávolítva",
- "%1$s removed system tag %2$s" : "%1$s eltávolította ezt a rendszer címkét: %2$s",
- "{actor} removed system tag {systemtag}" : "{actor} eltávolította ezt a rendszer címkét: {systemtag}",
- "You created system tag %1$s" : "Létrehoztad ezt a rendszer címkét: %1$s",
- "You created system tag {systemtag}" : "Létrehoztad ezt a rendszer címkét: {systemtag}",
+ "Removed system tag {systemtag}" : "{systemtag} rendszercímke eltávolítva",
+ "Removed system tag %1$s" : "%1$s rendszercímke eltávolítva",
+ "%1$s removed system tag %2$s" : "%1$s eltávolította a(z) %2$s rendszercímkét",
+ "{actor} removed system tag {systemtag}" : "{actor} eltávolította a(z) {systemtag} rendszercímkét",
+ "You created system tag %1$s" : "Létrehozta a(z) %1$s rendszercímkét",
+ "You created system tag {systemtag}" : "Létrehozta a(z) {systemtag} rendszercímkét",
"%1$s created system tag %2$s" : "%1$s létrehozta ezt a rendszer címkét: %2$s",
- "{actor} created system tag {systemtag}" : "{actor} létrehozta ezt a rendszer címkét: {systemtag}",
- "You deleted system tag %1$s" : "Törölted ezt a rendszer címkét: %1$s",
- "You deleted system tag {systemtag}" : "Törölted ezt a rendszer címkét: {systemtag}",
- "%1$s deleted system tag %2$s" : "%1$s törölte ezt a rendszer címkét: %2$s",
- "{actor} deleted system tag {systemtag}" : "{actor} törölte ezt a rendszer címkét: {systemtag}",
- "You updated system tag %2$s to %1$s" : "%2$s rendszer címke frissítve erre: %1$s",
- "You updated system tag {oldsystemtag} to {newsystemtag}" : "{oldsystemtag} rendszer címke frissítve erre: {newsystemtag}",
- "%1$s updated system tag %3$s to %2$s" : "%1$s frissítette ezt a rendszer címkét erről: %3$s erre: %2$s",
- "{actor} updated system tag {oldsystemtag} to {newsystemtag}" : "{actor} frissítette ezt a rendszer címkét: {oldsystemtag} erre: {newsystemtag}",
- "System tag %2$s was added to %1$s by the system" : "A rendszer hozzáadta a(z) %2$s rendszercímkét a következőhöz: %1$s",
+ "{actor} created system tag {systemtag}" : "{actor} létrehozta a(z) {systemtag} rendszercímkét",
+ "You deleted system tag %1$s" : "Törölte a(z) %1$s rendszercímkét",
+ "You deleted system tag {systemtag}" : "Törölte a(z) {systemtag} rendszercímkét",
+ "%1$s deleted system tag %2$s" : "%1$s törölte a(z) %2$s rendszercímkét",
+ "{actor} deleted system tag {systemtag}" : "{actor} törölte a(z) {systemtag} rendszercímkét",
+ "You updated system tag %2$s to %1$s" : "Frissítette a(z) %2$s rendszercímkét a következőre: %1$s",
+ "You updated system tag {oldsystemtag} to {newsystemtag}" : "Frissítette a(z) {oldsystemtag} rendszercímkét a következőre: {newsystemtag}",
+ "%1$s updated system tag %3$s to %2$s" : "%1$s erre frissítette a(z) %3$s rendszercímkét: %2$s",
+ "{actor} updated system tag {oldsystemtag} to {newsystemtag}" : "{actor} erre frissítette a(z) {oldsystemtag} rendszercímkét: {newsystemtag}",
+ "System tag %2$s was added to %1$s by the system" : "A rendszer hozzáadta a(z) %2$s rendszercímkét a(z) %1$s fájlhoz",
"System tag {systemtag} was added to {file} by the system" : "A rendszer hozzáadta a(z) {systemtag} rendszercímkét a(z) {file} fájlhoz",
- "You added system tag %2$s to %1$s" : "Hozzáadtad ezt a rendszer címkét: %2$s ehhez: %1$s",
- "You added system tag {systemtag} to {file}" : "Hozzáadtad ezt a rendszer címkét: {systemtag} ehhez: {file}",
- "%1$s added system tag %3$s to %2$s" : "%1$s hozzáadta ezt a rendszer címkét: %3$s ehhez: %2$s",
- "{actor} added system tag {systemtag} to {file}" : "{actor} hozzáadta ezt a rendszer címkét: {systemtag} ehhez: {file}",
- "System tag %2$s was removed from %1$s by the system" : "A rendszer eltávolította a(z) %2$s rendszercímkét a(z) %1$s fájlból",
- "System tag {systemtag} was removed from {file} by the system" : "A rendszer eltávolította a(z) {systemtag} rendszercímkét a(z) {file} fájlból",
- "You removed system tag %2$s from %1$s" : "Eltávolítottad ezt a rendszer címkét: %2$s innen: %1$s",
- "You removed system tag {systemtag} from {file}" : "Eltávolítottad ezt a rendszer címkét: {systemtag} innen: {file}",
- "%1$s removed system tag %3$s from %2$s" : "%1$s eltávolította ezt a rendszer címkét: %3$s innen: %2$s",
- "{actor} removed system tag {systemtag} from {file}" : "{actor} eltávolította ezt a rendszer címkét: {systemtag} innen: {file}",
+ "You added system tag %2$s to %1$s" : "Hozzáadta a(z) %2$s rendszercímkét a(z) %1$s fájlhoz",
+ "You added system tag {systemtag} to {file}" : "Hozzáadta a(z) {systemtag} rendszercímkét a(z) {file} fájlhoz",
+ "%1$s added system tag %3$s to %2$s" : "%1$s hozzáadta a(z) %3$s rendszercímkét a(z) %2$s fájlhoz",
+ "{actor} added system tag {systemtag} to {file}" : "{actor} hozzáadta a(z) {systemtag} rendszercímkét a(z) {file} fájlhoz",
+ "System tag %2$s was removed from %1$s by the system" : "A rendszer eltávolította a(z) %2$s rendszercímkét a(z) %1$s fájlról",
+ "System tag {systemtag} was removed from {file} by the system" : "A rendszer eltávolította a(z) {systemtag} rendszercímkét a(z) {file} fájlról",
+ "You removed system tag %2$s from %1$s" : "Eltávolította a(z) %2$s rendszercímkét a(z) %1$s fájlról",
+ "You removed system tag {systemtag} from {file}" : "Eltávolította a(z) {systemtag} rendszercímkét a(z) {file} fájlról",
+ "%1$s removed system tag %3$s from %2$s" : "%1$s eltávolította a(z) %3$s rendszercímkét a(z) %2$s fájlról",
+ "{actor} removed system tag {systemtag} from {file}" : "{actor} eltávolította a(z) {systemtag} rendszercímkét a(z) {file} fájlról",
"%s (restricted)" : "%s (korlátozott)",
"%s (invisible)" : "%s (láthatatlan)",
- "<strong>System tags</strong> for a file have been modified" : "A fájl <strong>rendszer címkéje</strong> módosítva lett",
+ "<strong>System tags</strong> for a file have been modified" : "A fájl <strong>rendszercímkéi</strong> módosítva lettek",
"Tags" : "Címkék",
"Collaborative tags" : "Együttműködési címkék",
"Collaborative tagging functionality which shares tags among users." : "Együttműködő címkézési funkció, amely megosztja a címkéket a felhasználók között.",
"Collaborative tagging functionality which shares tags among users. Great for teams.\n\t(If you are a provider with a multi-tenancy installation, it is advised to deactivate this app as tags are shared.)" : "Együttműködő címkézési funkció, amely megosztja a címkéket a felhasználók között. Nagyszerű a csapatok számára.\n\t(Ha Ön több szervezet számára szolgáltatást nyújtó szolgáltató, akkor ajánlott deaktiválni ezt az alkalmazást, mivel a címkék meg vannak osztva.)",
"Tagged files" : "Címkézett fájlok",
- "Select tags to filter by" : "Kiválasztott címkék a szűrő által:",
+ "Select tags to filter by" : "Válasszon címkéket a szűréshez:",
"No tags found" : "Nem találhatók címkék",
- "Please select tags to filter by" : "Kéjük, válasszon ki címkét a szűréshez:",
- "No files found for the selected tags" : "Nem található fájl a kiválasztott címkéhez.",
- "Collaborative tags are available for all users. Restricted tags are visible to users but cannot be assigned by them. Invisible tags are for internal use, since users cannot see or assign them." : "A közreműködő címkék elérhetőek az összes felhasználó számára. A korlátozott címkék láthatóak a felhasználók által de nem rendelhetik azt semmihez. A láthatatlan címkék belső használatra vannak fenntartva, mivel a felhasználók nem látják ezeket és nem is tudják semmihez hozzárendelni őket.",
+ "Please select tags to filter by" : "Válasszon címkéket a szűréshez:",
+ "No files found for the selected tags" : "Nem található fájl a kiválasztott címkéhez",
+ "Collaborative tags are available for all users. Restricted tags are visible to users but cannot be assigned by them. Invisible tags are for internal use, since users cannot see or assign them." : "Az együttműködési címkék elérhetők az összes felhasználó számára. A korlátozott címkék láthatók a felhasználók által, de nem rendelhetik azt semmihez. A láthatatlan címkék belső használatra vannak fenntartva, mivel a felhasználók nem látják ezeket, és nem is tudják semmihez hozzárendelni őket.",
"Create a new tag" : "Új címke létrehozása",
"Name" : "Név",
"Public" : "Nyilvános",
diff --git a/apps/updatenotification/l10n/cs.js b/apps/updatenotification/l10n/cs.js
index a71ed8b242d..172c2fc8584 100644
--- a/apps/updatenotification/l10n/cs.js
+++ b/apps/updatenotification/l10n/cs.js
@@ -24,6 +24,7 @@ OC.L10N.register(
"The update check is not yet finished. Please refresh the page." : "Kontrola aktualizací ještě neskončila. Načtěte stránku znovu.",
"Your version is up to date." : "Používáte nejnovější verzi.",
"A non-default update server is in use to be checked for updates:" : "Pro kontrolu aktualizací se používá jiný než výchozí server:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "Níže je možné změnit kanál aktualizací, což se projeví také na stránce pro správu aplikací. Např. po přepnutí kanálu na beta (testování před vydáním), budou zde nabízeny také aktualizace na testovací verze aplikací.",
"Update channel:" : "Kanál aktualizací:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "Vždy je možné přejít na novější verzi. Poté už se ale nelze vrátit zpět ke starší verzi ze stabilního kanálu.",
"Notify members of the following groups about available updates:" : "Upozorňovat členy následujících skupin na dostupnost aktualizací:",
diff --git a/apps/updatenotification/l10n/cs.json b/apps/updatenotification/l10n/cs.json
index f46aacd4eb5..e53b0576977 100644
--- a/apps/updatenotification/l10n/cs.json
+++ b/apps/updatenotification/l10n/cs.json
@@ -22,6 +22,7 @@
"The update check is not yet finished. Please refresh the page." : "Kontrola aktualizací ještě neskončila. Načtěte stránku znovu.",
"Your version is up to date." : "Používáte nejnovější verzi.",
"A non-default update server is in use to be checked for updates:" : "Pro kontrolu aktualizací se používá jiný než výchozí server:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "Níže je možné změnit kanál aktualizací, což se projeví také na stránce pro správu aplikací. Např. po přepnutí kanálu na beta (testování před vydáním), budou zde nabízeny také aktualizace na testovací verze aplikací.",
"Update channel:" : "Kanál aktualizací:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "Vždy je možné přejít na novější verzi. Poté už se ale nelze vrátit zpět ke starší verzi ze stabilního kanálu.",
"Notify members of the following groups about available updates:" : "Upozorňovat členy následujících skupin na dostupnost aktualizací:",
diff --git a/apps/updatenotification/l10n/de_DE.js b/apps/updatenotification/l10n/de_DE.js
index 38d5a3a08e3..f5af1009edc 100644
--- a/apps/updatenotification/l10n/de_DE.js
+++ b/apps/updatenotification/l10n/de_DE.js
@@ -24,6 +24,7 @@ OC.L10N.register(
"The update check is not yet finished. Please refresh the page." : "Die Aktualisierungsprüfung ist noch nicht abgeschlossen. Bitte die Seite neu laden.",
"Your version is up to date." : "Ihre Version ist aktuell.",
"A non-default update server is in use to be checked for updates:" : "Es wird ein Nicht-Standard-Aktualisierungsserver zum Prüfen auf Aktualisierungen verwendet:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "Sie können den Aktualisierungskanal unten ändern, was sich auch auf die Verwaltungsseite der Apps auswirkt. Z.B. Nach dem Wechsel zum Beta-Kanal werden Ihnen Beta-App-Updates auf der App-Verwaltungsseite angeboten.",
"Update channel:" : "Update-Kanal:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "Es kann immer auf eine neuere Version aktualisiert werden. Jedoch kann kein Downgrade auf eine stabilere Version erfolgen. ",
"Notify members of the following groups about available updates:" : "Informieren Sie die Mitglieder der folgenden Gruppen über verfügbare Updates:",
diff --git a/apps/updatenotification/l10n/de_DE.json b/apps/updatenotification/l10n/de_DE.json
index 21f29d8c438..c8808c81e19 100644
--- a/apps/updatenotification/l10n/de_DE.json
+++ b/apps/updatenotification/l10n/de_DE.json
@@ -22,6 +22,7 @@
"The update check is not yet finished. Please refresh the page." : "Die Aktualisierungsprüfung ist noch nicht abgeschlossen. Bitte die Seite neu laden.",
"Your version is up to date." : "Ihre Version ist aktuell.",
"A non-default update server is in use to be checked for updates:" : "Es wird ein Nicht-Standard-Aktualisierungsserver zum Prüfen auf Aktualisierungen verwendet:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "Sie können den Aktualisierungskanal unten ändern, was sich auch auf die Verwaltungsseite der Apps auswirkt. Z.B. Nach dem Wechsel zum Beta-Kanal werden Ihnen Beta-App-Updates auf der App-Verwaltungsseite angeboten.",
"Update channel:" : "Update-Kanal:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "Es kann immer auf eine neuere Version aktualisiert werden. Jedoch kann kein Downgrade auf eine stabilere Version erfolgen. ",
"Notify members of the following groups about available updates:" : "Informieren Sie die Mitglieder der folgenden Gruppen über verfügbare Updates:",
diff --git a/apps/updatenotification/l10n/hu.js b/apps/updatenotification/l10n/hu.js
index fba74394c00..d535d99283e 100644
--- a/apps/updatenotification/l10n/hu.js
+++ b/apps/updatenotification/l10n/hu.js
@@ -16,6 +16,7 @@ OC.L10N.register(
"Apps missing compatible version" : "Az alkalmazásoknak nincs kompatibilis verziója",
"View in store" : "Megtekintés a tárban",
"Apps with compatible version" : "Alkalmazások kompatibilis verzióval",
+ "Please note that the web updater is not recommended with more than 100 users! Please use the command line updater instead!" : "Vegye figyelembe, hogy a webes frissítő több mint 100 felhasználóval nem ajánlott. Használja helyette a parancssoros frissítőt.",
"Open updater" : "Frissítő megnyitása",
"Download now" : "Letöltés most",
"Please use the command line updater to update." : "Az frissítéshez kérjük használja a parancssoros frissítéskezelőt.",
@@ -23,6 +24,7 @@ OC.L10N.register(
"The update check is not yet finished. Please refresh the page." : "A frissítéskeresés még nem ért véget. Frissítse az oldalt.",
"Your version is up to date." : "A verziója naprakész.",
"A non-default update server is in use to be checked for updates:" : "Egy nem alapértelmezett frissítési kiszolgáló van használatban a frissítések kereséséhez:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "Alább módosíthatja a frissítési csatornát, amely érinti az alkalmazáskezelés oldalt is. Például ha a béta csatornára bált, akkor a béta alkalmazásfrissítések is fel lesznek kínálva az alkalmazáskezelés oldalon.",
"Update channel:" : "Frissítési csatorna:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "Bármikor frissíthet egy újabb verzióra, viszont sosem léphet vissza egy stabilabb verzióra.",
"Notify members of the following groups about available updates:" : "A következő csoport tagjainak értesítése az elérhető frissítésekről:",
diff --git a/apps/updatenotification/l10n/hu.json b/apps/updatenotification/l10n/hu.json
index a8701d8b0e4..9b21c0b49d7 100644
--- a/apps/updatenotification/l10n/hu.json
+++ b/apps/updatenotification/l10n/hu.json
@@ -14,6 +14,7 @@
"Apps missing compatible version" : "Az alkalmazásoknak nincs kompatibilis verziója",
"View in store" : "Megtekintés a tárban",
"Apps with compatible version" : "Alkalmazások kompatibilis verzióval",
+ "Please note that the web updater is not recommended with more than 100 users! Please use the command line updater instead!" : "Vegye figyelembe, hogy a webes frissítő több mint 100 felhasználóval nem ajánlott. Használja helyette a parancssoros frissítőt.",
"Open updater" : "Frissítő megnyitása",
"Download now" : "Letöltés most",
"Please use the command line updater to update." : "Az frissítéshez kérjük használja a parancssoros frissítéskezelőt.",
@@ -21,6 +22,7 @@
"The update check is not yet finished. Please refresh the page." : "A frissítéskeresés még nem ért véget. Frissítse az oldalt.",
"Your version is up to date." : "A verziója naprakész.",
"A non-default update server is in use to be checked for updates:" : "Egy nem alapértelmezett frissítési kiszolgáló van használatban a frissítések kereséséhez:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "Alább módosíthatja a frissítési csatornát, amely érinti az alkalmazáskezelés oldalt is. Például ha a béta csatornára bált, akkor a béta alkalmazásfrissítések is fel lesznek kínálva az alkalmazáskezelés oldalon.",
"Update channel:" : "Frissítési csatorna:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "Bármikor frissíthet egy újabb verzióra, viszont sosem léphet vissza egy stabilabb verzióra.",
"Notify members of the following groups about available updates:" : "A következő csoport tagjainak értesítése az elérhető frissítésekről:",
diff --git a/apps/updatenotification/l10n/pl.js b/apps/updatenotification/l10n/pl.js
index 1bdc7e210d4..4c0a581e9a1 100644
--- a/apps/updatenotification/l10n/pl.js
+++ b/apps/updatenotification/l10n/pl.js
@@ -24,6 +24,7 @@ OC.L10N.register(
"The update check is not yet finished. Please refresh the page." : "Sprawdzanie aktualizacji nie zostało jeszcze zakończone. Odśwież stronę.",
"Your version is up to date." : "Posiadasz aktualną wersję.",
"A non-default update server is in use to be checked for updates:" : "Do sprawdzania aktualizacji nie są używane domyślne serwery aktualizacji:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "Możesz zmienić kanał aktualizacji poniżej, co wpływa również na stronę zarządzania aplikacjami. Np. po przejściu na kanał beta aktualizacje aplikacji beta będą dostępne na stronie zarządzania aplikacjami.",
"Update channel:" : "Kanał aktualizacji:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "Zawsze możesz zaktualizować do nowszej wersji. Ale nigdy nie możesz powrócić do wersji bardziej stabilnej.",
"Notify members of the following groups about available updates:" : "Powiadom członków następujących grup o dostępnych aktualizacjach:",
diff --git a/apps/updatenotification/l10n/pl.json b/apps/updatenotification/l10n/pl.json
index db86c4681b1..281cdbe998f 100644
--- a/apps/updatenotification/l10n/pl.json
+++ b/apps/updatenotification/l10n/pl.json
@@ -22,6 +22,7 @@
"The update check is not yet finished. Please refresh the page." : "Sprawdzanie aktualizacji nie zostało jeszcze zakończone. Odśwież stronę.",
"Your version is up to date." : "Posiadasz aktualną wersję.",
"A non-default update server is in use to be checked for updates:" : "Do sprawdzania aktualizacji nie są używane domyślne serwery aktualizacji:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "Możesz zmienić kanał aktualizacji poniżej, co wpływa również na stronę zarządzania aplikacjami. Np. po przejściu na kanał beta aktualizacje aplikacji beta będą dostępne na stronie zarządzania aplikacjami.",
"Update channel:" : "Kanał aktualizacji:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "Zawsze możesz zaktualizować do nowszej wersji. Ale nigdy nie możesz powrócić do wersji bardziej stabilnej.",
"Notify members of the following groups about available updates:" : "Powiadom członków następujących grup o dostępnych aktualizacjach:",
diff --git a/apps/updatenotification/l10n/tr.js b/apps/updatenotification/l10n/tr.js
index 08cd3e42899..30dc1c81e84 100644
--- a/apps/updatenotification/l10n/tr.js
+++ b/apps/updatenotification/l10n/tr.js
@@ -24,6 +24,7 @@ OC.L10N.register(
"The update check is not yet finished. Please refresh the page." : "Güncelleme denetimi henüz tamamlanmadı. Lütfen sayfayı yenileyin.",
"Your version is up to date." : "Sürümünüz güncel.",
"A non-default update server is in use to be checked for updates:" : "Güncelleme denetimi için varsayılan sunucudan başka bir sunucu kullanılıyor:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "Uygulama yönetimi sayfasını da etkileyen aşağıdaki güncelleme kanalını değiştirebilirsiniz. Örneğin. beta kanalına geçtikten sonra, uygulama yönetimi sayfasında beta uygulama güncellemeleri sunulur.",
"Update channel:" : "Güncelleme kanalı:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "Her zaman bir üst sürüme güncelleyebilirsiniz ancak asla daha kararlı bir eski sürüme dönemezsiniz.",
"Notify members of the following groups about available updates:" : "Yayınlanan güncellemeler şu grupların üyelerine bildirilsin:",
diff --git a/apps/updatenotification/l10n/tr.json b/apps/updatenotification/l10n/tr.json
index 9856dcdab6d..ca1c260bf21 100644
--- a/apps/updatenotification/l10n/tr.json
+++ b/apps/updatenotification/l10n/tr.json
@@ -22,6 +22,7 @@
"The update check is not yet finished. Please refresh the page." : "Güncelleme denetimi henüz tamamlanmadı. Lütfen sayfayı yenileyin.",
"Your version is up to date." : "Sürümünüz güncel.",
"A non-default update server is in use to be checked for updates:" : "Güncelleme denetimi için varsayılan sunucudan başka bir sunucu kullanılıyor:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "Uygulama yönetimi sayfasını da etkileyen aşağıdaki güncelleme kanalını değiştirebilirsiniz. Örneğin. beta kanalına geçtikten sonra, uygulama yönetimi sayfasında beta uygulama güncellemeleri sunulur.",
"Update channel:" : "Güncelleme kanalı:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "Her zaman bir üst sürüme güncelleyebilirsiniz ancak asla daha kararlı bir eski sürüme dönemezsiniz.",
"Notify members of the following groups about available updates:" : "Yayınlanan güncellemeler şu grupların üyelerine bildirilsin:",
diff --git a/apps/updatenotification/l10n/zh_HK.js b/apps/updatenotification/l10n/zh_HK.js
index 8484706d735..9c2538a7b62 100644
--- a/apps/updatenotification/l10n/zh_HK.js
+++ b/apps/updatenotification/l10n/zh_HK.js
@@ -24,6 +24,7 @@ OC.L10N.register(
"The update check is not yet finished. Please refresh the page." : "更新檢查未完成。請重新整理此頁面。",
"Your version is up to date." : "您的版本是最新版。",
"A non-default update server is in use to be checked for updates:" : "此非默認更新伺服器用於檢查更新:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "您可以變更下方的更新頻道,這也會影響應用程式管理頁面。例如,切換到測試版頻道後,在應用程式管理頁更新應用程式時也會提供測試版。",
"Update channel:" : "更新頻道:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "您可以更新到新版本,但無法降級到較穩定的版本。",
"Notify members of the following groups about available updates:" : "有可用更新時通知這些以下群組的成員:",
diff --git a/apps/updatenotification/l10n/zh_HK.json b/apps/updatenotification/l10n/zh_HK.json
index fb4bb9d55d7..27f8820fd1b 100644
--- a/apps/updatenotification/l10n/zh_HK.json
+++ b/apps/updatenotification/l10n/zh_HK.json
@@ -22,6 +22,7 @@
"The update check is not yet finished. Please refresh the page." : "更新檢查未完成。請重新整理此頁面。",
"Your version is up to date." : "您的版本是最新版。",
"A non-default update server is in use to be checked for updates:" : "此非默認更新伺服器用於檢查更新:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "您可以變更下方的更新頻道,這也會影響應用程式管理頁面。例如,切換到測試版頻道後,在應用程式管理頁更新應用程式時也會提供測試版。",
"Update channel:" : "更新頻道:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "您可以更新到新版本,但無法降級到較穩定的版本。",
"Notify members of the following groups about available updates:" : "有可用更新時通知這些以下群組的成員:",
diff --git a/apps/updatenotification/l10n/zh_TW.js b/apps/updatenotification/l10n/zh_TW.js
index 6f774f48480..6f85eccc8c4 100644
--- a/apps/updatenotification/l10n/zh_TW.js
+++ b/apps/updatenotification/l10n/zh_TW.js
@@ -24,6 +24,7 @@ OC.L10N.register(
"The update check is not yet finished. Please refresh the page." : "更新檢查未完成。請重新整理此頁面。",
"Your version is up to date." : "您的版本是最新版。",
"A non-default update server is in use to be checked for updates:" : "使用非預設的更新伺服器檢查更新:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "您可以變更下方的更新頻道,這也會影響應用程式管理頁面。例如,切換到測試版頻道後,在應用程式管理頁更新應用程式時也會提供測試版。",
"Update channel:" : "更新頻道:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "您始終可以更新到較新的版本。但您無法降級到較穩定的版本。",
"Notify members of the following groups about available updates:" : "有可用更新時通知這些群組的成員:",
diff --git a/apps/updatenotification/l10n/zh_TW.json b/apps/updatenotification/l10n/zh_TW.json
index 3743afca78f..6ba3b8ef7f1 100644
--- a/apps/updatenotification/l10n/zh_TW.json
+++ b/apps/updatenotification/l10n/zh_TW.json
@@ -22,6 +22,7 @@
"The update check is not yet finished. Please refresh the page." : "更新檢查未完成。請重新整理此頁面。",
"Your version is up to date." : "您的版本是最新版。",
"A non-default update server is in use to be checked for updates:" : "使用非預設的更新伺服器檢查更新:",
+ "You can change the update channel below which also affects the apps management page. E.g. after switching to the beta channel, beta app updates will be offered to you in the apps management page." : "您可以變更下方的更新頻道,這也會影響應用程式管理頁面。例如,切換到測試版頻道後,在應用程式管理頁更新應用程式時也會提供測試版。",
"Update channel:" : "更新頻道:",
"You can always update to a newer version. But you can never downgrade to a more stable version." : "您始終可以更新到較新的版本。但您無法降級到較穩定的版本。",
"Notify members of the following groups about available updates:" : "有可用更新時通知這些群組的成員:",
diff --git a/apps/user_ldap/appinfo/info.xml b/apps/user_ldap/appinfo/info.xml
index 2dae4845241..d654d34d66e 100644
--- a/apps/user_ldap/appinfo/info.xml
+++ b/apps/user_ldap/appinfo/info.xml
@@ -50,6 +50,7 @@ A user logs into Nextcloud with their LDAP or AD credentials, and is granted acc
<command>OCA\User_LDAP\Command\CheckUser</command>
<command>OCA\User_LDAP\Command\CreateEmptyConfig</command>
<command>OCA\User_LDAP\Command\DeleteConfig</command>
+ <command>OCA\User_LDAP\Command\ResetGroup</command>
<command>OCA\User_LDAP\Command\ResetUser</command>
<command>OCA\User_LDAP\Command\Search</command>
<command>OCA\User_LDAP\Command\SetConfig</command>
diff --git a/apps/user_ldap/composer/composer/autoload_classmap.php b/apps/user_ldap/composer/composer/autoload_classmap.php
index 12ede37a941..ae112b2b604 100644
--- a/apps/user_ldap/composer/composer/autoload_classmap.php
+++ b/apps/user_ldap/composer/composer/autoload_classmap.php
@@ -14,6 +14,7 @@ return array(
'OCA\\User_LDAP\\Command\\CheckUser' => $baseDir . '/../lib/Command/CheckUser.php',
'OCA\\User_LDAP\\Command\\CreateEmptyConfig' => $baseDir . '/../lib/Command/CreateEmptyConfig.php',
'OCA\\User_LDAP\\Command\\DeleteConfig' => $baseDir . '/../lib/Command/DeleteConfig.php',
+ 'OCA\\User_LDAP\\Command\\ResetGroup' => $baseDir . '/../lib/Command/ResetGroup.php',
'OCA\\User_LDAP\\Command\\ResetUser' => $baseDir . '/../lib/Command/ResetUser.php',
'OCA\\User_LDAP\\Command\\Search' => $baseDir . '/../lib/Command/Search.php',
'OCA\\User_LDAP\\Command\\SetConfig' => $baseDir . '/../lib/Command/SetConfig.php',
@@ -26,6 +27,7 @@ return array(
'OCA\\User_LDAP\\ConnectionFactory' => $baseDir . '/../lib/ConnectionFactory.php',
'OCA\\User_LDAP\\Controller\\ConfigAPIController' => $baseDir . '/../lib/Controller/ConfigAPIController.php',
'OCA\\User_LDAP\\Controller\\RenewPasswordController' => $baseDir . '/../lib/Controller/RenewPasswordController.php',
+ 'OCA\\User_LDAP\\DataCollector\\LdapDataCollector' => $baseDir . '/../lib/DataCollector/LdapDataCollector.php',
'OCA\\User_LDAP\\Events\\GroupBackendRegistered' => $baseDir . '/../lib/Events/GroupBackendRegistered.php',
'OCA\\User_LDAP\\Events\\UserBackendRegistered' => $baseDir . '/../lib/Events/UserBackendRegistered.php',
'OCA\\User_LDAP\\Exceptions\\AttributeNotSet' => $baseDir . '/../lib/Exceptions/AttributeNotSet.php',
diff --git a/apps/user_ldap/composer/composer/autoload_static.php b/apps/user_ldap/composer/composer/autoload_static.php
index ecf5e4167f6..3ff92c350f5 100644
--- a/apps/user_ldap/composer/composer/autoload_static.php
+++ b/apps/user_ldap/composer/composer/autoload_static.php
@@ -29,6 +29,7 @@ class ComposerStaticInitUser_LDAP
'OCA\\User_LDAP\\Command\\CheckUser' => __DIR__ . '/..' . '/../lib/Command/CheckUser.php',
'OCA\\User_LDAP\\Command\\CreateEmptyConfig' => __DIR__ . '/..' . '/../lib/Command/CreateEmptyConfig.php',
'OCA\\User_LDAP\\Command\\DeleteConfig' => __DIR__ . '/..' . '/../lib/Command/DeleteConfig.php',
+ 'OCA\\User_LDAP\\Command\\ResetGroup' => __DIR__ . '/..' . '/../lib/Command/ResetGroup.php',
'OCA\\User_LDAP\\Command\\ResetUser' => __DIR__ . '/..' . '/../lib/Command/ResetUser.php',
'OCA\\User_LDAP\\Command\\Search' => __DIR__ . '/..' . '/../lib/Command/Search.php',
'OCA\\User_LDAP\\Command\\SetConfig' => __DIR__ . '/..' . '/../lib/Command/SetConfig.php',
@@ -41,6 +42,7 @@ class ComposerStaticInitUser_LDAP
'OCA\\User_LDAP\\ConnectionFactory' => __DIR__ . '/..' . '/../lib/ConnectionFactory.php',
'OCA\\User_LDAP\\Controller\\ConfigAPIController' => __DIR__ . '/..' . '/../lib/Controller/ConfigAPIController.php',
'OCA\\User_LDAP\\Controller\\RenewPasswordController' => __DIR__ . '/..' . '/../lib/Controller/RenewPasswordController.php',
+ 'OCA\\User_LDAP\\DataCollector\\LdapDataCollector' => __DIR__ . '/..' . '/../lib/DataCollector/LdapDataCollector.php',
'OCA\\User_LDAP\\Events\\GroupBackendRegistered' => __DIR__ . '/..' . '/../lib/Events/GroupBackendRegistered.php',
'OCA\\User_LDAP\\Events\\UserBackendRegistered' => __DIR__ . '/..' . '/../lib/Events/UserBackendRegistered.php',
'OCA\\User_LDAP\\Exceptions\\AttributeNotSet' => __DIR__ . '/..' . '/../lib/Exceptions/AttributeNotSet.php',
diff --git a/apps/user_ldap/css/settings.css b/apps/user_ldap/css/settings.css
index 54d0e2dbb0c..f99310118a9 100644
--- a/apps/user_ldap/css/settings.css
+++ b/apps/user_ldap/css/settings.css
@@ -9,7 +9,8 @@
}
.tablerow {
- display: table-row;
+ display: flex;
+ align-items: center;
white-space: nowrap;
text-align: left;
}
@@ -226,3 +227,8 @@ select[multiple=multiple] + button {
#ldapSettings div.ui-accordion-content {
background: white;
}
+
+ul.ui-multiselect-checkboxes label {
+ display: flex;
+ align-items: center;
+}
diff --git a/apps/user_ldap/lib/Command/CreateEmptyConfig.php b/apps/user_ldap/lib/Command/CreateEmptyConfig.php
index 8b1736e3a53..f7f04e28e60 100644
--- a/apps/user_ldap/lib/Command/CreateEmptyConfig.php
+++ b/apps/user_ldap/lib/Command/CreateEmptyConfig.php
@@ -59,6 +59,7 @@ class CreateEmptyConfig extends Command {
protected function execute(InputInterface $input, OutputInterface $output): int {
$configPrefix = $this->helper->getNextServerConfigurationPrefix();
$configHolder = new Configuration($configPrefix);
+ $configHolder->ldapConfigurationActive = false;
$configHolder->saveConfiguration();
$prose = '';
diff --git a/apps/user_ldap/lib/Command/ResetGroup.php b/apps/user_ldap/lib/Command/ResetGroup.php
new file mode 100644
index 00000000000..f3c3019f919
--- /dev/null
+++ b/apps/user_ldap/lib/Command/ResetGroup.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * @copyright Copyright (c) 2021 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ * @author Côme Chilliet <come.chilliet@nextcloud.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace OCA\User_LDAP\Command;
+
+use OCA\User_LDAP\Group_Proxy;
+use OCA\User_LDAP\GroupPluginManager;
+use OCP\IGroup;
+use OCP\IGroupManager;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Helper\QuestionHelper;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Question\Question;
+
+class ResetGroup extends Command {
+ private IGroupManager $groupManager;
+ private GroupPluginManager $pluginManager;
+ private Group_Proxy $backend;
+
+ public function __construct(
+ IGroupManager $groupManager,
+ GroupPluginManager $pluginManager,
+ Group_Proxy $backend
+ ) {
+ $this->groupManager = $groupManager;
+ $this->pluginManager = $pluginManager;
+ $this->backend = $backend;
+ parent::__construct();
+ }
+
+ protected function configure(): void {
+ $this
+ ->setName('ldap:reset-group')
+ ->setDescription('deletes an LDAP group independent of the group state in the LDAP')
+ ->addArgument(
+ 'gid',
+ InputArgument::REQUIRED,
+ 'the group name as used in Nextcloud'
+ )
+ ->addOption(
+ 'yes',
+ 'y',
+ InputOption::VALUE_NONE,
+ 'do not ask for confirmation'
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ try {
+ $gid = $input->getArgument('gid');
+ $group = $this->groupManager->get($gid);
+ if (!$group instanceof IGroup) {
+ throw new \Exception('Group not found');
+ }
+ $backends = $group->getBackendNames();
+ if (!in_array('LDAP', $backends)) {
+ throw new \Exception('The given group is not a recognized LDAP group.');
+ }
+ if ($input->getOption('yes') === false) {
+ /** @var QuestionHelper $helper */
+ $helper = $this->getHelper('question');
+ $q = new Question('Delete all local data of this group (y|N)? ');
+ $input->setOption('yes', $helper->ask($input, $output, $q) === 'y');
+ }
+ if ($input->getOption('yes') !== true) {
+ throw new \Exception('Reset cancelled by operator');
+ }
+
+ // Disable real deletion if a plugin supports it
+ $pluginManagerSuppressed = $this->pluginManager->setSuppressDeletion(true);
+ // Bypass groupExists test to force mapping deletion
+ $this->backend->getLDAPAccess($gid)->connection->writeToCache('groupExists' . $gid, false);
+ echo "calling delete $gid\n";
+ if ($group->delete()) {
+ $this->pluginManager->setSuppressDeletion($pluginManagerSuppressed);
+ return 0;
+ }
+ } catch (\Throwable $e) {
+ if (isset($pluginManagerSuppressed)) {
+ $this->pluginManager->setSuppressDeletion($pluginManagerSuppressed);
+ }
+ $output->writeln('<error>' . $e->getMessage() . '</error>');
+ return 1;
+ }
+ $output->writeln('<error>Error while resetting group</error>');
+ return 2;
+ }
+}
diff --git a/apps/user_ldap/lib/Configuration.php b/apps/user_ldap/lib/Configuration.php
index 9ffb2a79781..c16823d39ee 100644
--- a/apps/user_ldap/lib/Configuration.php
+++ b/apps/user_ldap/lib/Configuration.php
@@ -56,10 +56,9 @@ class Configuration {
*/
protected $configRead = false;
/**
- * @var string[] pre-filled with one reference key so that at least one entry is written on save request and
- * the config ID is registered
+ * @var string[]
*/
- protected $unsavedChanges = ['ldapConfigurationActive' => 'ldapConfigurationActive'];
+ protected array $unsavedChanges = [];
/**
* @var array<string, mixed> settings
@@ -257,6 +256,7 @@ class Configuration {
*/
public function saveConfiguration(): void {
$cta = array_flip($this->getConfigTranslationArray());
+ $changed = false;
foreach ($this->unsavedChanges as $key) {
$value = $this->config[$key];
switch ($key) {
@@ -286,9 +286,12 @@ class Configuration {
if (is_null($value)) {
$value = '';
}
+ $changed = true;
$this->saveValue($cta[$key], $value);
}
- $this->saveValue('_lastChange', (string)time());
+ if ($changed) {
+ $this->saveValue('_lastChange', (string)time());
+ }
$this->unsavedChanges = [];
}
diff --git a/apps/user_ldap/lib/Controller/ConfigAPIController.php b/apps/user_ldap/lib/Controller/ConfigAPIController.php
index 72ded754880..e408d03fcd5 100644
--- a/apps/user_ldap/lib/Controller/ConfigAPIController.php
+++ b/apps/user_ldap/lib/Controller/ConfigAPIController.php
@@ -118,6 +118,7 @@ class ConfigAPIController extends OCSController {
try {
$configPrefix = $this->ldapHelper->getNextServerConfigurationPrefix();
$configHolder = new Configuration($configPrefix);
+ $configHolder->ldapConfigurationActive = false;
$configHolder->saveConfiguration();
} catch (\Exception $e) {
$this->logger->logException($e);
diff --git a/apps/user_ldap/lib/DataCollector/LdapDataCollector.php b/apps/user_ldap/lib/DataCollector/LdapDataCollector.php
new file mode 100644
index 00000000000..cb61de96e37
--- /dev/null
+++ b/apps/user_ldap/lib/DataCollector/LdapDataCollector.php
@@ -0,0 +1,50 @@
+<?php declare(strict_types = 1);
+/**
+ * @copyright 2022 Carl Schwan <carl@carlschwan.eu>
+ *
+ * @author Carl Schwan <carl@carlschwan.eu>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\User_LDAP\DataCollector;
+
+use OC\AppFramework\Http\Request;
+use OCP\AppFramework\Http\Response;
+use OCP\DataCollector\AbstractDataCollector;
+
+class LdapDataCollector extends AbstractDataCollector {
+ public function startLdapRequest(string $query, array $args): void {
+ $this->data[] = [
+ 'start' => microtime(true),
+ 'query' => $query,
+ 'args' => $args,
+ 'end' => microtime(true),
+ ];
+ }
+
+ public function stopLastLdapRequest(): void {
+ $this->data[count($this->data) - 1]['end'] = microtime(true);
+ }
+
+ public function getName(): string {
+ return 'ldap';
+ }
+
+ public function collect(Request $request, Response $response, \Throwable $exception = null): void {
+ }
+}
diff --git a/apps/user_ldap/lib/GroupPluginManager.php b/apps/user_ldap/lib/GroupPluginManager.php
index d23e9d4d443..5999409cdba 100644
--- a/apps/user_ldap/lib/GroupPluginManager.php
+++ b/apps/user_ldap/lib/GroupPluginManager.php
@@ -26,9 +26,10 @@ namespace OCA\User_LDAP;
use OCP\GroupInterface;
class GroupPluginManager {
- private $respondToActions = 0;
+ private int $respondToActions = 0;
- private $which = [
+ /** @var array<int, ?ILDAPGroupPlugin> */
+ private array $which = [
GroupInterface::CREATE_GROUP => null,
GroupInterface::DELETE_GROUP => null,
GroupInterface::ADD_TO_GROUP => null,
@@ -37,6 +38,8 @@ class GroupPluginManager {
GroupInterface::GROUP_DETAILS => null
];
+ private bool $suppressDeletion = false;
+
/**
* @return int All implemented actions
*/
@@ -84,16 +87,31 @@ class GroupPluginManager {
throw new \Exception('No plugin implements createGroup in this LDAP Backend.');
}
+ public function canDeleteGroup(): bool {
+ return !$this->suppressDeletion && $this->implementsActions(GroupInterface::DELETE_GROUP);
+ }
+
+ /**
+ * @return bool – the value before the change
+ */
+ public function setSuppressDeletion(bool $value): bool {
+ $old = $this->suppressDeletion;
+ $this->suppressDeletion = $value;
+ return $old;
+ }
+
/**
* Delete a group
- * @param string $gid Group Id of the group to delete
- * @return bool
+ *
* @throws \Exception
*/
- public function deleteGroup($gid) {
+ public function deleteGroup(string $gid): bool {
$plugin = $this->which[GroupInterface::DELETE_GROUP];
if ($plugin) {
+ if ($this->suppressDeletion) {
+ return false;
+ }
return $plugin->deleteGroup($gid);
}
throw new \Exception('No plugin implements deleteGroup in this LDAP Backend.');
diff --git a/apps/user_ldap/lib/Group_LDAP.php b/apps/user_ldap/lib/Group_LDAP.php
index 766b77bf521..f9d9b061743 100644
--- a/apps/user_ldap/lib/Group_LDAP.php
+++ b/apps/user_ldap/lib/Group_LDAP.php
@@ -48,10 +48,11 @@ use OC;
use OC\Cache\CappedMemoryCache;
use OC\ServerNotAvailableException;
use OCP\Group\Backend\IGetDisplayNameBackend;
+use OCP\Group\Backend\IDeleteGroupBackend;
use OCP\GroupInterface;
use Psr\Log\LoggerInterface;
-class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, IGetDisplayNameBackend {
+class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, IGetDisplayNameBackend, IDeleteGroupBackend {
protected $enabled = false;
/** @var string[][] $cachedGroupMembers array of users with gid as key */
@@ -1204,6 +1205,7 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
*/
public function implementsActions($actions) {
return (bool)((GroupInterface::COUNT_USERS |
+ GroupInterface::DELETE_GROUP |
$this->groupPluginManager->getImplementedActions()) & $actions);
}
@@ -1249,19 +1251,32 @@ class Group_LDAP extends BackendUtility implements GroupInterface, IGroupLDAP, I
* delete a group
*
* @param string $gid gid of the group to delete
- * @return bool
* @throws Exception
*/
- public function deleteGroup($gid) {
- if ($this->groupPluginManager->implementsActions(GroupInterface::DELETE_GROUP)) {
+ public function deleteGroup(string $gid): bool {
+ if ($this->groupPluginManager->canDeleteGroup()) {
if ($ret = $this->groupPluginManager->deleteGroup($gid)) {
- #delete group in nextcloud internal db
+ // Delete group in nextcloud internal db
$this->access->getGroupMapper()->unmap($gid);
$this->access->connection->writeToCache("groupExists" . $gid, false);
}
return $ret;
}
- throw new Exception('Could not delete group in LDAP backend.');
+
+ // Getting dn, if false the group is not mapped
+ $dn = $this->access->groupname2dn($gid);
+ if (!$dn) {
+ throw new Exception('Could not delete unknown group '.$gid.' in LDAP backend.');
+ }
+
+ if (!$this->groupExists($gid)) {
+ // The group does not exist in the LDAP, remove the mapping
+ $this->access->getGroupMapper()->unmap($gid);
+ $this->access->connection->writeToCache("groupExists" . $gid, false);
+ return true;
+ }
+
+ throw new Exception('Could not delete existing group '.$gid.' in LDAP backend.');
}
/**
diff --git a/apps/user_ldap/lib/Group_Proxy.php b/apps/user_ldap/lib/Group_Proxy.php
index 92a9041949e..ea2fcce679c 100644
--- a/apps/user_ldap/lib/Group_Proxy.php
+++ b/apps/user_ldap/lib/Group_Proxy.php
@@ -28,10 +28,11 @@
*/
namespace OCA\User_LDAP;
-use OCP\Group\Backend\INamedBackend;
+use OCP\Group\Backend\IDeleteGroupBackend;
use OCP\Group\Backend\IGetDisplayNameBackend;
+use OCP\Group\Backend\INamedBackend;
-class Group_Proxy extends Proxy implements \OCP\GroupInterface, IGroupLDAP, IGetDisplayNameBackend, INamedBackend {
+class Group_Proxy extends Proxy implements \OCP\GroupInterface, IGroupLDAP, IGetDisplayNameBackend, INamedBackend, IDeleteGroupBackend {
private $backends = [];
private $refBackend = null;
@@ -171,11 +172,8 @@ class Group_Proxy extends Proxy implements \OCP\GroupInterface, IGroupLDAP, IGet
/**
* delete a group
- *
- * @param string $gid gid of the group to delete
- * @return bool
*/
- public function deleteGroup($gid) {
+ public function deleteGroup(string $gid): bool {
return $this->handleRequest(
$gid, 'deleteGroup', [$gid]);
}
diff --git a/apps/user_ldap/lib/LDAP.php b/apps/user_ldap/lib/LDAP.php
index 18a9476128d..3c579596941 100644
--- a/apps/user_ldap/lib/LDAP.php
+++ b/apps/user_ldap/lib/LDAP.php
@@ -14,6 +14,7 @@
* @author Robin McCorkell <robin@mccorkell.me.uk>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Roger Szabo <roger.szabo@web.de>
+ * @author Carl Schwan <carl@carlschwan.eu>
*
* @license AGPL-3.0
*
@@ -32,7 +33,9 @@
*/
namespace OCA\User_LDAP;
+use OCP\Profiler\IProfiler;
use OC\ServerNotAvailableException;
+use OCA\User_LDAP\DataCollector\LdapDataCollector;
use OCA\User_LDAP\Exceptions\ConstraintViolationException;
use OCA\User_LDAP\PagedResults\IAdapter;
use OCA\User_LDAP\PagedResults\Php73;
@@ -45,9 +48,18 @@ class LDAP implements ILDAPWrapper {
/** @var IAdapter */
protected $pagedResultsAdapter;
+ private ?LdapDataCollector $dataCollector = null;
+
public function __construct(string $logFile = '') {
$this->pagedResultsAdapter = new Php73();
$this->logFile = $logFile;
+
+ /** @var IProfiler $profiler */
+ $profiler = \OC::$server->get(IProfiler::class);
+ if ($profiler->isEnabled()) {
+ $this->dataCollector = new LdapDataCollector();
+ $profiler->add($this->dataCollector);
+ }
}
/**
@@ -295,24 +307,26 @@ class LDAP implements ILDAPWrapper {
if ($this->isResultFalse($result)) {
$this->postFunctionCall();
}
+ if ($this->dataCollector !== null) {
+ $this->dataCollector->stopLastLdapRequest();
+ }
return $result;
}
return null;
}
- /**
- * @param string $functionName
- * @param array $args
- */
- private function preFunctionCall($functionName, $args) {
+ private function preFunctionCall(string $functionName, array $args): void {
$this->curFunc = $functionName;
$this->curArgs = $args;
+ if ($this->dataCollector !== null) {
+ $args = array_map(fn ($item) => (!$this->isResource($item) ? $item : '(resource)'), $this->curArgs);
+
+ $this->dataCollector->startLdapRequest($this->curFunc, $args);
+ }
+
if ($this->logFile !== '' && is_writable(dirname($this->logFile)) && (!file_exists($this->logFile) || is_writable($this->logFile))) {
- $args = array_reduce($this->curArgs, static function (array $carry, $item): array {
- $carry[] = !is_resource($item) ? $item : '(resource)';
- return $carry;
- }, []);
+ $args = array_map(fn ($item) => (!$this->isResource($item) ? $item : '(resource)'), $this->curArgs);
file_put_contents(
$this->logFile,
$this->curFunc . '::' . json_encode($args) . "\n",
diff --git a/apps/user_ldap/lib/Migration/Version1120Date20210917155206.php b/apps/user_ldap/lib/Migration/Version1120Date20210917155206.php
index bca390441d7..b7a9b81d6a0 100644
--- a/apps/user_ldap/lib/Migration/Version1120Date20210917155206.php
+++ b/apps/user_ldap/lib/Migration/Version1120Date20210917155206.php
@@ -129,7 +129,7 @@ class Version1120Date20210917155206 extends SimpleMigrationStep {
$qb = $this->dbc->getQueryBuilder();
$qb->select('owncloud_name', 'directory_uuid')
->from($table)
- ->where($qb->expr()->gt($qb->func()->octetLength('owncloud_name'), '64', IQueryBuilder::PARAM_INT));
+ ->where($qb->expr()->gt($qb->func()->octetLength('owncloud_name'), $qb->createNamedParameter('64'), IQueryBuilder::PARAM_INT));
return $qb;
}
diff --git a/apps/user_ldap/lib/Migration/Version1141Date20220323143801.php b/apps/user_ldap/lib/Migration/Version1141Date20220323143801.php
index be496d9215e..10043371aae 100644
--- a/apps/user_ldap/lib/Migration/Version1141Date20220323143801.php
+++ b/apps/user_ldap/lib/Migration/Version1141Date20220323143801.php
@@ -51,7 +51,7 @@ class Version1141Date20220323143801 extends SimpleMigrationStep {
$qb = $this->dbc->getQueryBuilder();
$qb->select('ldap_dn')
->from($tableName)
- ->where($qb->expr()->gt($qb->func()->octetLength('ldap_dn'), '4000', IQueryBuilder::PARAM_INT));
+ ->where($qb->expr()->gt($qb->func()->octetLength('ldap_dn'), $qb->createNamedParameter('4000'), IQueryBuilder::PARAM_INT));
$dnsTooLong = [];
$result = $qb->executeQuery();
diff --git a/apps/user_ldap/lib/UserPluginManager.php b/apps/user_ldap/lib/UserPluginManager.php
index 035b7952dce..748a210cf60 100644
--- a/apps/user_ldap/lib/UserPluginManager.php
+++ b/apps/user_ldap/lib/UserPluginManager.php
@@ -28,9 +28,9 @@ namespace OCA\User_LDAP;
use OC\User\Backend;
class UserPluginManager {
- private $respondToActions = 0;
+ private int $respondToActions = 0;
- private $which = [
+ private array $which = [
Backend::CREATE_USER => null,
Backend::SET_PASSWORD => null,
Backend::GET_HOME => null,
@@ -41,8 +41,7 @@ class UserPluginManager {
'deleteUser' => null
];
- /** @var bool */
- private $suppressDeletion = false;
+ private bool $suppressDeletion = false;
/**
* @return int All implemented actions, except for 'deleteUser'
diff --git a/apps/user_ldap/lib/Wizard.php b/apps/user_ldap/lib/Wizard.php
index 98d399b77b9..ae9546be08b 100644
--- a/apps/user_ldap/lib/Wizard.php
+++ b/apps/user_ldap/lib/Wizard.php
@@ -1331,7 +1331,7 @@ class Wizard extends LDAPUtility {
$this->configuration->ldapAgentName,
$this->configuration->ldapAgentPassword);
if ($lo === true) {
- $this->$cr = $cr;
+ $this->cr = $cr;
return $cr;
}
diff --git a/apps/user_ldap/tests/GroupLDAPPluginTest.php b/apps/user_ldap/tests/GroupLDAPPluginTest.php
index b55f57990a0..660608d6b1f 100644
--- a/apps/user_ldap/tests/GroupLDAPPluginTest.php
+++ b/apps/user_ldap/tests/GroupLDAPPluginTest.php
@@ -84,7 +84,7 @@ class GroupLDAPPluginTest extends \Test\TestCase {
$pluginManager->createGroup('group');
}
-
+
public function testCreateGroupNotRegistered() {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('No plugin implements createGroup in this LDAP Backend.');
@@ -108,13 +108,13 @@ class GroupLDAPPluginTest extends \Test\TestCase {
->method('deleteGroup')
->with(
$this->equalTo('group')
- );
+ )->willReturn(true);
$pluginManager->register($plugin);
- $pluginManager->deleteGroup('group');
+ $this->assertTrue($pluginManager->deleteGroup('group'));
}
-
+
public function testDeleteGroupNotRegistered() {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('No plugin implements deleteGroup in this LDAP Backend.');
@@ -145,7 +145,7 @@ class GroupLDAPPluginTest extends \Test\TestCase {
$pluginManager->addToGroup('uid', 'gid');
}
-
+
public function testAddToGroupNotRegistered() {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('No plugin implements addToGroup in this LDAP Backend.');
@@ -176,7 +176,7 @@ class GroupLDAPPluginTest extends \Test\TestCase {
$pluginManager->removeFromGroup('uid', 'gid');
}
-
+
public function testRemoveFromGroupNotRegistered() {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('No plugin implements removeFromGroup in this LDAP Backend.');
@@ -207,7 +207,7 @@ class GroupLDAPPluginTest extends \Test\TestCase {
$pluginManager->countUsersInGroup('gid', 'search');
}
-
+
public function testCountUsersInGroupNotRegistered() {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('No plugin implements countUsersInGroup in this LDAP Backend.');
@@ -237,7 +237,7 @@ class GroupLDAPPluginTest extends \Test\TestCase {
$pluginManager->getGroupDetails('gid');
}
-
+
public function testgetGroupDetailsNotRegistered() {
$this->expectException(\Exception::class);
$this->expectExceptionMessage('No plugin implements getGroupDetails in this LDAP Backend.');
diff --git a/apps/user_ldap/tests/Group_LDAPTest.php b/apps/user_ldap/tests/Group_LDAPTest.php
index f8327c0776c..6204c22cb9e 100644
--- a/apps/user_ldap/tests/Group_LDAPTest.php
+++ b/apps/user_ldap/tests/Group_LDAPTest.php
@@ -1092,7 +1092,7 @@ class Group_LDAPTest extends TestCase {
$pluginManager->expects($this->once())
->method('deleteGroup')
->with('gid')
- ->willReturn('result');
+ ->willReturn(true);
$mapper = $this->getMockBuilder(GroupMapping::class)
->setMethods(['unmap'])
@@ -1108,7 +1108,7 @@ class Group_LDAPTest extends TestCase {
$ldap = new GroupLDAP($access, $pluginManager);
- $this->assertEquals($ldap->deleteGroup('gid'), 'result');
+ $this->assertTrue($ldap->deleteGroup('gid'));
}
diff --git a/apps/weather_status/l10n/cs.js b/apps/weather_status/l10n/cs.js
index e7fb1f90730..e83018187d8 100644
--- a/apps/weather_status/l10n/cs.js
+++ b/apps/weather_status/l10n/cs.js
@@ -21,18 +21,18 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} polojasno",
"{temperature} {unit} foggy later today" : "{temperature} {unit} mlhavo dnes později",
"{temperature} {unit} foggy" : "{temperature} {unit} mlhavo",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} drobný déšť dnes později",
- "{temperature} {unit} light rain" : "{temperature} {unit} drobný déšť",
- "{temperature} {unit} rain later today" : "{temperature} {unit} drobný déšť dnes později",
- "{temperature} {unit} rain" : "{temperature} {unit} déšť",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} hustý déšť dnes později",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} hustý déšť",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} přeháňky dnes později",
- "{temperature} {unit} rain showers" : "{temperature} {unit} přeháňky",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} drobné přeháňky dnes později",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} drobné přeháňky",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} intenzivní přeháňky dnes později",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} intenzivní přeháňky",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} drobný déšť dnes později",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} drobný déšť",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} drobný déšť dnes později",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} déšť",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} hustý déšť dnes později",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} hustý déšť",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} přeháňky dnes později",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} přeháňky",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} drobné přeháňky dnes později",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} drobné přeháňky",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} intenzivní přeháňky dnes později",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} intenzivní přeháňky",
"More weather for {adr}" : "Více o počasí pro {adr}",
"Loading weather" : "Načítá se počasí",
"Remove from favorites" : "Odebrat z oblíbených",
diff --git a/apps/weather_status/l10n/cs.json b/apps/weather_status/l10n/cs.json
index c6e7841cc84..1a90e43161d 100644
--- a/apps/weather_status/l10n/cs.json
+++ b/apps/weather_status/l10n/cs.json
@@ -19,18 +19,18 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} polojasno",
"{temperature} {unit} foggy later today" : "{temperature} {unit} mlhavo dnes později",
"{temperature} {unit} foggy" : "{temperature} {unit} mlhavo",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} drobný déšť dnes později",
- "{temperature} {unit} light rain" : "{temperature} {unit} drobný déšť",
- "{temperature} {unit} rain later today" : "{temperature} {unit} drobný déšť dnes později",
- "{temperature} {unit} rain" : "{temperature} {unit} déšť",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} hustý déšť dnes později",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} hustý déšť",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} přeháňky dnes později",
- "{temperature} {unit} rain showers" : "{temperature} {unit} přeháňky",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} drobné přeháňky dnes později",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} drobné přeháňky",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} intenzivní přeháňky dnes později",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} intenzivní přeháňky",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} drobný déšť dnes později",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} drobný déšť",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} drobný déšť dnes později",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} déšť",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} hustý déšť dnes později",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} hustý déšť",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} přeháňky dnes později",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} přeháňky",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} drobné přeháňky dnes později",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} drobné přeháňky",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} intenzivní přeháňky dnes později",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} intenzivní přeháňky",
"More weather for {adr}" : "Více o počasí pro {adr}",
"Loading weather" : "Načítá se počasí",
"Remove from favorites" : "Odebrat z oblíbených",
diff --git a/apps/weather_status/l10n/de.js b/apps/weather_status/l10n/de.js
index 3787804bcd3..a5418ee4237 100644
--- a/apps/weather_status/l10n/de.js
+++ b/apps/weather_status/l10n/de.js
@@ -11,28 +11,28 @@ OC.L10N.register(
"Detect location" : "Standort ermitteln",
"Set custom address" : "Benutzerdefinierte Adresse festlegen",
"Favorites" : "Favoriten",
- "{temperature} {unit} clear sky later today" : "Später am Tag {temperature} {unit} klarer Himmel ",
+ "{temperature} {unit} clear sky later today" : "{temperature} {unit} klarer Himmel später am Tag",
"{temperature} {unit} clear sky" : "{temperature} {unit} klarer Himmel",
- "{temperature} {unit} cloudy later today" : "Später am Tag {temperature} {unit} bewölkt",
+ "{temperature} {unit} cloudy later today" : "{temperature} {unit} bewölkt später am Tag",
"{temperature} {unit} cloudy" : "{temperature} {unit} bewölkt",
- "{temperature} {unit} fair weather later today" : "Später am Tag {temperature} {unit} schönes Wetter",
+ "{temperature} {unit} fair weather later today" : "{temperature} {unit} schönes Wetter später am Tag",
"{temperature} {unit} fair weather" : "{temperature} {unit} schönes Wetter",
- "{temperature} {unit} partly cloudy later today" : "Später am Tag {temperature} {unit} teilweise bewölkt",
+ "{temperature} {unit} partly cloudy later today" : "{temperature} {unit} teilweise bewölkt später am Tag",
"{temperature} {unit} partly cloudy" : "{temperature} {unit} teilweise bewölkt",
- "{temperature} {unit} foggy later today" : "Später am Tag {temperature} {unit} nebelig",
+ "{temperature} {unit} foggy later today" : "{temperature} {unit} neblig später am Tag",
"{temperature} {unit} foggy" : "{temperature} {unit} nebelig",
- "{temperature} {unit} light rain later today" : "Später am Tag {temperature} {unit} leichter Regen",
- "{temperature} {unit} light rain" : "{temperature} {unit} leichter Regen",
- "{temperature} {unit} rain later today" : "Später am Tag {temperature} {unit} Regen",
- "{temperature} {unit} rain" : "{temperature} {unit} Regen",
- "{temperature} {unit} heavy rain later today" : "Später am Tag {temperature} {unit} starker Regen",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} starker Regen",
- "{temperature} {unit} rain showers later today" : "Später am Tag {temperature} {unit} Regenschauer",
- "{temperature} {unit} rain showers" : "{temperature} {unit} Regenschauer",
- "{temperature} {unit} light rain showers later today" : "Später am Tag {temperature} {unit} leichte Regenschauer",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} leichte Regenschauer",
- "{temperature} {unit} heavy rain showers later today" : "Später am Tag {temperature} {unit} starke Regenschauer",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} starke Regenschauer",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} leichter Regen später am Tag",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} leichter Regen",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} Regen später am Tag",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} Regen",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} starker Regen später am Tag",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} starker Regen",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} Regenschauer später am Tag",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} Regenschauer",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} leichte Regenschauer später am Tag",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} leichte Regenschauer",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} starke Regenschauer später am Tag",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} starke Regenschauer",
"More weather for {adr}" : "Mehr Wetter für {adr}",
"Loading weather" : "Lade Wetter",
"Remove from favorites" : "Von Favoriten entfernen",
diff --git a/apps/weather_status/l10n/de.json b/apps/weather_status/l10n/de.json
index d35207419a6..cddfd88b461 100644
--- a/apps/weather_status/l10n/de.json
+++ b/apps/weather_status/l10n/de.json
@@ -9,28 +9,28 @@
"Detect location" : "Standort ermitteln",
"Set custom address" : "Benutzerdefinierte Adresse festlegen",
"Favorites" : "Favoriten",
- "{temperature} {unit} clear sky later today" : "Später am Tag {temperature} {unit} klarer Himmel ",
+ "{temperature} {unit} clear sky later today" : "{temperature} {unit} klarer Himmel später am Tag",
"{temperature} {unit} clear sky" : "{temperature} {unit} klarer Himmel",
- "{temperature} {unit} cloudy later today" : "Später am Tag {temperature} {unit} bewölkt",
+ "{temperature} {unit} cloudy later today" : "{temperature} {unit} bewölkt später am Tag",
"{temperature} {unit} cloudy" : "{temperature} {unit} bewölkt",
- "{temperature} {unit} fair weather later today" : "Später am Tag {temperature} {unit} schönes Wetter",
+ "{temperature} {unit} fair weather later today" : "{temperature} {unit} schönes Wetter später am Tag",
"{temperature} {unit} fair weather" : "{temperature} {unit} schönes Wetter",
- "{temperature} {unit} partly cloudy later today" : "Später am Tag {temperature} {unit} teilweise bewölkt",
+ "{temperature} {unit} partly cloudy later today" : "{temperature} {unit} teilweise bewölkt später am Tag",
"{temperature} {unit} partly cloudy" : "{temperature} {unit} teilweise bewölkt",
- "{temperature} {unit} foggy later today" : "Später am Tag {temperature} {unit} nebelig",
+ "{temperature} {unit} foggy later today" : "{temperature} {unit} neblig später am Tag",
"{temperature} {unit} foggy" : "{temperature} {unit} nebelig",
- "{temperature} {unit} light rain later today" : "Später am Tag {temperature} {unit} leichter Regen",
- "{temperature} {unit} light rain" : "{temperature} {unit} leichter Regen",
- "{temperature} {unit} rain later today" : "Später am Tag {temperature} {unit} Regen",
- "{temperature} {unit} rain" : "{temperature} {unit} Regen",
- "{temperature} {unit} heavy rain later today" : "Später am Tag {temperature} {unit} starker Regen",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} starker Regen",
- "{temperature} {unit} rain showers later today" : "Später am Tag {temperature} {unit} Regenschauer",
- "{temperature} {unit} rain showers" : "{temperature} {unit} Regenschauer",
- "{temperature} {unit} light rain showers later today" : "Später am Tag {temperature} {unit} leichte Regenschauer",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} leichte Regenschauer",
- "{temperature} {unit} heavy rain showers later today" : "Später am Tag {temperature} {unit} starke Regenschauer",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} starke Regenschauer",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} leichter Regen später am Tag",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} leichter Regen",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} Regen später am Tag",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} Regen",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} starker Regen später am Tag",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} starker Regen",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} Regenschauer später am Tag",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} Regenschauer",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} leichte Regenschauer später am Tag",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} leichte Regenschauer",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} starke Regenschauer später am Tag",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} starke Regenschauer",
"More weather for {adr}" : "Mehr Wetter für {adr}",
"Loading weather" : "Lade Wetter",
"Remove from favorites" : "Von Favoriten entfernen",
diff --git a/apps/weather_status/l10n/de_DE.js b/apps/weather_status/l10n/de_DE.js
index a3c1d4a339f..8b9d67946ee 100644
--- a/apps/weather_status/l10n/de_DE.js
+++ b/apps/weather_status/l10n/de_DE.js
@@ -21,18 +21,18 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} Teilweise bewölkt",
"{temperature} {unit} foggy later today" : "{temperature} {unit} Neblig später am Tag",
"{temperature} {unit} foggy" : "{temperature} {unit} Neblig",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} Leichter Regen später am Tag",
- "{temperature} {unit} light rain" : "{temperature} {unit} Leichter Regen",
- "{temperature} {unit} rain later today" : "{temperature} {unit} Regen später am Tag",
- "{temperature} {unit} rain" : "{temperature} {unit} Regen",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} Starker Regen später am Tag",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} Starker Regen",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} Regenschauer später am Tag",
- "{temperature} {unit} rain showers" : "{temperature} {unit} Regenschauer",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} Leichte Regenschauer später am Tag",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} Leichte Regenschauer",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} Starke Regenschauer später am Tag",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} Starke Regenschauer",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} Leichter Regen später am Tag",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} Leichter Regen",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} Regen später am Tag",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} Regen",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} Starker Regen später am Tag",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} Starker Regen",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} Regenschauer später am Tag",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} Regenschauer",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} Leichte Regenschauer später am Tag",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} Leichte Regenschauer",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} Starke Regenschauer später am Tag",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} Starke Regenschauer",
"More weather for {adr}" : "Mehr Wetter für {adr}",
"Loading weather" : "Lade Wetter",
"Remove from favorites" : "Von Favoriten entfernen",
diff --git a/apps/weather_status/l10n/de_DE.json b/apps/weather_status/l10n/de_DE.json
index 4c198970fc4..891fceb8b62 100644
--- a/apps/weather_status/l10n/de_DE.json
+++ b/apps/weather_status/l10n/de_DE.json
@@ -19,18 +19,18 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} Teilweise bewölkt",
"{temperature} {unit} foggy later today" : "{temperature} {unit} Neblig später am Tag",
"{temperature} {unit} foggy" : "{temperature} {unit} Neblig",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} Leichter Regen später am Tag",
- "{temperature} {unit} light rain" : "{temperature} {unit} Leichter Regen",
- "{temperature} {unit} rain later today" : "{temperature} {unit} Regen später am Tag",
- "{temperature} {unit} rain" : "{temperature} {unit} Regen",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} Starker Regen später am Tag",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} Starker Regen",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} Regenschauer später am Tag",
- "{temperature} {unit} rain showers" : "{temperature} {unit} Regenschauer",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} Leichte Regenschauer später am Tag",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} Leichte Regenschauer",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} Starke Regenschauer später am Tag",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} Starke Regenschauer",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} Leichter Regen später am Tag",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} Leichter Regen",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} Regen später am Tag",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} Regen",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} Starker Regen später am Tag",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} Starker Regen",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} Regenschauer später am Tag",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} Regenschauer",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} Leichte Regenschauer später am Tag",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} Leichte Regenschauer",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} Starke Regenschauer später am Tag",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} Starke Regenschauer",
"More weather for {adr}" : "Mehr Wetter für {adr}",
"Loading weather" : "Lade Wetter",
"Remove from favorites" : "Von Favoriten entfernen",
diff --git a/apps/weather_status/l10n/es.js b/apps/weather_status/l10n/es.js
index edd765ee761..b55511b8a8d 100644
--- a/apps/weather_status/l10n/es.js
+++ b/apps/weather_status/l10n/es.js
@@ -16,12 +16,6 @@ OC.L10N.register(
"{temperature} {unit} fair weather" : "{temperature} {unit} Buen día",
"{temperature} {unit} partly cloudy" : "{temperature} {unit} Parcialmente nublado",
"{temperature} {unit} foggy" : "{temperature} {unit} Con brumas",
- "{temperature} {unit} light rain" : "{temperature} {unit} Lluvia ligera",
- "{temperature} {unit} rain" : "{temperature} {unit} Lluvia",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} Lluvia intensa",
- "{temperature} {unit} rain showers" : "{temperature} {unit} Chubascos",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} Chubascos ligeros",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} Chubascos intensos",
"More weather for {adr}" : "Más previsiones para {adr}",
"Loading weather" : "Cargando previsión del tiempo",
"Remove from favorites" : "Quitar de favoritos",
diff --git a/apps/weather_status/l10n/es.json b/apps/weather_status/l10n/es.json
index ad1ab61657a..865fd17405d 100644
--- a/apps/weather_status/l10n/es.json
+++ b/apps/weather_status/l10n/es.json
@@ -14,12 +14,6 @@
"{temperature} {unit} fair weather" : "{temperature} {unit} Buen día",
"{temperature} {unit} partly cloudy" : "{temperature} {unit} Parcialmente nublado",
"{temperature} {unit} foggy" : "{temperature} {unit} Con brumas",
- "{temperature} {unit} light rain" : "{temperature} {unit} Lluvia ligera",
- "{temperature} {unit} rain" : "{temperature} {unit} Lluvia",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} Lluvia intensa",
- "{temperature} {unit} rain showers" : "{temperature} {unit} Chubascos",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} Chubascos ligeros",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} Chubascos intensos",
"More weather for {adr}" : "Más previsiones para {adr}",
"Loading weather" : "Cargando previsión del tiempo",
"Remove from favorites" : "Quitar de favoritos",
diff --git a/apps/weather_status/l10n/eu.js b/apps/weather_status/l10n/eu.js
index 2cc5a161d7f..cffdb9d1a5e 100644
--- a/apps/weather_status/l10n/eu.js
+++ b/apps/weather_status/l10n/eu.js
@@ -21,18 +21,6 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} hodei-tarteak",
"{temperature} {unit} foggy later today" : "{temperature} {unit} lainotu egingo da geroago",
"{temperature} {unit} foggy" : "{temperature} {unit} lainotsu",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} zirimiria egingo du geroago",
- "{temperature} {unit} light rain" : "{temperature} {unit} zirimiria",
- "{temperature} {unit} rain later today" : "{temperature} {unit} euria egingo du geroago",
- "{temperature} {unit} rain" : "{temperature} {unit} euria",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} euri-jasa egingo du geroago",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} euri-jasa",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} zaparradak egongo dira geroago",
- "{temperature} {unit} rain showers" : "{temperature} {unit} zaparradak",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} zaparrada arinak geroago",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} zaparrada arinak",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} zaparrada handiak geroago",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} zaparrada handiak",
"More weather for {adr}" : "Eguraldi gehiago {adr}-(e)rako",
"Loading weather" : "Eguraldia kargatzen",
"Remove from favorites" : "Kendu gogokoetatik",
diff --git a/apps/weather_status/l10n/eu.json b/apps/weather_status/l10n/eu.json
index 5b9846a2cad..091def3710b 100644
--- a/apps/weather_status/l10n/eu.json
+++ b/apps/weather_status/l10n/eu.json
@@ -19,18 +19,6 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} hodei-tarteak",
"{temperature} {unit} foggy later today" : "{temperature} {unit} lainotu egingo da geroago",
"{temperature} {unit} foggy" : "{temperature} {unit} lainotsu",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} zirimiria egingo du geroago",
- "{temperature} {unit} light rain" : "{temperature} {unit} zirimiria",
- "{temperature} {unit} rain later today" : "{temperature} {unit} euria egingo du geroago",
- "{temperature} {unit} rain" : "{temperature} {unit} euria",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} euri-jasa egingo du geroago",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} euri-jasa",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} zaparradak egongo dira geroago",
- "{temperature} {unit} rain showers" : "{temperature} {unit} zaparradak",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} zaparrada arinak geroago",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} zaparrada arinak",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} zaparrada handiak geroago",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} zaparrada handiak",
"More weather for {adr}" : "Eguraldi gehiago {adr}-(e)rako",
"Loading weather" : "Eguraldia kargatzen",
"Remove from favorites" : "Kendu gogokoetatik",
diff --git a/apps/weather_status/l10n/fr.js b/apps/weather_status/l10n/fr.js
index 5436e89f6d4..2d6500f1890 100644
--- a/apps/weather_status/l10n/fr.js
+++ b/apps/weather_status/l10n/fr.js
@@ -21,18 +21,6 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} Partiellement nuageux",
"{temperature} {unit} foggy later today" : "{temperature} {unit} Brouillard dans la journée",
"{temperature} {unit} foggy" : "{temperature} {unit} Brouillard",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} Pluie faible dans la journée",
- "{temperature} {unit} light rain" : "{temperature} {unit} Pluie faible",
- "{temperature} {unit} rain later today" : "{temperature} {unit} Pluie dans la journée",
- "{temperature} {unit} rain" : "{temperature} {unit} Pluie",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} Fortes pluies dans la journée",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} Fortes pluies",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} Averses dans la journée",
- "{temperature} {unit} rain showers" : "{temperature} {unit} Averses",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} Faibles averses dans la journée",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} Faibles averses",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} Fortes averses dans la journée",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} Fortes averses",
"More weather for {adr}" : "Plus de météo pour {adr}",
"Loading weather" : "Chargement de la météo",
"Remove from favorites" : "Retirer des favoris",
diff --git a/apps/weather_status/l10n/fr.json b/apps/weather_status/l10n/fr.json
index 96d8a674407..f655d207345 100644
--- a/apps/weather_status/l10n/fr.json
+++ b/apps/weather_status/l10n/fr.json
@@ -19,18 +19,6 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} Partiellement nuageux",
"{temperature} {unit} foggy later today" : "{temperature} {unit} Brouillard dans la journée",
"{temperature} {unit} foggy" : "{temperature} {unit} Brouillard",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} Pluie faible dans la journée",
- "{temperature} {unit} light rain" : "{temperature} {unit} Pluie faible",
- "{temperature} {unit} rain later today" : "{temperature} {unit} Pluie dans la journée",
- "{temperature} {unit} rain" : "{temperature} {unit} Pluie",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} Fortes pluies dans la journée",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} Fortes pluies",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} Averses dans la journée",
- "{temperature} {unit} rain showers" : "{temperature} {unit} Averses",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} Faibles averses dans la journée",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} Faibles averses",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} Fortes averses dans la journée",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} Fortes averses",
"More weather for {adr}" : "Plus de météo pour {adr}",
"Loading weather" : "Chargement de la météo",
"Remove from favorites" : "Retirer des favoris",
diff --git a/apps/weather_status/l10n/hu.js b/apps/weather_status/l10n/hu.js
index bd551b2151d..e7e91961742 100644
--- a/apps/weather_status/l10n/hu.js
+++ b/apps/weather_status/l10n/hu.js
@@ -15,11 +15,6 @@ OC.L10N.register(
"{temperature} {unit} cloudy" : "{temperature} {unit} felhős",
"{temperature} {unit} partly cloudy" : "{temperature} {unit} részben felhős",
"{temperature} {unit} foggy" : "{temperature} {unit} ködös",
- "{temperature} {unit} light rain" : "{temperature} {unit} gyenge eső",
- "{temperature} {unit} rain" : "{temperature} {unit} eső",
- "{temperature} {unit} rain showers" : "{temperature} {unit} záporok",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} enyhe záporok",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} erős záporok",
"More weather for {adr}" : "További időjárás a {adr} címhez",
"Loading weather" : "Időjárás betöltése",
"Remove from favorites" : "Eltávolítás a kedvencekből",
diff --git a/apps/weather_status/l10n/hu.json b/apps/weather_status/l10n/hu.json
index 1564b08b93f..c686250700b 100644
--- a/apps/weather_status/l10n/hu.json
+++ b/apps/weather_status/l10n/hu.json
@@ -13,11 +13,6 @@
"{temperature} {unit} cloudy" : "{temperature} {unit} felhős",
"{temperature} {unit} partly cloudy" : "{temperature} {unit} részben felhős",
"{temperature} {unit} foggy" : "{temperature} {unit} ködös",
- "{temperature} {unit} light rain" : "{temperature} {unit} gyenge eső",
- "{temperature} {unit} rain" : "{temperature} {unit} eső",
- "{temperature} {unit} rain showers" : "{temperature} {unit} záporok",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} enyhe záporok",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} erős záporok",
"More weather for {adr}" : "További időjárás a {adr} címhez",
"Loading weather" : "Időjárás betöltése",
"Remove from favorites" : "Eltávolítás a kedvencekből",
diff --git a/apps/weather_status/l10n/it.js b/apps/weather_status/l10n/it.js
index db1af4e70ed..373ff88dcdd 100644
--- a/apps/weather_status/l10n/it.js
+++ b/apps/weather_status/l10n/it.js
@@ -21,18 +21,6 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} parzialmente nuvoloso",
"{temperature} {unit} foggy later today" : "{temperature} {unit} nebbioso più tardi in giornata",
"{temperature} {unit} foggy" : "{temperature} {unit} nebbioso",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} pioggia leggera più tardi in giornata",
- "{temperature} {unit} light rain" : "{temperature} {unit} pioggia leggera",
- "{temperature} {unit} rain later today" : "{temperature} {unit} pioggia più tardi in giornata",
- "{temperature} {unit} rain" : "{temperature} {unit} pioggia più tardi in giornata",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} pioggia intensa più tardi in giornata",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} pioggia intensa",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} pioggia sparsa più tardi in giornata",
- "{temperature} {unit} rain showers" : "{temperature} {unit} pioggia sparsa",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} pioggia leggera sparsa più tardi in giornata",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} pioggia leggera sparsa",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} pioggia intensa sparsa più tardi in giornata",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} pioggia intensa sparsa",
"More weather for {adr}" : "Altro meteo per {adr}",
"Loading weather" : "Caricamento meteo",
"Remove from favorites" : "Rimuovi dai preferiti",
diff --git a/apps/weather_status/l10n/it.json b/apps/weather_status/l10n/it.json
index 3c008d706d0..1f55c6fbb38 100644
--- a/apps/weather_status/l10n/it.json
+++ b/apps/weather_status/l10n/it.json
@@ -19,18 +19,6 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} parzialmente nuvoloso",
"{temperature} {unit} foggy later today" : "{temperature} {unit} nebbioso più tardi in giornata",
"{temperature} {unit} foggy" : "{temperature} {unit} nebbioso",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} pioggia leggera più tardi in giornata",
- "{temperature} {unit} light rain" : "{temperature} {unit} pioggia leggera",
- "{temperature} {unit} rain later today" : "{temperature} {unit} pioggia più tardi in giornata",
- "{temperature} {unit} rain" : "{temperature} {unit} pioggia più tardi in giornata",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} pioggia intensa più tardi in giornata",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} pioggia intensa",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} pioggia sparsa più tardi in giornata",
- "{temperature} {unit} rain showers" : "{temperature} {unit} pioggia sparsa",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} pioggia leggera sparsa più tardi in giornata",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} pioggia leggera sparsa",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} pioggia intensa sparsa più tardi in giornata",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} pioggia intensa sparsa",
"More weather for {adr}" : "Altro meteo per {adr}",
"Loading weather" : "Caricamento meteo",
"Remove from favorites" : "Rimuovi dai preferiti",
diff --git a/apps/weather_status/l10n/nl.js b/apps/weather_status/l10n/nl.js
index 01b708b4030..2975242ed30 100644
--- a/apps/weather_status/l10n/nl.js
+++ b/apps/weather_status/l10n/nl.js
@@ -19,18 +19,6 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} half bewolkt",
"{temperature} {unit} foggy later today" : "{temperature} {unit} mistig later vandaag",
"{temperature} {unit} foggy" : "{temperature} {unit} mistig",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} lichte regen later vandaag",
- "{temperature} {unit} light rain" : "{temperature} {unit} lichte regen",
- "{temperature} {unit} rain later today" : "{temperature} {unit} regen later vandaag",
- "{temperature} {unit} rain" : "{temperature} {unit} regen",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} zware regen later vandaag",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} zware regen",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} regenbuien later vandaag",
- "{temperature} {unit} rain showers" : "{temperature} {unit} regenbuien",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} lichte regenbuien later vandaag",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} lichte regenbuien",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} zware regenbuien later vandaag",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} zware regenbuien",
"More weather for {adr}" : "Meer weer voor {adr}",
"Loading weather" : "Weergegevens ophalen",
"Remove from favorites" : "Verwijderen uit favorieten",
diff --git a/apps/weather_status/l10n/nl.json b/apps/weather_status/l10n/nl.json
index dc84f6ad32d..623d058cf40 100644
--- a/apps/weather_status/l10n/nl.json
+++ b/apps/weather_status/l10n/nl.json
@@ -17,18 +17,6 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} half bewolkt",
"{temperature} {unit} foggy later today" : "{temperature} {unit} mistig later vandaag",
"{temperature} {unit} foggy" : "{temperature} {unit} mistig",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} lichte regen later vandaag",
- "{temperature} {unit} light rain" : "{temperature} {unit} lichte regen",
- "{temperature} {unit} rain later today" : "{temperature} {unit} regen later vandaag",
- "{temperature} {unit} rain" : "{temperature} {unit} regen",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} zware regen later vandaag",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} zware regen",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} regenbuien later vandaag",
- "{temperature} {unit} rain showers" : "{temperature} {unit} regenbuien",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} lichte regenbuien later vandaag",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} lichte regenbuien",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} zware regenbuien later vandaag",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} zware regenbuien",
"More weather for {adr}" : "Meer weer voor {adr}",
"Loading weather" : "Weergegevens ophalen",
"Remove from favorites" : "Verwijderen uit favorieten",
diff --git a/apps/weather_status/l10n/pl.js b/apps/weather_status/l10n/pl.js
index e619159de5c..02f2e6756bb 100644
--- a/apps/weather_status/l10n/pl.js
+++ b/apps/weather_status/l10n/pl.js
@@ -21,18 +21,18 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} częściowe zachmurzenie",
"{temperature} {unit} foggy later today" : "{temperature} {unit} mgła później dzisiaj",
"{temperature} {unit} foggy" : "{temperature} {unit} mgła",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} lekkie opady deszczu później dzisiaj",
- "{temperature} {unit} light rain" : "{temperature} {unit} lekkie opady deszczu",
- "{temperature} {unit} rain later today" : "{temperature} {unit} opady deszczu później dzisiaj",
- "{temperature} {unit} rain" : "{temperature} {unit} opady deszczu",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} ulewne opady deszczu później dzisiaj",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} ulewne opady deszczu",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} przelotne opady deszczu później dzisiaj",
- "{temperature} {unit} rain showers" : "{temperature} {unit} przelotne opady deszczu",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} lekkie przelotne opady deszczu później dzisiaj",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} lekkie przelotne opady deszczu",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} obfite opady deszczu później dzisiaj",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} ulewne opady deszczu",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} lekkie opady deszczu później dzisiaj",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} lekkie opady deszczu",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} opady deszczu później dzisiaj",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} opady deszczu",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} ulewne opady deszczu później dzisiaj",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} ulewne opady deszczu",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} przelotne opady deszczu później dzisiaj",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} przelotne opady deszczu",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} lekkie przelotne opady deszczu później dzisiaj",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} lekkie przelotne opady deszczu",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} obfite opady deszczu później dzisiaj",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} ulewne opady deszczu",
"More weather for {adr}" : "Więcej pogody dla {adr}",
"Loading weather" : "Wczytywanie pogody",
"Remove from favorites" : "Usuń z ulubionych",
diff --git a/apps/weather_status/l10n/pl.json b/apps/weather_status/l10n/pl.json
index 7828ddc1700..5cebe9bcf35 100644
--- a/apps/weather_status/l10n/pl.json
+++ b/apps/weather_status/l10n/pl.json
@@ -19,18 +19,18 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} częściowe zachmurzenie",
"{temperature} {unit} foggy later today" : "{temperature} {unit} mgła później dzisiaj",
"{temperature} {unit} foggy" : "{temperature} {unit} mgła",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} lekkie opady deszczu później dzisiaj",
- "{temperature} {unit} light rain" : "{temperature} {unit} lekkie opady deszczu",
- "{temperature} {unit} rain later today" : "{temperature} {unit} opady deszczu później dzisiaj",
- "{temperature} {unit} rain" : "{temperature} {unit} opady deszczu",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} ulewne opady deszczu później dzisiaj",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} ulewne opady deszczu",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} przelotne opady deszczu później dzisiaj",
- "{temperature} {unit} rain showers" : "{temperature} {unit} przelotne opady deszczu",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} lekkie przelotne opady deszczu później dzisiaj",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} lekkie przelotne opady deszczu",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} obfite opady deszczu później dzisiaj",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} ulewne opady deszczu",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} lekkie opady deszczu później dzisiaj",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} lekkie opady deszczu",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} opady deszczu później dzisiaj",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} opady deszczu",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} ulewne opady deszczu później dzisiaj",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} ulewne opady deszczu",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} przelotne opady deszczu później dzisiaj",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} przelotne opady deszczu",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} lekkie przelotne opady deszczu później dzisiaj",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} lekkie przelotne opady deszczu",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} obfite opady deszczu później dzisiaj",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} ulewne opady deszczu",
"More weather for {adr}" : "Więcej pogody dla {adr}",
"Loading weather" : "Wczytywanie pogody",
"Remove from favorites" : "Usuń z ulubionych",
diff --git a/apps/weather_status/l10n/pt_BR.js b/apps/weather_status/l10n/pt_BR.js
index 2264fcf13b4..13cd94c425b 100644
--- a/apps/weather_status/l10n/pt_BR.js
+++ b/apps/weather_status/l10n/pt_BR.js
@@ -21,18 +21,6 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} parcialmente nublado",
"{temperature} {unit} foggy later today" : "{temperature} {unit} nevoeiro mais tarde hoje",
"{temperature} {unit} foggy" : "{temperature} {unit} nevoeiro",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} chuva leve mais tarde hoje",
- "{temperature} {unit} light rain" : "{temperature} {unit} chuva leve",
- "{temperature} {unit} rain later today" : "{temperature} {unit} chuva mais tarde hoje",
- "{temperature} {unit} rain" : "{temperature} {unit} chuva",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} chuva forte mais tarde hoje",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} chuva forte",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} pancadas de chuva mais tarde hoje",
- "{temperature} {unit} rain showers" : "{temperature} {unit} pancadas de chuva",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} pancadas de chuva fracas mais tarde hoje",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} pancadas de chuva leve",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} pancadas de chuva forte hoje mais tarde",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} pancadas de chuvas fortes",
"More weather for {adr}" : "Ver mais Tempo para {adr}",
"Loading weather" : "Carregando Tempo",
"Remove from favorites" : "Remover dos favoritos",
diff --git a/apps/weather_status/l10n/pt_BR.json b/apps/weather_status/l10n/pt_BR.json
index b93f1765032..f8624fb6e48 100644
--- a/apps/weather_status/l10n/pt_BR.json
+++ b/apps/weather_status/l10n/pt_BR.json
@@ -19,18 +19,6 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} parcialmente nublado",
"{temperature} {unit} foggy later today" : "{temperature} {unit} nevoeiro mais tarde hoje",
"{temperature} {unit} foggy" : "{temperature} {unit} nevoeiro",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} chuva leve mais tarde hoje",
- "{temperature} {unit} light rain" : "{temperature} {unit} chuva leve",
- "{temperature} {unit} rain later today" : "{temperature} {unit} chuva mais tarde hoje",
- "{temperature} {unit} rain" : "{temperature} {unit} chuva",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} chuva forte mais tarde hoje",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} chuva forte",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} pancadas de chuva mais tarde hoje",
- "{temperature} {unit} rain showers" : "{temperature} {unit} pancadas de chuva",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} pancadas de chuva fracas mais tarde hoje",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} pancadas de chuva leve",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} pancadas de chuva forte hoje mais tarde",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} pancadas de chuvas fortes",
"More weather for {adr}" : "Ver mais Tempo para {adr}",
"Loading weather" : "Carregando Tempo",
"Remove from favorites" : "Remover dos favoritos",
diff --git a/apps/weather_status/l10n/ru.js b/apps/weather_status/l10n/ru.js
index e4e0881dc77..d10d7b9d060 100644
--- a/apps/weather_status/l10n/ru.js
+++ b/apps/weather_status/l10n/ru.js
@@ -21,18 +21,6 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} местами облачно",
"{temperature} {unit} foggy later today" : "{temperature} {unit} сегодня обещают туман",
"{temperature} {unit} foggy" : "{temperature} {unit} туман",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} сегодня обещают небольшой дождь",
- "{temperature} {unit} light rain" : "{temperature} {unit} идёт небольшой дождь",
- "{temperature} {unit} rain later today" : "{temperature} {unit} сегодня обещают дождь",
- "{temperature} {unit} rain" : "{temperature} {unit} идёт дождь",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} сегодня обещают сильный дождь",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} идёт сильный дождь",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} сегодня обещают мокрый снег",
- "{temperature} {unit} rain showers" : "{temperature} {unit} идёт мокрый снег",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} сегодня обещают снег с дождём",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} идёт снег с дождём ",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} сегодня обещают сильный снег с дождём ",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} идёт сильный снег с дождём ",
"More weather for {adr}" : "Дополнительные сведения о погоде в {adr}",
"Loading weather" : "Получение сведений о погоде...",
"Remove from favorites" : "Удалить из избранного",
diff --git a/apps/weather_status/l10n/ru.json b/apps/weather_status/l10n/ru.json
index 4427e54cb77..39b946c8330 100644
--- a/apps/weather_status/l10n/ru.json
+++ b/apps/weather_status/l10n/ru.json
@@ -19,18 +19,6 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} местами облачно",
"{temperature} {unit} foggy later today" : "{temperature} {unit} сегодня обещают туман",
"{temperature} {unit} foggy" : "{temperature} {unit} туман",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} сегодня обещают небольшой дождь",
- "{temperature} {unit} light rain" : "{temperature} {unit} идёт небольшой дождь",
- "{temperature} {unit} rain later today" : "{temperature} {unit} сегодня обещают дождь",
- "{temperature} {unit} rain" : "{temperature} {unit} идёт дождь",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} сегодня обещают сильный дождь",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} идёт сильный дождь",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} сегодня обещают мокрый снег",
- "{temperature} {unit} rain showers" : "{temperature} {unit} идёт мокрый снег",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} сегодня обещают снег с дождём",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} идёт снег с дождём ",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} сегодня обещают сильный снег с дождём ",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} идёт сильный снег с дождём ",
"More weather for {adr}" : "Дополнительные сведения о погоде в {adr}",
"Loading weather" : "Получение сведений о погоде...",
"Remove from favorites" : "Удалить из избранного",
diff --git a/apps/weather_status/l10n/sk.js b/apps/weather_status/l10n/sk.js
index a867a83c6f0..115e2e29ea1 100644
--- a/apps/weather_status/l10n/sk.js
+++ b/apps/weather_status/l10n/sk.js
@@ -21,18 +21,6 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} čiastočne zamračené",
"{temperature} {unit} foggy later today" : "{temperature} {unit} hmlisto, neskôr v priebehu dňa",
"{temperature} {unit} foggy" : "{temperature} {unit} hmlisto",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} slabý dážď, neskôr v priebehu dňa",
- "{temperature} {unit} light rain" : "{temperature} {unit} ľahký dážď",
- "{temperature} {unit} rain later today" : "{temperature} {unit} dážď, neskôr v priebehu dňa",
- "{temperature} {unit} rain" : "{temperature} {unit} dážď",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} silný dážď, neskôr v priebehu dňa",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} silný dážď",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} dažďové prehánky, neskôr v priebehu dňa",
- "{temperature} {unit} rain showers" : "{temperature} {unit} dažďové prehánky",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} ľahké dažďové prehánky, neskôr v priebehu dňa",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} ľahké dažďové prehánky",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} silné dažďové prehánky, neskôr v priebehu dňa",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} silné dažďové prehánky",
"More weather for {adr}" : "Viac o počasí pre {adr}",
"Loading weather" : "Načítava sa počasie",
"Remove from favorites" : "Odstrániť z obľúbených",
diff --git a/apps/weather_status/l10n/sk.json b/apps/weather_status/l10n/sk.json
index 03fe899a901..bb48b57283c 100644
--- a/apps/weather_status/l10n/sk.json
+++ b/apps/weather_status/l10n/sk.json
@@ -19,18 +19,6 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} čiastočne zamračené",
"{temperature} {unit} foggy later today" : "{temperature} {unit} hmlisto, neskôr v priebehu dňa",
"{temperature} {unit} foggy" : "{temperature} {unit} hmlisto",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} slabý dážď, neskôr v priebehu dňa",
- "{temperature} {unit} light rain" : "{temperature} {unit} ľahký dážď",
- "{temperature} {unit} rain later today" : "{temperature} {unit} dážď, neskôr v priebehu dňa",
- "{temperature} {unit} rain" : "{temperature} {unit} dážď",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} silný dážď, neskôr v priebehu dňa",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} silný dážď",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} dažďové prehánky, neskôr v priebehu dňa",
- "{temperature} {unit} rain showers" : "{temperature} {unit} dažďové prehánky",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} ľahké dažďové prehánky, neskôr v priebehu dňa",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} ľahké dažďové prehánky",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} silné dažďové prehánky, neskôr v priebehu dňa",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} silné dažďové prehánky",
"More weather for {adr}" : "Viac o počasí pre {adr}",
"Loading weather" : "Načítava sa počasie",
"Remove from favorites" : "Odstrániť z obľúbených",
diff --git a/apps/weather_status/l10n/sv.js b/apps/weather_status/l10n/sv.js
index afc5f2a06aa..c1ac235072b 100644
--- a/apps/weather_status/l10n/sv.js
+++ b/apps/weather_status/l10n/sv.js
@@ -21,18 +21,6 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} och växlande molnighet",
"{temperature} {unit} foggy later today" : "{temperature} {unit} och dimma senare idag",
"{temperature} {unit} foggy" : "{temperature} {unit} och dimma",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} och lätt regn senare idag",
- "{temperature} {unit} light rain" : "{temperature} {unit} och lätt regn",
- "{temperature} {unit} rain later today" : "{temperature} {unit} och regn senare idag",
- "{temperature} {unit} rain" : "{temperature} {unit} och regn",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} och kraftigt regn senare idag",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} och kraftigt regn",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} och regnbyar senare idag",
- "{temperature} {unit} rain showers" : "{temperature} {unit} och regnbyar",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} och lätta regnbyar senare idag",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} och lätta regnbyar",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} och kraftiga regnbyar senare idag",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} och kraftiga regnbyar",
"More weather for {adr}" : "Mer väder omkring {adr}",
"Loading weather" : "Hämtar väder",
"Remove from favorites" : "Ta bort från favoriter",
diff --git a/apps/weather_status/l10n/sv.json b/apps/weather_status/l10n/sv.json
index 6f4373eab50..61f309c3a60 100644
--- a/apps/weather_status/l10n/sv.json
+++ b/apps/weather_status/l10n/sv.json
@@ -19,18 +19,6 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} och växlande molnighet",
"{temperature} {unit} foggy later today" : "{temperature} {unit} och dimma senare idag",
"{temperature} {unit} foggy" : "{temperature} {unit} och dimma",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} och lätt regn senare idag",
- "{temperature} {unit} light rain" : "{temperature} {unit} och lätt regn",
- "{temperature} {unit} rain later today" : "{temperature} {unit} och regn senare idag",
- "{temperature} {unit} rain" : "{temperature} {unit} och regn",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} och kraftigt regn senare idag",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} och kraftigt regn",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} och regnbyar senare idag",
- "{temperature} {unit} rain showers" : "{temperature} {unit} och regnbyar",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} och lätta regnbyar senare idag",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} och lätta regnbyar",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} och kraftiga regnbyar senare idag",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} och kraftiga regnbyar",
"More weather for {adr}" : "Mer väder omkring {adr}",
"Loading weather" : "Hämtar väder",
"Remove from favorites" : "Ta bort från favoriter",
diff --git a/apps/weather_status/l10n/tr.js b/apps/weather_status/l10n/tr.js
index b04a359e885..57dcf479c0a 100644
--- a/apps/weather_status/l10n/tr.js
+++ b/apps/weather_status/l10n/tr.js
@@ -21,21 +21,21 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} parçalı bulutlu",
"{temperature} {unit} foggy later today" : "{temperature} {unit} bugün sisli",
"{temperature} {unit} foggy" : "{temperature} {unit} sisli",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} bugün hafif yağmurlu",
- "{temperature} {unit} light rain" : "{temperature} {unit} hafif yağmurlu",
- "{temperature} {unit} rain later today" : "{temperature} {unit} bugün yağmurlu",
- "{temperature} {unit} rain" : "{temperature} {unit} yağmurlu",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} bugün yoğun yağmurlu",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} yoğun yağmurlu",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} bugün sağanak yağışlı",
- "{temperature} {unit} rain showers" : "{temperature} {unit} sağanak yağışlı",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} bugün hafif sağanak yağışlı",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} hafif sağanak yağışlı",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} bugün ağır sağanak yağışlı",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} ağır sağanak yağışlı",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} bugün hafif yağmurlu",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} hafif yağmurlu",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} bugün hafif yağmurlu",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} yağmurlu",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} bugün şiddetli yağmurlu",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} şiddetli yağmurlu",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} bugün sağanak yağışlı",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} sağanak yağışlı",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} bugün hafif sağanak yağışlı",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} hafif sağanak yağışlı",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} bugün şiddetli sağanak yağışlı",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} şiddetli sağanak yağışlı",
"More weather for {adr}" : "{adr} için geniş hava durumu",
"Loading weather" : "Hava durumu yükleniyor",
- "Remove from favorites" : "Sık kullanılanlardan çıkar",
+ "Remove from favorites" : "Sık kullanılanlardan kaldır",
"Add as favorite" : "Sık kullanılanlara ekle",
"You are not logged in." : "Oturum açmamışsınız.",
"There was an error getting the weather status information." : "Hava durumu bilgileri alınırken bir sorun çıktı.",
@@ -54,9 +54,9 @@ OC.L10N.register(
"{temperature} {unit} Foggy at {time}" : "{temperature} {unit} Sisli {time}",
"{temperature} {unit} Light rain at {time}" : "{temperature} {unit} Hafif yağışlı {time}",
"{temperature} {unit} Rain at {time}" : "{temperature} {unit} Yağışlı {time}",
- "{temperature} {unit} Heavy rain at {time}" : "{temperature} {unit} Ağır yağışlı {time}",
+ "{temperature} {unit} Heavy rain at {time}" : "{temperature} {unit} şiddetli yağmur {time}",
"{temperature} {unit} Rain showers at {time}" : "{temperature} {unit} Sağanak yağış {time}",
"{temperature} {unit} Light rain showers at {time}" : "{temperature} {unit} Hafif sağnak {time}",
- "{temperature} {unit} Heavy rain showers at {time}" : "{temperature} {unit} Ağır sağnak {time}"
+ "{temperature} {unit} Heavy rain showers at {time}" : "{temperature} {unit} şiddetli sağanak yağış {time}"
},
"nplurals=2; plural=(n > 1);");
diff --git a/apps/weather_status/l10n/tr.json b/apps/weather_status/l10n/tr.json
index e0b0d908b16..9acde1dddab 100644
--- a/apps/weather_status/l10n/tr.json
+++ b/apps/weather_status/l10n/tr.json
@@ -19,21 +19,21 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} parçalı bulutlu",
"{temperature} {unit} foggy later today" : "{temperature} {unit} bugün sisli",
"{temperature} {unit} foggy" : "{temperature} {unit} sisli",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} bugün hafif yağmurlu",
- "{temperature} {unit} light rain" : "{temperature} {unit} hafif yağmurlu",
- "{temperature} {unit} rain later today" : "{temperature} {unit} bugün yağmurlu",
- "{temperature} {unit} rain" : "{temperature} {unit} yağmurlu",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} bugün yoğun yağmurlu",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} yoğun yağmurlu",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} bugün sağanak yağışlı",
- "{temperature} {unit} rain showers" : "{temperature} {unit} sağanak yağışlı",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} bugün hafif sağanak yağışlı",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} hafif sağanak yağışlı",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} bugün ağır sağanak yağışlı",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} ağır sağanak yağışlı",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} bugün hafif yağmurlu",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} hafif yağmurlu",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} bugün hafif yağmurlu",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} yağmurlu",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} bugün şiddetli yağmurlu",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} şiddetli yağmurlu",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} bugün sağanak yağışlı",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} sağanak yağışlı",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} bugün hafif sağanak yağışlı",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} hafif sağanak yağışlı",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} bugün şiddetli sağanak yağışlı",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} şiddetli sağanak yağışlı",
"More weather for {adr}" : "{adr} için geniş hava durumu",
"Loading weather" : "Hava durumu yükleniyor",
- "Remove from favorites" : "Sık kullanılanlardan çıkar",
+ "Remove from favorites" : "Sık kullanılanlardan kaldır",
"Add as favorite" : "Sık kullanılanlara ekle",
"You are not logged in." : "Oturum açmamışsınız.",
"There was an error getting the weather status information." : "Hava durumu bilgileri alınırken bir sorun çıktı.",
@@ -52,9 +52,9 @@
"{temperature} {unit} Foggy at {time}" : "{temperature} {unit} Sisli {time}",
"{temperature} {unit} Light rain at {time}" : "{temperature} {unit} Hafif yağışlı {time}",
"{temperature} {unit} Rain at {time}" : "{temperature} {unit} Yağışlı {time}",
- "{temperature} {unit} Heavy rain at {time}" : "{temperature} {unit} Ağır yağışlı {time}",
+ "{temperature} {unit} Heavy rain at {time}" : "{temperature} {unit} şiddetli yağmur {time}",
"{temperature} {unit} Rain showers at {time}" : "{temperature} {unit} Sağanak yağış {time}",
"{temperature} {unit} Light rain showers at {time}" : "{temperature} {unit} Hafif sağnak {time}",
- "{temperature} {unit} Heavy rain showers at {time}" : "{temperature} {unit} Ağır sağnak {time}"
+ "{temperature} {unit} Heavy rain showers at {time}" : "{temperature} {unit} şiddetli sağanak yağış {time}"
},"pluralForm" :"nplurals=2; plural=(n > 1);"
} \ No newline at end of file
diff --git a/apps/weather_status/l10n/zh_CN.js b/apps/weather_status/l10n/zh_CN.js
index 7c40c338a4c..2e91ad2b902 100644
--- a/apps/weather_status/l10n/zh_CN.js
+++ b/apps/weather_status/l10n/zh_CN.js
@@ -21,18 +21,6 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit}局部多云",
"{temperature} {unit} foggy later today" : "今日晚些时候{temperature} {unit}有雾",
"{temperature} {unit} foggy" : "{temperature} {unit}雾",
- "{temperature} {unit} light rain later today" : "今日晚些时候{temperature} {unit}小雨",
- "{temperature} {unit} light rain" : "{temperature} {unit}小雨",
- "{temperature} {unit} rain later today" : "今日晚些时候{temperature} {unit}有雨",
- "{temperature} {unit} rain" : "{temperature} {unit}下雨",
- "{temperature} {unit} heavy rain later today" : "今日晚些时候{temperature} {unit}大雨",
- "{temperature} {unit} heavy rain" : "{temperature} {unit}大雨",
- "{temperature} {unit} rain showers later today" : "今日晚些时候{temperature} {unit}有阵雨",
- "{temperature} {unit} rain showers" : "{temperature} {unit}阵雨",
- "{temperature} {unit} light rain showers later today" : "今日晚些时候{temperature} {unit}零星小雨",
- "{temperature} {unit} light rain showers" : "{temperature} {unit}零星小雨",
- "{temperature} {unit} heavy rain showers later today" : "今日晚先时候{temperature} {unit}有滂沱阵雨",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit}滂沱阵雨",
"More weather for {adr}" : "{adr} 的更多天气信息",
"Loading weather" : "正在加载天气",
"Remove from favorites" : "从收藏夹移除",
diff --git a/apps/weather_status/l10n/zh_CN.json b/apps/weather_status/l10n/zh_CN.json
index bf90e6cd500..d2bc40e4cd4 100644
--- a/apps/weather_status/l10n/zh_CN.json
+++ b/apps/weather_status/l10n/zh_CN.json
@@ -19,18 +19,6 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit}局部多云",
"{temperature} {unit} foggy later today" : "今日晚些时候{temperature} {unit}有雾",
"{temperature} {unit} foggy" : "{temperature} {unit}雾",
- "{temperature} {unit} light rain later today" : "今日晚些时候{temperature} {unit}小雨",
- "{temperature} {unit} light rain" : "{temperature} {unit}小雨",
- "{temperature} {unit} rain later today" : "今日晚些时候{temperature} {unit}有雨",
- "{temperature} {unit} rain" : "{temperature} {unit}下雨",
- "{temperature} {unit} heavy rain later today" : "今日晚些时候{temperature} {unit}大雨",
- "{temperature} {unit} heavy rain" : "{temperature} {unit}大雨",
- "{temperature} {unit} rain showers later today" : "今日晚些时候{temperature} {unit}有阵雨",
- "{temperature} {unit} rain showers" : "{temperature} {unit}阵雨",
- "{temperature} {unit} light rain showers later today" : "今日晚些时候{temperature} {unit}零星小雨",
- "{temperature} {unit} light rain showers" : "{temperature} {unit}零星小雨",
- "{temperature} {unit} heavy rain showers later today" : "今日晚先时候{temperature} {unit}有滂沱阵雨",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit}滂沱阵雨",
"More weather for {adr}" : "{adr} 的更多天气信息",
"Loading weather" : "正在加载天气",
"Remove from favorites" : "从收藏夹移除",
diff --git a/apps/weather_status/l10n/zh_HK.js b/apps/weather_status/l10n/zh_HK.js
index fa415dbd6ba..55b7be28ade 100644
--- a/apps/weather_status/l10n/zh_HK.js
+++ b/apps/weather_status/l10n/zh_HK.js
@@ -21,18 +21,18 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} 局部密雲",
"{temperature} {unit} foggy later today" : "{temperature} {unit} 今天稍後有霧",
"{temperature} {unit} foggy" : "{temperature} {unit} 有霧",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} 天稍後有微雨",
- "{temperature} {unit} light rain" : "{temperature} {unit} 微雨",
- "{temperature} {unit} rain later today" : "{temperature} {unit} 今天稍後有雨",
- "{temperature} {unit} rain" : "{temperature} {unit} 有雨",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} 今天稍後有大雨",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} 大雨",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} 今天稍後有陣雨",
- "{temperature} {unit} rain showers" : "{temperature} {unit} 陣雨",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} 今日稍後有小驟雨",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} 小驟雨",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} 今日稍後有大驟雨",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} 大驟雨",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} 今日稍後有微雨",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} 微雨",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} 今天稍後有雨",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} 有雨",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} 今天稍後有大雨",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} 大雨",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} 今天稍後有陣雨",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} 陣雨",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} 今日稍後有小驟雨",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} 小驟雨",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} 今日稍後有大驟雨",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} 大驟雨",
"More weather for {adr}" : "{adr} 的更多天氣",
"Loading weather" : "正在載入天氣",
"Remove from favorites" : "從最愛中移除",
diff --git a/apps/weather_status/l10n/zh_HK.json b/apps/weather_status/l10n/zh_HK.json
index 7a251ad060a..15fcd64c1ce 100644
--- a/apps/weather_status/l10n/zh_HK.json
+++ b/apps/weather_status/l10n/zh_HK.json
@@ -19,18 +19,18 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} 局部密雲",
"{temperature} {unit} foggy later today" : "{temperature} {unit} 今天稍後有霧",
"{temperature} {unit} foggy" : "{temperature} {unit} 有霧",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} 天稍後有微雨",
- "{temperature} {unit} light rain" : "{temperature} {unit} 微雨",
- "{temperature} {unit} rain later today" : "{temperature} {unit} 今天稍後有雨",
- "{temperature} {unit} rain" : "{temperature} {unit} 有雨",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} 今天稍後有大雨",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} 大雨",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} 今天稍後有陣雨",
- "{temperature} {unit} rain showers" : "{temperature} {unit} 陣雨",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} 今日稍後有小驟雨",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} 小驟雨",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} 今日稍後有大驟雨",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} 大驟雨",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} 今日稍後有微雨",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} 微雨",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} 今天稍後有雨",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} 有雨",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} 今天稍後有大雨",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} 大雨",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} 今天稍後有陣雨",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} 陣雨",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} 今日稍後有小驟雨",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} 小驟雨",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} 今日稍後有大驟雨",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} 大驟雨",
"More weather for {adr}" : "{adr} 的更多天氣",
"Loading weather" : "正在載入天氣",
"Remove from favorites" : "從最愛中移除",
diff --git a/apps/weather_status/l10n/zh_TW.js b/apps/weather_status/l10n/zh_TW.js
index 58b5923069d..69c123697a3 100644
--- a/apps/weather_status/l10n/zh_TW.js
+++ b/apps/weather_status/l10n/zh_TW.js
@@ -21,18 +21,18 @@ OC.L10N.register(
"{temperature} {unit} partly cloudy" : "{temperature} {unit} 局部多雲",
"{temperature} {unit} foggy later today" : "{temperature} {unit} 今日稍後有霧",
"{temperature} {unit} foggy" : "{temperature} {unit} 有霧",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} 今日稍後小雨",
- "{temperature} {unit} light rain" : "{temperature} {unit} 小雨",
- "{temperature} {unit} rain later today" : "{temperature} {unit} 今日稍後有雨",
- "{temperature} {unit} rain" : "{temperature} {unit} 有雨",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} 今日稍後大雨",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} 大雨",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} 今日稍後陣雨",
- "{temperature} {unit} rain showers" : "{temperature} {unit} 陣雨",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} 今日稍後小陣雨",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} 小陣雨",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} 今日稍後強陣雨",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} 強陣雨",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} 今日稍後小雨",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} 小雨",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} 今日稍後有雨",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} 有雨",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} 今日稍後大雨",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} 大雨",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} 今日稍後陣雨",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} 陣雨",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} 今日稍後小陣雨",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} 小陣雨",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} 今日稍後強陣雨",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} 強陣雨",
"More weather for {adr}" : "{adr} 的更多天氣",
"Loading weather" : "正在載入天氣",
"Remove from favorites" : "從最愛中移除",
diff --git a/apps/weather_status/l10n/zh_TW.json b/apps/weather_status/l10n/zh_TW.json
index e337d06d8ca..cd4d80a21c0 100644
--- a/apps/weather_status/l10n/zh_TW.json
+++ b/apps/weather_status/l10n/zh_TW.json
@@ -19,18 +19,18 @@
"{temperature} {unit} partly cloudy" : "{temperature} {unit} 局部多雲",
"{temperature} {unit} foggy later today" : "{temperature} {unit} 今日稍後有霧",
"{temperature} {unit} foggy" : "{temperature} {unit} 有霧",
- "{temperature} {unit} light rain later today" : "{temperature} {unit} 今日稍後小雨",
- "{temperature} {unit} light rain" : "{temperature} {unit} 小雨",
- "{temperature} {unit} rain later today" : "{temperature} {unit} 今日稍後有雨",
- "{temperature} {unit} rain" : "{temperature} {unit} 有雨",
- "{temperature} {unit} heavy rain later today" : "{temperature} {unit} 今日稍後大雨",
- "{temperature} {unit} heavy rain" : "{temperature} {unit} 大雨",
- "{temperature} {unit} rain showers later today" : "{temperature} {unit} 今日稍後陣雨",
- "{temperature} {unit} rain showers" : "{temperature} {unit} 陣雨",
- "{temperature} {unit} light rain showers later today" : "{temperature} {unit} 今日稍後小陣雨",
- "{temperature} {unit} light rain showers" : "{temperature} {unit} 小陣雨",
- "{temperature} {unit} heavy rain showers later today" : "{temperature} {unit} 今日稍後強陣雨",
- "{temperature} {unit} heavy rain showers" : "{temperature} {unit} 強陣雨",
+ "{temperature} {unit} light rainfall later today" : "{temperature} {unit} 今日稍後小雨",
+ "{temperature} {unit} light rainfall" : "{temperature} {unit} 小雨",
+ "{temperature} {unit} rainfall later today" : "{temperature} {unit} 今日稍後有雨",
+ "{temperature} {unit} rainfall" : "{temperature} {unit} 有雨",
+ "{temperature} {unit} heavy rainfall later today" : "{temperature} {unit} 今日稍後大雨",
+ "{temperature} {unit} heavy rainfall" : "{temperature} {unit} 大雨",
+ "{temperature} {unit} rainfall showers later today" : "{temperature} {unit} 今日稍後陣雨",
+ "{temperature} {unit} rainfall showers" : "{temperature} {unit} 陣雨",
+ "{temperature} {unit} light rainfall showers later today" : "{temperature} {unit} 今日稍後小陣雨",
+ "{temperature} {unit} light rainfall showers" : "{temperature} {unit} 小陣雨",
+ "{temperature} {unit} heavy rainfall showers later today" : "{temperature} {unit} 今日稍後強陣雨",
+ "{temperature} {unit} heavy rainfall showers" : "{temperature} {unit} 強陣雨",
"More weather for {adr}" : "{adr} 的更多天氣",
"Loading weather" : "正在載入天氣",
"Remove from favorites" : "從最愛中移除",
diff --git a/apps/weather_status/src/App.vue b/apps/weather_status/src/App.vue
index 78cbaadeb8d..8b96a520ef7 100644
--- a/apps/weather_status/src/App.vue
+++ b/apps/weather_status/src/App.vue
@@ -137,56 +137,56 @@ const weatherOptions = {
lightrain: {
icon: 'icon-lightrain',
text: (temperature, unit, later = false) => later
- ? t('weather_status', '{temperature} {unit} light rain later today', { temperature, unit })
- : t('weather_status', '{temperature} {unit} light rain', { temperature, unit }),
+ ? t('weather_status', '{temperature} {unit} light rainfall later today', { temperature, unit })
+ : t('weather_status', '{temperature} {unit} light rainfall', { temperature, unit }),
},
rain: {
icon: 'icon-rain',
text: (temperature, unit, later = false) => later
- ? t('weather_status', '{temperature} {unit} rain later today', { temperature, unit })
- : t('weather_status', '{temperature} {unit} rain', { temperature, unit }),
+ ? t('weather_status', '{temperature} {unit} rainfall later today', { temperature, unit })
+ : t('weather_status', '{temperature} {unit} rainfall', { temperature, unit }),
},
heavyrain: {
icon: 'icon-heavyrain',
text: (temperature, unit, later = false) => later
- ? t('weather_status', '{temperature} {unit} heavy rain later today', { temperature, unit })
- : t('weather_status', '{temperature} {unit} heavy rain', { temperature, unit }),
+ ? t('weather_status', '{temperature} {unit} heavy rainfall later today', { temperature, unit })
+ : t('weather_status', '{temperature} {unit} heavy rainfall', { temperature, unit }),
},
rainshowers_day: {
icon: 'icon-rainshowers-day',
text: (temperature, unit, later = false) => later
- ? t('weather_status', '{temperature} {unit} rain showers later today', { temperature, unit })
- : t('weather_status', '{temperature} {unit} rain showers', { temperature, unit }),
+ ? t('weather_status', '{temperature} {unit} rainfall showers later today', { temperature, unit })
+ : t('weather_status', '{temperature} {unit} rainfall showers', { temperature, unit }),
},
rainshowers_night: {
icon: 'icon-rainshowers-night',
text: (temperature, unit, later = false) => later
- ? t('weather_status', '{temperature} {unit} rain showers later today', { temperature, unit })
- : t('weather_status', '{temperature} {unit} rain showers', { temperature, unit }),
+ ? t('weather_status', '{temperature} {unit} rainfall showers later today', { temperature, unit })
+ : t('weather_status', '{temperature} {unit} rainfall showers', { temperature, unit }),
},
lightrainshowers_day: {
icon: 'icon-light-rainshowers-day',
text: (temperature, unit, later = false) => later
- ? t('weather_status', '{temperature} {unit} light rain showers later today', { temperature, unit })
- : t('weather_status', '{temperature} {unit} light rain showers', { temperature, unit }),
+ ? t('weather_status', '{temperature} {unit} light rainfall showers later today', { temperature, unit })
+ : t('weather_status', '{temperature} {unit} light rainfall showers', { temperature, unit }),
},
lightrainshowers_night: {
icon: 'icon-light-rainshowers-night',
text: (temperature, unit, later = false) => later
- ? t('weather_status', '{temperature} {unit} light rain showers later today', { temperature, unit })
- : t('weather_status', '{temperature} {unit} light rain showers', { temperature, unit }),
+ ? t('weather_status', '{temperature} {unit} light rainfall showers later today', { temperature, unit })
+ : t('weather_status', '{temperature} {unit} light rainfall showers', { temperature, unit }),
},
heavyrainshowers_day: {
icon: 'icon-heavy-rainshowers-day',
text: (temperature, unit, later = false) => later
- ? t('weather_status', '{temperature} {unit} heavy rain showers later today', { temperature, unit })
- : t('weather_status', '{temperature} {unit} heavy rain showers', { temperature, unit }),
+ ? t('weather_status', '{temperature} {unit} heavy rainfall showers later today', { temperature, unit })
+ : t('weather_status', '{temperature} {unit} heavy rainfall showers', { temperature, unit }),
},
heavyrainshowers_night: {
icon: 'icon-heavy-rainshowers-night',
text: (temperature, unit, later = false) => later
- ? t('weather_status', '{temperature} {unit} heavy rain showers later today', { temperature, unit })
- : t('weather_status', '{temperature} {unit} heavy rain showers', { temperature, unit }),
+ ? t('weather_status', '{temperature} {unit} heavy rainfall showers later today', { temperature, unit })
+ : t('weather_status', '{temperature} {unit} heavy rainfall showers', { temperature, unit }),
},
}
diff --git a/apps/workflowengine/lib/Listener/LoadAdditionalSettingsScriptsListener.php b/apps/workflowengine/lib/Listener/LoadAdditionalSettingsScriptsListener.php
index 6c38051d41a..a3806799ff0 100644
--- a/apps/workflowengine/lib/Listener/LoadAdditionalSettingsScriptsListener.php
+++ b/apps/workflowengine/lib/Listener/LoadAdditionalSettingsScriptsListener.php
@@ -32,7 +32,7 @@ use OCP\EventDispatcher\IEventListener;
use OCP\Template;
use function class_exists;
use function function_exists;
-use function script;
+use OCP\Util;
class LoadAdditionalSettingsScriptsListener implements IEventListener {
public function handle(Event $event): void {
@@ -41,10 +41,9 @@ class LoadAdditionalSettingsScriptsListener implements IEventListener {
class_exists(Template::class, true);
}
- script('core', 'systemtags');
-
- script(Application::APP_ID, [
- 'workflowengine',
- ]);
+ Util::addScript('core', 'files_fileinfo');
+ Util::addScript('core', 'files_client');
+ Util::addScript('core', 'systemtags');
+ Util::addScript(Application::APP_ID, 'workflowengine');
}
}