diff options
Diffstat (limited to 'lib')
86 files changed, 1993 insertions, 265 deletions
diff --git a/lib/base.php b/lib/base.php index 909a62040ee..d6c6e17eff9 100644 --- a/lib/base.php +++ b/lib/base.php @@ -377,7 +377,7 @@ class OC { \OCP\Util::addScript('update'); \OCP\Util::addStyle('update'); - /** @var \OCP\App\IAppManager $appManager */ + /** @var \OC\App\AppManager $appManager */ $appManager = \OC::$server->getAppManager(); $tmpl = new OC_Template('', 'update.admin', 'guest'); @@ -387,14 +387,19 @@ class OC { // get third party apps $ocVersion = \OCP\Util::getVersion(); $incompatibleApps = $appManager->getIncompatibleApps($ocVersion); + $incompatibleShippedApps = []; foreach ($incompatibleApps as $appInfo) { if ($appManager->isShipped($appInfo['id'])) { - $l = \OC::$server->getL10N('core'); - $hint = $l->t('The files of the app "%$1s" (%$2s) were not replaced correctly.', [$appInfo['name'], $appInfo['id']]); - throw new \OC\HintException('The files of the app "' . $appInfo['name'] . '" (' . $appInfo['id'] . ') were not replaced correctly.', $hint); + $incompatibleShippedApps[] = $appInfo['name'] . ' (' . $appInfo['id'] . ')'; } } + if (!empty($incompatibleShippedApps)) { + $l = \OC::$server->getL10N('core'); + $hint = $l->t('The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server.', [implode(', ', $incompatibleShippedApps)]); + throw new \OC\HintException('The files of the app ' . implode(', ', $incompatibleShippedApps) . ' were not replaced correctly. Make sure it is a version compatible with the server.', $hint); + } + $tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion)); $tmpl->assign('incompatibleAppsList', $incompatibleApps); $tmpl->assign('productName', 'Nextcloud'); // for now diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 42cfb8c45e1..dafa46bc996 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -189,6 +189,7 @@ return array( 'OCP\\LDAP\\ILDAPProviderFactory' => $baseDir . '/lib/public/LDAP/ILDAPProviderFactory.php', 'OCP\\Lock\\ILockingProvider' => $baseDir . '/lib/public/Lock/ILockingProvider.php', 'OCP\\Lock\\LockedException' => $baseDir . '/lib/public/Lock/LockedException.php', + 'OCP\\Lockdown\\ILockdownManager' => $baseDir . '/lib/public/Lockdown/ILockdownManager.php', 'OCP\\Mail\\IMailer' => $baseDir . '/lib/public/Mail/IMailer.php', 'OCP\\Migration\\IOutput' => $baseDir . '/lib/public/Migration/IOutput.php', 'OCP\\Migration\\IRepairStep' => $baseDir . '/lib/public/Migration/IRepairStep.php', @@ -264,6 +265,7 @@ return array( 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\AppNotEnabledException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php', 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\CrossSiteRequestForgeryException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/CrossSiteRequestForgeryException.php', 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\NotAdminException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php', + 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\NotConfirmedException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php', 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\NotLoggedInException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/NotLoggedInException.php', 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\SecurityException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/SecurityException.php', 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\StrictCookieMissingException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/StrictCookieMissingException.php', @@ -580,6 +582,9 @@ return array( 'OC\\Lock\\DBLockingProvider' => $baseDir . '/lib/private/Lock/DBLockingProvider.php', 'OC\\Lock\\MemcacheLockingProvider' => $baseDir . '/lib/private/Lock/MemcacheLockingProvider.php', 'OC\\Lock\\NoopLockingProvider' => $baseDir . '/lib/private/Lock/NoopLockingProvider.php', + 'OC\\Lockdown\\Filesystem\\NullCache' => $baseDir . '/lib/private/Lockdown/Filesystem/NullCache.php', + 'OC\\Lockdown\\Filesystem\\NullStorage' => $baseDir . '/lib/private/Lockdown/Filesystem/NullStorage.php', + 'OC\\Lockdown\\LockdownManager' => $baseDir . '/lib/private/Lockdown/LockdownManager.php', 'OC\\Log' => $baseDir . '/lib/private/Log.php', 'OC\\Log\\ErrorHandler' => $baseDir . '/lib/private/Log/ErrorHandler.php', 'OC\\Log\\Errorlog' => $baseDir . '/lib/private/Log/Errorlog.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index d7e937577f2..5b8356785bc 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -219,6 +219,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\LDAP\\ILDAPProviderFactory' => __DIR__ . '/../../..' . '/lib/public/LDAP/ILDAPProviderFactory.php', 'OCP\\Lock\\ILockingProvider' => __DIR__ . '/../../..' . '/lib/public/Lock/ILockingProvider.php', 'OCP\\Lock\\LockedException' => __DIR__ . '/../../..' . '/lib/public/Lock/LockedException.php', + 'OCP\\Lockdown\\ILockdownManager' => __DIR__ . '/../../..' . '/lib/public/Lockdown/ILockdownManager.php', 'OCP\\Mail\\IMailer' => __DIR__ . '/../../..' . '/lib/public/Mail/IMailer.php', 'OCP\\Migration\\IOutput' => __DIR__ . '/../../..' . '/lib/public/Migration/IOutput.php', 'OCP\\Migration\\IRepairStep' => __DIR__ . '/../../..' . '/lib/public/Migration/IRepairStep.php', @@ -294,6 +295,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\AppNotEnabledException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php', 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\CrossSiteRequestForgeryException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/CrossSiteRequestForgeryException.php', 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\NotAdminException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php', + 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\NotConfirmedException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php', 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\NotLoggedInException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/NotLoggedInException.php', 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\SecurityException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/SecurityException.php', 'OC\\AppFramework\\Middleware\\Security\\Exceptions\\StrictCookieMissingException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/StrictCookieMissingException.php', @@ -610,6 +612,9 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Lock\\DBLockingProvider' => __DIR__ . '/../../..' . '/lib/private/Lock/DBLockingProvider.php', 'OC\\Lock\\MemcacheLockingProvider' => __DIR__ . '/../../..' . '/lib/private/Lock/MemcacheLockingProvider.php', 'OC\\Lock\\NoopLockingProvider' => __DIR__ . '/../../..' . '/lib/private/Lock/NoopLockingProvider.php', + 'OC\\Lockdown\\Filesystem\\NullCache' => __DIR__ . '/../../..' . '/lib/private/Lockdown/Filesystem/NullCache.php', + 'OC\\Lockdown\\Filesystem\\NullStorage' => __DIR__ . '/../../..' . '/lib/private/Lockdown/Filesystem/NullStorage.php', + 'OC\\Lockdown\\LockdownManager' => __DIR__ . '/../../..' . '/lib/private/Lockdown/LockdownManager.php', 'OC\\Log' => __DIR__ . '/../../..' . '/lib/private/Log.php', 'OC\\Log\\ErrorHandler' => __DIR__ . '/../../..' . '/lib/private/Log/ErrorHandler.php', 'OC\\Log\\Errorlog' => __DIR__ . '/../../..' . '/lib/private/Log/Errorlog.php', diff --git a/lib/l10n/cs_CZ.js b/lib/l10n/cs_CZ.js index c4bb85acd64..9a44c0d1800 100644 --- a/lib/l10n/cs_CZ.js +++ b/lib/l10n/cs_CZ.js @@ -5,7 +5,6 @@ OC.L10N.register( "This can usually be fixed by giving the webserver write access to the config directory" : "To lze obvykle vyřešit povolením zápisu webovému serveru do konfiguračního adresáře", "See %s" : "Viz %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "To lze obvykle vyřešit %spovolením zápisu webovému serveru do konfiguračního adresáře%s.", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "Soubory aplikace \"%$1s\" (%$2s) nebyly řádně nahrazeny.", "Sample configuration detected" : "Byla detekována vzorová konfigurace", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Pravděpodobně byla zkopírována konfigurační nastavení ze vzorových souborů. Toto není podporováno a může poškodit vaši instalaci. Nahlédněte prosím do dokumentace před prováděním změn v souboru config.php", "PHP %s or higher is required." : "Je vyžadováno PHP %s nebo vyšší.", @@ -44,7 +43,6 @@ OC.L10N.register( "Server settings" : "Nastavení serveru", "Sharing" : "Sdílení", "Encryption" : "Šifrování", - "Logging" : "Logování", "Additional settings" : "Dodatečná nastavení", "Tips & tricks" : "Tipy a triky", "%s enter the database username and name." : "%s zadejte uživatelské jméno a jméno databáze.", @@ -221,6 +219,7 @@ OC.L10N.register( "App can't be installed because it is not compatible with this version of the server" : "Aplikaci nelze nainstalovat, protože není kompatibilní s touto verzí serveru.", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Aplikace nemůže být nainstalována, protože obsahuje značku\n<shipped>\n\ntrue\n</shipped>\n\ncož není povoleno pro nedodávané aplikace", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Aplikace nemůže být nainstalována, protože verze uvedená v info.xml nesouhlasí s verzí oznámenou z úložiště aplikací.", + "Logging" : "Logování", "Recommended" : "Doporučené", "Microsoft Windows Platform is not supported" : "Platforma Microsoft Windows není podporována", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Provozování Nextcloud Serveru na platformě Microsoft Windows není podporováno. Doporučujeme, abyste použili linuxový server ve virtuálním stroji, pokud nemáte možnost server migrovat.", diff --git a/lib/l10n/cs_CZ.json b/lib/l10n/cs_CZ.json index 9514c96394a..861bc657d32 100644 --- a/lib/l10n/cs_CZ.json +++ b/lib/l10n/cs_CZ.json @@ -3,7 +3,6 @@ "This can usually be fixed by giving the webserver write access to the config directory" : "To lze obvykle vyřešit povolením zápisu webovému serveru do konfiguračního adresáře", "See %s" : "Viz %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "To lze obvykle vyřešit %spovolením zápisu webovému serveru do konfiguračního adresáře%s.", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "Soubory aplikace \"%$1s\" (%$2s) nebyly řádně nahrazeny.", "Sample configuration detected" : "Byla detekována vzorová konfigurace", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Pravděpodobně byla zkopírována konfigurační nastavení ze vzorových souborů. Toto není podporováno a může poškodit vaši instalaci. Nahlédněte prosím do dokumentace před prováděním změn v souboru config.php", "PHP %s or higher is required." : "Je vyžadováno PHP %s nebo vyšší.", @@ -42,7 +41,6 @@ "Server settings" : "Nastavení serveru", "Sharing" : "Sdílení", "Encryption" : "Šifrování", - "Logging" : "Logování", "Additional settings" : "Dodatečná nastavení", "Tips & tricks" : "Tipy a triky", "%s enter the database username and name." : "%s zadejte uživatelské jméno a jméno databáze.", @@ -219,6 +217,7 @@ "App can't be installed because it is not compatible with this version of the server" : "Aplikaci nelze nainstalovat, protože není kompatibilní s touto verzí serveru.", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Aplikace nemůže být nainstalována, protože obsahuje značku\n<shipped>\n\ntrue\n</shipped>\n\ncož není povoleno pro nedodávané aplikace", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Aplikace nemůže být nainstalována, protože verze uvedená v info.xml nesouhlasí s verzí oznámenou z úložiště aplikací.", + "Logging" : "Logování", "Recommended" : "Doporučené", "Microsoft Windows Platform is not supported" : "Platforma Microsoft Windows není podporována", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Provozování Nextcloud Serveru na platformě Microsoft Windows není podporováno. Doporučujeme, abyste použili linuxový server ve virtuálním stroji, pokud nemáte možnost server migrovat.", diff --git a/lib/l10n/de.js b/lib/l10n/de.js index 28a4da2419e..89c83366136 100644 --- a/lib/l10n/de.js +++ b/lib/l10n/de.js @@ -5,7 +5,7 @@ OC.L10N.register( "This can usually be fixed by giving the webserver write access to the config directory" : "Dies kann normalerweise repariert werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird", "See %s" : "Siehe %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Dies kann normalerweise behoben werden, %sindem dem Webserver Schreibzugriff auf das Konfigurationsverzeichnis gegeben wird%s.", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "Die Dateien der App \"%$1s\" (%$2s) wurden nicht korrekt ersetzt.", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Die Dateien der App %$1s wurden nicht korrekt ersetzt. Stelle sicher, dass die Version mit dem Server kompatibel ist.", "Sample configuration detected" : "Beispielkonfiguration gefunden", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann Ihre Installation zunichte machen und wird nicht unterstützt. Bitte die Dokumentation lesen, bevor Änderungen an der config.php vorgenommen werden.", "PHP %s or higher is required." : "PHP %s oder höher wird benötigt.", @@ -44,7 +44,6 @@ OC.L10N.register( "Server settings" : "Servereinstellungen", "Sharing" : "Teilen", "Encryption" : "Verschlüsselung", - "Logging" : "Protokollierung", "Additional settings" : "Zusätzliche Einstellungen", "Tips & tricks" : "Tipps & Tricks", "%s enter the database username and name." : "%s bitte gib den Datenbank Benutzernamen und den Datenbank Namen ein.", @@ -221,6 +220,7 @@ OC.L10N.register( "App can't be installed because it is not compatible with this version of the server" : "Die App kann nicht installiert werden, da sie mit dieser Serverversion nicht kompatibel ist.", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Die App kann nicht installiert werden, weil sie die <shipped>true</shipped>-Bezeichnung enthält, die bei Apps, die nicht zum Standardumfang gehören, nicht erlaubt ist", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Diese App kann nicht installiert werden, da die Version in info.xml nicht die gleiche Version wie die aus dem App Store ist.", + "Logging" : "Protokollierung", "Recommended" : "Empfohlen", "Microsoft Windows Platform is not supported" : "Microsoft Windows-Plattform wird nicht unterstützt", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Der Betrieb eines Nextcloud-Servers unter Microsoft Windows ist nicht unterstützt. Bitte ziehein Betracht einen Linux-Server im Rahmen einer virtuellen Maschine aufzusetzen, wenn du keine Möglichkeit hast, den Server selbst zu migrieren.", diff --git a/lib/l10n/de.json b/lib/l10n/de.json index 163965e2689..46de315cfdf 100644 --- a/lib/l10n/de.json +++ b/lib/l10n/de.json @@ -3,7 +3,7 @@ "This can usually be fixed by giving the webserver write access to the config directory" : "Dies kann normalerweise repariert werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird", "See %s" : "Siehe %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Dies kann normalerweise behoben werden, %sindem dem Webserver Schreibzugriff auf das Konfigurationsverzeichnis gegeben wird%s.", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "Die Dateien der App \"%$1s\" (%$2s) wurden nicht korrekt ersetzt.", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Die Dateien der App %$1s wurden nicht korrekt ersetzt. Stelle sicher, dass die Version mit dem Server kompatibel ist.", "Sample configuration detected" : "Beispielkonfiguration gefunden", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann Ihre Installation zunichte machen und wird nicht unterstützt. Bitte die Dokumentation lesen, bevor Änderungen an der config.php vorgenommen werden.", "PHP %s or higher is required." : "PHP %s oder höher wird benötigt.", @@ -42,7 +42,6 @@ "Server settings" : "Servereinstellungen", "Sharing" : "Teilen", "Encryption" : "Verschlüsselung", - "Logging" : "Protokollierung", "Additional settings" : "Zusätzliche Einstellungen", "Tips & tricks" : "Tipps & Tricks", "%s enter the database username and name." : "%s bitte gib den Datenbank Benutzernamen und den Datenbank Namen ein.", @@ -219,6 +218,7 @@ "App can't be installed because it is not compatible with this version of the server" : "Die App kann nicht installiert werden, da sie mit dieser Serverversion nicht kompatibel ist.", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Die App kann nicht installiert werden, weil sie die <shipped>true</shipped>-Bezeichnung enthält, die bei Apps, die nicht zum Standardumfang gehören, nicht erlaubt ist", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Diese App kann nicht installiert werden, da die Version in info.xml nicht die gleiche Version wie die aus dem App Store ist.", + "Logging" : "Protokollierung", "Recommended" : "Empfohlen", "Microsoft Windows Platform is not supported" : "Microsoft Windows-Plattform wird nicht unterstützt", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Der Betrieb eines Nextcloud-Servers unter Microsoft Windows ist nicht unterstützt. Bitte ziehein Betracht einen Linux-Server im Rahmen einer virtuellen Maschine aufzusetzen, wenn du keine Möglichkeit hast, den Server selbst zu migrieren.", diff --git a/lib/l10n/de_DE.js b/lib/l10n/de_DE.js index a71b7cf72c6..434402a8527 100644 --- a/lib/l10n/de_DE.js +++ b/lib/l10n/de_DE.js @@ -5,7 +5,7 @@ OC.L10N.register( "This can usually be fixed by giving the webserver write access to the config directory" : "Dies kann normalerweise repariert werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird", "See %s" : "Siehe %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Dies kann normalerweise behoben werden, %sindem dem Webserver Schreibzugriff auf das Konfigurationsverzeichnis gegeben wird%s.", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "Die Dateien der App \"%$1s\" (%$2s) wurden nicht korrekt ersetzt.", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Die Dateien der App %$1s wurden nicht korrekt ersetzt. Stellen Sie sicher, dass die Version mit dem Server kompatibel ist.", "Sample configuration detected" : "Beispielkonfiguration gefunden", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann Ihre Installation zerstören und wird nicht unterstützt. Bitte lesen Sie die Dokumentation, bevor Sie Änderungen an der config.php vornehmen.", "PHP %s or higher is required." : "PHP %s oder höher wird benötigt.", @@ -44,7 +44,6 @@ OC.L10N.register( "Server settings" : "Servereinstellungen", "Sharing" : "Teilen", "Encryption" : "Verschlüsselung", - "Logging" : "Protokollierung", "Additional settings" : "Zusätzliche Einstellungen", "Tips & tricks" : "Tipps & Tricks", "%s enter the database username and name." : "%s geben Sie den Datenbank-Benutzernamen und den Datenbanknamen an.", @@ -221,6 +220,7 @@ OC.L10N.register( "App can't be installed because it is not compatible with this version of the server" : "Die App kann nicht installiert werden, da sie mit dieser Serverversion nicht kompatibel ist.", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Die App kann nicht installiert werden, weil sie den <shipped>true</shipped>-Tag enthält, der bei Apps, die nicht zum Standardumfang gehören, nicht erlaubt ist", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Die App konnte nicht installiert werden, da die Version in der info.xml nicht die gleiche Version wie im App-Store ist.", + "Logging" : "Protokollierung", "Recommended" : "Empfohlen", "Microsoft Windows Platform is not supported" : "Microsoft Windows-Plattform wird nicht unterstützt", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Der Betrieb eines Nextcloud Servers unter Microsoft Windows ist nicht unterstützt. Bitte ziehen Sie in Betracht einen Linux Server im Rahmen einer virtuellen Maschine aufzusetzen, wenn Sie keine Möglichkeit haben, den Server selbst zu migrieren.", diff --git a/lib/l10n/de_DE.json b/lib/l10n/de_DE.json index 8d2953651e5..10bf5de7b1d 100644 --- a/lib/l10n/de_DE.json +++ b/lib/l10n/de_DE.json @@ -3,7 +3,7 @@ "This can usually be fixed by giving the webserver write access to the config directory" : "Dies kann normalerweise repariert werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird", "See %s" : "Siehe %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Dies kann normalerweise behoben werden, %sindem dem Webserver Schreibzugriff auf das Konfigurationsverzeichnis gegeben wird%s.", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "Die Dateien der App \"%$1s\" (%$2s) wurden nicht korrekt ersetzt.", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Die Dateien der App %$1s wurden nicht korrekt ersetzt. Stellen Sie sicher, dass die Version mit dem Server kompatibel ist.", "Sample configuration detected" : "Beispielkonfiguration gefunden", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann Ihre Installation zerstören und wird nicht unterstützt. Bitte lesen Sie die Dokumentation, bevor Sie Änderungen an der config.php vornehmen.", "PHP %s or higher is required." : "PHP %s oder höher wird benötigt.", @@ -42,7 +42,6 @@ "Server settings" : "Servereinstellungen", "Sharing" : "Teilen", "Encryption" : "Verschlüsselung", - "Logging" : "Protokollierung", "Additional settings" : "Zusätzliche Einstellungen", "Tips & tricks" : "Tipps & Tricks", "%s enter the database username and name." : "%s geben Sie den Datenbank-Benutzernamen und den Datenbanknamen an.", @@ -219,6 +218,7 @@ "App can't be installed because it is not compatible with this version of the server" : "Die App kann nicht installiert werden, da sie mit dieser Serverversion nicht kompatibel ist.", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Die App kann nicht installiert werden, weil sie den <shipped>true</shipped>-Tag enthält, der bei Apps, die nicht zum Standardumfang gehören, nicht erlaubt ist", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Die App konnte nicht installiert werden, da die Version in der info.xml nicht die gleiche Version wie im App-Store ist.", + "Logging" : "Protokollierung", "Recommended" : "Empfohlen", "Microsoft Windows Platform is not supported" : "Microsoft Windows-Plattform wird nicht unterstützt", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Der Betrieb eines Nextcloud Servers unter Microsoft Windows ist nicht unterstützt. Bitte ziehen Sie in Betracht einen Linux Server im Rahmen einer virtuellen Maschine aufzusetzen, wenn Sie keine Möglichkeit haben, den Server selbst zu migrieren.", diff --git a/lib/l10n/es.js b/lib/l10n/es.js index 14b57caa516..7c30bcaef6c 100644 --- a/lib/l10n/es.js +++ b/lib/l10n/es.js @@ -42,7 +42,6 @@ OC.L10N.register( "Server settings" : "Configuración del servidor", "Sharing" : "Compartir", "Encryption" : "Cifrado", - "Logging" : "Inicio de sesión", "Additional settings" : "Configuración adicional", "Tips & tricks" : "Sugerencias y trucos", "%s enter the database username and name." : "%s introduzca el nombre de usuario y la contraseña de la BBDD.", @@ -219,6 +218,7 @@ OC.L10N.register( "App can't be installed because it is not compatible with this version of the server" : "La aplicación no se puede instalar porque no es compatible con esta versión del servidor", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "La aplicación no se puede instalar porque contiene la etiqueta\n<shipped>\ntrue\n</shipped>\nque no está permitida para aplicaciones no distribuidas", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "La App no se puede instalar debido a que la versión de info.xml no es la misma que la versión reportada por la App Store.", + "Logging" : "Inicio de sesión", "Recommended" : "Recomendado", "Microsoft Windows Platform is not supported" : "La plataforma Microsoft Windows no está soportada", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Ejecutar el servidor Nextcloud en la plataforma MIcrosoft Windows no está soportado. Sugerimos usar un servidor Linux en una máquina virtual si no existe la opción de migrar el propio servidor.", diff --git a/lib/l10n/es.json b/lib/l10n/es.json index b712849303c..5445c9c757a 100644 --- a/lib/l10n/es.json +++ b/lib/l10n/es.json @@ -40,7 +40,6 @@ "Server settings" : "Configuración del servidor", "Sharing" : "Compartir", "Encryption" : "Cifrado", - "Logging" : "Inicio de sesión", "Additional settings" : "Configuración adicional", "Tips & tricks" : "Sugerencias y trucos", "%s enter the database username and name." : "%s introduzca el nombre de usuario y la contraseña de la BBDD.", @@ -217,6 +216,7 @@ "App can't be installed because it is not compatible with this version of the server" : "La aplicación no se puede instalar porque no es compatible con esta versión del servidor", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "La aplicación no se puede instalar porque contiene la etiqueta\n<shipped>\ntrue\n</shipped>\nque no está permitida para aplicaciones no distribuidas", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "La App no se puede instalar debido a que la versión de info.xml no es la misma que la versión reportada por la App Store.", + "Logging" : "Inicio de sesión", "Recommended" : "Recomendado", "Microsoft Windows Platform is not supported" : "La plataforma Microsoft Windows no está soportada", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Ejecutar el servidor Nextcloud en la plataforma MIcrosoft Windows no está soportado. Sugerimos usar un servidor Linux en una máquina virtual si no existe la opción de migrar el propio servidor.", diff --git a/lib/l10n/fr.js b/lib/l10n/fr.js index 545ee1d23b5..d182116c5da 100644 --- a/lib/l10n/fr.js +++ b/lib/l10n/fr.js @@ -5,7 +5,7 @@ OC.L10N.register( "This can usually be fixed by giving the webserver write access to the config directory" : "Ce problème est généralement résolu en donnant au serveur web un accès en écriture au répertoire \"config\"", "See %s" : "Voir %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Ce problème est généralement résolu %sen donnant au serveur web un accès en écriture au répertoire de configuration%s.", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "Les fichiers de l'application « %$1s » (%$2s) n'ont pas été remplacés correctement.", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Les fichiers de l'application %$1s n'ont pas été remplacés correctement. Veuillez vérifier que c'est une version compatible avec le serveur.", "Sample configuration detected" : "Configuration d'exemple détectée", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Il a été détecté que la configuration donnée à titre d'exemple a été copiée. Cela peut rendre votre installation inopérante et n'est pas pris en charge. Veuillez lire la documentation avant d'effectuer des modifications dans config.php", "PHP %s or higher is required." : "PHP %s ou supérieur est requis.", @@ -21,6 +21,7 @@ OC.L10N.register( "Server version %s or lower is required." : "Un serveur de version %s ou inférieure est requis.", "Unknown filetype" : "Type de fichier inconnu", "Invalid image" : "Image non valable", + "Avatar image is not square" : "L'image d'avatar n'est pas carré", "today" : "aujourd'hui", "yesterday" : "hier", "_%n day ago_::_%n days ago_" : ["il y a %n jour","il y a %n jours"], @@ -43,7 +44,6 @@ OC.L10N.register( "Server settings" : "Paramètres serveur", "Sharing" : "Partage", "Encryption" : "Chiffrement", - "Logging" : "Connexion", "Additional settings" : "Paramètres supplémentaires", "Tips & tricks" : "Trucs et astuces", "%s enter the database username and name." : "%s entrez le nom d'utilisateur et le nom de la base de données.", @@ -203,6 +203,7 @@ OC.L10N.register( "Storage unauthorized. %s" : "Espace de stockage non autorisé. %s", "Storage incomplete configuration. %s" : "Configuration de l'espace de stockage incomplète. %s", "Storage connection error. %s" : "Erreur de connexion à l'espace stockage. %s", + "Storage is temporarily not available" : "Le support de stockage est temporairement indisponible", "Storage connection timeout. %s" : "Le délai d'attente pour la connexion à l'espace de stockage a été dépassé. %s", "App directory already exists" : "Le dossier de l'application existe déjà", "Can't create app folder. Please fix permissions. %s" : "Impossible de créer le dossier de l'application. Corrigez les droits d'accès. %s", @@ -219,6 +220,7 @@ OC.L10N.register( "App can't be installed because it is not compatible with this version of the server" : "L'application ne peut être installée car elle n'est pas compatible avec cette version du serveur", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "L'application ne peut être installée car elle contient la balise <shipped>true</shipped> qui n'est pas autorisée pour les applications non incluses par défaut", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "L'App ne peut pas être installé car la version dans info.xml diffère de la version signalée par l' app store", + "Logging" : "Connexion", "Recommended" : "Recommandée", "Microsoft Windows Platform is not supported" : "La plate-forme Microsoft Windows n'est pas prise en charge.", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "L'exécution de Nextcloud Server sur une plateforme Microsoft Windows n'est pas supportée. Nous suggérons d'utilier un serveur Linux dans une machine virtuelle si vous n'avez pas la possibilité de migrer le serveur lui-même.", diff --git a/lib/l10n/fr.json b/lib/l10n/fr.json index e810852d851..cfabc97f539 100644 --- a/lib/l10n/fr.json +++ b/lib/l10n/fr.json @@ -3,7 +3,7 @@ "This can usually be fixed by giving the webserver write access to the config directory" : "Ce problème est généralement résolu en donnant au serveur web un accès en écriture au répertoire \"config\"", "See %s" : "Voir %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Ce problème est généralement résolu %sen donnant au serveur web un accès en écriture au répertoire de configuration%s.", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "Les fichiers de l'application « %$1s » (%$2s) n'ont pas été remplacés correctement.", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Les fichiers de l'application %$1s n'ont pas été remplacés correctement. Veuillez vérifier que c'est une version compatible avec le serveur.", "Sample configuration detected" : "Configuration d'exemple détectée", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Il a été détecté que la configuration donnée à titre d'exemple a été copiée. Cela peut rendre votre installation inopérante et n'est pas pris en charge. Veuillez lire la documentation avant d'effectuer des modifications dans config.php", "PHP %s or higher is required." : "PHP %s ou supérieur est requis.", @@ -19,6 +19,7 @@ "Server version %s or lower is required." : "Un serveur de version %s ou inférieure est requis.", "Unknown filetype" : "Type de fichier inconnu", "Invalid image" : "Image non valable", + "Avatar image is not square" : "L'image d'avatar n'est pas carré", "today" : "aujourd'hui", "yesterday" : "hier", "_%n day ago_::_%n days ago_" : ["il y a %n jour","il y a %n jours"], @@ -41,7 +42,6 @@ "Server settings" : "Paramètres serveur", "Sharing" : "Partage", "Encryption" : "Chiffrement", - "Logging" : "Connexion", "Additional settings" : "Paramètres supplémentaires", "Tips & tricks" : "Trucs et astuces", "%s enter the database username and name." : "%s entrez le nom d'utilisateur et le nom de la base de données.", @@ -201,6 +201,7 @@ "Storage unauthorized. %s" : "Espace de stockage non autorisé. %s", "Storage incomplete configuration. %s" : "Configuration de l'espace de stockage incomplète. %s", "Storage connection error. %s" : "Erreur de connexion à l'espace stockage. %s", + "Storage is temporarily not available" : "Le support de stockage est temporairement indisponible", "Storage connection timeout. %s" : "Le délai d'attente pour la connexion à l'espace de stockage a été dépassé. %s", "App directory already exists" : "Le dossier de l'application existe déjà", "Can't create app folder. Please fix permissions. %s" : "Impossible de créer le dossier de l'application. Corrigez les droits d'accès. %s", @@ -217,6 +218,7 @@ "App can't be installed because it is not compatible with this version of the server" : "L'application ne peut être installée car elle n'est pas compatible avec cette version du serveur", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "L'application ne peut être installée car elle contient la balise <shipped>true</shipped> qui n'est pas autorisée pour les applications non incluses par défaut", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "L'App ne peut pas être installé car la version dans info.xml diffère de la version signalée par l' app store", + "Logging" : "Connexion", "Recommended" : "Recommandée", "Microsoft Windows Platform is not supported" : "La plate-forme Microsoft Windows n'est pas prise en charge.", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "L'exécution de Nextcloud Server sur une plateforme Microsoft Windows n'est pas supportée. Nous suggérons d'utilier un serveur Linux dans une machine virtuelle si vous n'avez pas la possibilité de migrer le serveur lui-même.", diff --git a/lib/l10n/hu_HU.js b/lib/l10n/hu_HU.js index 92651f45303..d5b4598cf81 100644 --- a/lib/l10n/hu_HU.js +++ b/lib/l10n/hu_HU.js @@ -5,7 +5,7 @@ OC.L10N.register( "This can usually be fixed by giving the webserver write access to the config directory" : "Ez rendszerint úgy oldható meg, hogy írási jogot adunk a webszervernek a config könyvtárra.", "See %s" : "Lásd %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Ez rendszerint úgy oldható meg, hogy %sírási jogot adunk a webszervernek a config könyvtárra%s.", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "\"%$1s\" (%$2s) alkalmazás fájljai nem megfelelően lettek cserélve.", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "%$1s alkalmazás fájljai nem megfelelően lettek cserélve. Győződj meg róla, hogy ez a verzió kompatibilis-e a szerverrel.", "Sample configuration detected" : "A példabeállítások vannak beállítva", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Úgy tűnik a példakonfigurációt próbálja ténylegesen használni. Ez nem támogatott, és működésképtelenné teheti a telepítést. Kérlek olvasd el a dokumentációt és azt követően változtas a config.php-n!", "PHP %s or higher is required." : "PHP %s vagy ennél újabb szükséges.", @@ -44,7 +44,6 @@ OC.L10N.register( "Server settings" : "Szerver beállítások", "Sharing" : "Megosztás", "Encryption" : "Titkosítás", - "Logging" : "Naplózás", "Additional settings" : "További beállítások", "Tips & tricks" : "Tippek és trükkök", "%s enter the database username and name." : "%s add meg az adatbázis nevét és felhasználónevét", @@ -221,6 +220,7 @@ OC.L10N.register( "App can't be installed because it is not compatible with this version of the server" : "Az alkalmazást nem lehet telepíteni, mert nem kompatibilis ezzel a szerver verzióval", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Az alkalmazást nem lehet telepíteni, mert tartalmazza a \n<shipped>\ntrue\n</shipped>\ncímkét, ami a nem szállított alkalmazások esetén nem engedélyezett", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Az alkalmazás nem telepíthető, mert az info.xml fájlban tárolt verzió nem egyezik meg az alkalmazás boltban elérhető verzióval", + "Logging" : "Naplózás", "Recommended" : "Ajánlott", "Microsoft Windows Platform is not supported" : "Microsoft Windows platform nem támogatott", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "A Nextcloud Server Microsoft Windows platformon való futtatása nem támogatott. Ha nincs más lehetőséged a szerver migrációjára, akkor javasoljuk, hogy Linux szervert használj virtuális gépben.", diff --git a/lib/l10n/hu_HU.json b/lib/l10n/hu_HU.json index ae980944269..02bd506bc22 100644 --- a/lib/l10n/hu_HU.json +++ b/lib/l10n/hu_HU.json @@ -3,7 +3,7 @@ "This can usually be fixed by giving the webserver write access to the config directory" : "Ez rendszerint úgy oldható meg, hogy írási jogot adunk a webszervernek a config könyvtárra.", "See %s" : "Lásd %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Ez rendszerint úgy oldható meg, hogy %sírási jogot adunk a webszervernek a config könyvtárra%s.", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "\"%$1s\" (%$2s) alkalmazás fájljai nem megfelelően lettek cserélve.", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "%$1s alkalmazás fájljai nem megfelelően lettek cserélve. Győződj meg róla, hogy ez a verzió kompatibilis-e a szerverrel.", "Sample configuration detected" : "A példabeállítások vannak beállítva", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Úgy tűnik a példakonfigurációt próbálja ténylegesen használni. Ez nem támogatott, és működésképtelenné teheti a telepítést. Kérlek olvasd el a dokumentációt és azt követően változtas a config.php-n!", "PHP %s or higher is required." : "PHP %s vagy ennél újabb szükséges.", @@ -42,7 +42,6 @@ "Server settings" : "Szerver beállítások", "Sharing" : "Megosztás", "Encryption" : "Titkosítás", - "Logging" : "Naplózás", "Additional settings" : "További beállítások", "Tips & tricks" : "Tippek és trükkök", "%s enter the database username and name." : "%s add meg az adatbázis nevét és felhasználónevét", @@ -219,6 +218,7 @@ "App can't be installed because it is not compatible with this version of the server" : "Az alkalmazást nem lehet telepíteni, mert nem kompatibilis ezzel a szerver verzióval", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Az alkalmazást nem lehet telepíteni, mert tartalmazza a \n<shipped>\ntrue\n</shipped>\ncímkét, ami a nem szállított alkalmazások esetén nem engedélyezett", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Az alkalmazás nem telepíthető, mert az info.xml fájlban tárolt verzió nem egyezik meg az alkalmazás boltban elérhető verzióval", + "Logging" : "Naplózás", "Recommended" : "Ajánlott", "Microsoft Windows Platform is not supported" : "Microsoft Windows platform nem támogatott", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "A Nextcloud Server Microsoft Windows platformon való futtatása nem támogatott. Ha nincs más lehetőséged a szerver migrációjára, akkor javasoljuk, hogy Linux szervert használj virtuális gépben.", diff --git a/lib/l10n/it.js b/lib/l10n/it.js index af47d8f9e17..af307f3c0c3 100644 --- a/lib/l10n/it.js +++ b/lib/l10n/it.js @@ -5,7 +5,7 @@ OC.L10N.register( "This can usually be fixed by giving the webserver write access to the config directory" : "Ciò può essere normalmente corretto fornendo al server web accesso in scrittura alla cartella \"config\"", "See %s" : "Vedi %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Ciò può essere normalmente corretto %sfornendo al server web accesso in scrittura alla cartella \"config\"%s", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "I file dell'applicazione \"%1$s\" (%2$s) non sono stati sostituiti correttamente.", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "I file dell'applicazione %1$s non sono stati sostituiti correttamente. Assicurati che sia una versione compatibile con il server.", "Sample configuration detected" : "Configurazione di esempio rilevata", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "È stato rilevato che la configurazione di esempio è stata copiata. Ciò può compromettere la tua installazione e non è supportato. Leggi la documentazione prima di modificare il file config.php", "PHP %s or higher is required." : "Richiesto PHP %s o superiore", @@ -44,7 +44,6 @@ OC.L10N.register( "Server settings" : "Impostazioni server", "Sharing" : "Condivisione", "Encryption" : "Cifratura", - "Logging" : "Accesso", "Additional settings" : "Impostazioni aggiuntive", "Tips & tricks" : "Suggerimenti e trucchi", "%s enter the database username and name." : "%s digita il nome utente e il nome del database.", @@ -221,6 +220,7 @@ OC.L10N.register( "App can't be installed because it is not compatible with this version of the server" : "L'applicazione non può essere installata perché non è compatibile con questa versione del server", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "L'applicazione non può essere installata poiché contiene l'etichetta <shipped>true<shipped> che è consentita per le applicazioni native", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "L'applicazione non può essere installata poiché la versione nel file info.xml non è la stessa riportata dall'app store", + "Logging" : "Accesso", "Recommended" : "Consigliata", "Microsoft Windows Platform is not supported" : "La piattaforma Microsoft Windows non è supportata", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "L'esecuzione del server Nextcloud sulla piattaforma Microsoft Windows. Ti consigliamo di utilizzare un server Linux in una macchina virtuale.", diff --git a/lib/l10n/it.json b/lib/l10n/it.json index cb4b4139b07..1cf8223f3f4 100644 --- a/lib/l10n/it.json +++ b/lib/l10n/it.json @@ -3,7 +3,7 @@ "This can usually be fixed by giving the webserver write access to the config directory" : "Ciò può essere normalmente corretto fornendo al server web accesso in scrittura alla cartella \"config\"", "See %s" : "Vedi %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Ciò può essere normalmente corretto %sfornendo al server web accesso in scrittura alla cartella \"config\"%s", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "I file dell'applicazione \"%1$s\" (%2$s) non sono stati sostituiti correttamente.", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "I file dell'applicazione %1$s non sono stati sostituiti correttamente. Assicurati che sia una versione compatibile con il server.", "Sample configuration detected" : "Configurazione di esempio rilevata", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "È stato rilevato che la configurazione di esempio è stata copiata. Ciò può compromettere la tua installazione e non è supportato. Leggi la documentazione prima di modificare il file config.php", "PHP %s or higher is required." : "Richiesto PHP %s o superiore", @@ -42,7 +42,6 @@ "Server settings" : "Impostazioni server", "Sharing" : "Condivisione", "Encryption" : "Cifratura", - "Logging" : "Accesso", "Additional settings" : "Impostazioni aggiuntive", "Tips & tricks" : "Suggerimenti e trucchi", "%s enter the database username and name." : "%s digita il nome utente e il nome del database.", @@ -219,6 +218,7 @@ "App can't be installed because it is not compatible with this version of the server" : "L'applicazione non può essere installata perché non è compatibile con questa versione del server", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "L'applicazione non può essere installata poiché contiene l'etichetta <shipped>true<shipped> che è consentita per le applicazioni native", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "L'applicazione non può essere installata poiché la versione nel file info.xml non è la stessa riportata dall'app store", + "Logging" : "Accesso", "Recommended" : "Consigliata", "Microsoft Windows Platform is not supported" : "La piattaforma Microsoft Windows non è supportata", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "L'esecuzione del server Nextcloud sulla piattaforma Microsoft Windows. Ti consigliamo di utilizzare un server Linux in una macchina virtuale.", diff --git a/lib/l10n/ja.js b/lib/l10n/ja.js index b8a47cb094e..11d81383d6f 100644 --- a/lib/l10n/ja.js +++ b/lib/l10n/ja.js @@ -5,6 +5,7 @@ OC.L10N.register( "This can usually be fixed by giving the webserver write access to the config directory" : "多くの場合、これはWebサーバーにconfigディレクトリへの書き込み権限を与えることで解決できます。", "See %s" : "%s を閲覧", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "多くの場合、これは %s Webサーバーにconfigディレクトリ %s への書き込み権限を与えることで解決できます。", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "アプリ %1$s のファイルが正しく置き換えられませんでした。サーバーと互換性のあるバージョンであることを確認してください。", "Sample configuration detected" : "サンプル設定が見つかりました。", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "サンプル設定がコピーされてそのままです。このままではインストールが失敗し、サポート対象外になります。config.phpを変更する前にドキュメントを確認してください。", "PHP %s or higher is required." : "PHP %s 以上が必要です。", @@ -20,6 +21,7 @@ OC.L10N.register( "Server version %s or lower is required." : "サーバーの %s よりも低いバージョンが必要です。", "Unknown filetype" : "不明なファイルタイプ", "Invalid image" : "無効な画像", + "Avatar image is not square" : "アバター画像が正方形ではありません", "today" : "今日", "yesterday" : "1日前", "_%n day ago_::_%n days ago_" : ["%n 日前"], @@ -42,7 +44,6 @@ OC.L10N.register( "Server settings" : "サーバー設定", "Sharing" : "共有", "Encryption" : "暗号化", - "Logging" : "ロギング", "Additional settings" : "追加設定", "Tips & tricks" : "ヒントとコツ", "%s enter the database username and name." : "%s データベース名とデータベースのユーザー名を入力してください。", @@ -100,6 +101,51 @@ OC.L10N.register( "Expiration date is in the past" : "有効期限が切れています", "Cannot set expiration date more than %s days in the future" : "有効期限を%s日以降に設定できません。", "Could not find category \"%s\"" : "カテゴリ \"%s\" が見つかりませんでした", + "Sunday" : "日曜日", + "Monday" : "月曜日", + "Tuesday" : "火曜日", + "Wednesday" : "水曜日", + "Thursday" : "木曜日", + "Friday" : "金曜日", + "Saturday" : "土曜日", + "Sun." : "日", + "Mon." : "月", + "Tue." : "火", + "Wed." : "水", + "Thu." : "木", + "Fri." : "金", + "Sat." : "土", + "Su" : "日", + "Mo" : "月", + "Tu" : "火", + "We" : "水", + "Th" : "木", + "Fr" : "金", + "Sa" : "土", + "January" : "1月", + "February" : "2月", + "March" : "3月", + "April" : "4月", + "May" : "5月", + "June" : "6月", + "July" : "7月", + "August" : "8月", + "September" : "9月", + "October" : "10月", + "November" : "11月", + "December" : "12月", + "Jan." : "1月", + "Feb." : "2月", + "Mar." : "3月", + "Apr." : "4月", + "May." : "5月", + "Jun." : "6月", + "Jul." : "7月", + "Aug." : "8月", + "Sep." : "9月", + "Oct." : "10月", + "Nov." : "11月", + "Dec." : "12月", "Apps" : "アプリ", "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "ユーザー名で利用できる文字列は、次のものです: \"a-z\", \"A-Z\", \"0-9\", \"_.@-\"", "A valid username must be provided" : "有効なユーザー名を指定する必要があります", @@ -115,6 +161,7 @@ OC.L10N.register( "App \"%s\" cannot be installed because appinfo file cannot be read." : "appinfoファイルが読み込めないため、アプリ名 \"%s\" がインストールできません。", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "\"%s\" アプリは、このバージョンのサーバーと互換性がないためインストールされませんでした。", "No app name specified" : "アプリ名が未指定", + "App '%s' could not be installed!" : "'%s' アプリをインストールできませんでした。", "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "次の依存関係が満たされないため、\"%s\" アプリをインストールできません:%s", "a safe home for all your data" : "あなたの全データの安全な家", "File is currently busy, please try again later" : "現在ファイルはビジーです。後でもう一度試してください。", @@ -173,11 +220,18 @@ OC.L10N.register( "App can't be installed because it is not compatible with this version of the server" : "アプリは、このバージョンのサーバーと互換性がないためインストールされませんでした。", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "非shippedアプリには許可されない<shipped>true</shipped>タグが含まれているためにアプリをインストールできません。", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "info.xmlのバージョンがアプリストアのバージョンと合っていないため、アプリはインストールされません", + "Logging" : "ロギング", "Recommended" : "おすすめ", "Microsoft Windows Platform is not supported" : "Microsoft Windows プラットフォームはサポートしていません。", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "マイクロソフト Windowsプラットフォーム上での Nextcloudの動作をサポートしていません。サーバー丸ごと移行する方式をとれない場合は仮想マシンで Linux を動かすことをお勧めします。", "Storage not available" : "ストレージが利用できません", "ownCloud %s or higher is required." : "ownCloud %s 以上が必要です", - "ownCloud %s or lower is required." : "ownCloud %s 以下が必要です" + "ownCloud %s or lower is required." : "ownCloud %s 以下が必要です", + "App \"%s\" cannot be installed because it is not compatible with this version of Nextcloud." : "\"%s\" アプリはこのバージョンのNextcloudと互換性がないためインストールできません。", + "App can't be installed because it is not compatible with this version of Nextcloud" : "このバージョンのNextcloudと互換性がないため、アプリケーションをインストールできません", + "App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" : "info.xml/version のバージョンがアプリストアのバージョンと合っていないため、アプリはインストールされません", + "Hint: You can speed up the upgrade by executing this SQL command manually: ALTER TABLE %s ADD COLUMN checksum varchar(255) DEFAULT NULL AFTER permissions;" : "ヒント:次のSQLコマンドを手動で実行すると、アップグレードを高速化できます: ALTER TABLE %s ADD COLUMN checksum varchar(255) DEFAULT NULL AFTER permissions;", + "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself. Find Linux packages as well as easy to deploy virtual machine images on <a href=\"%s\">%s</a>. For migrating existing installations to Linux you can find some tips and a migration script in <a href=\"%s\">our documentation</a>." : "Microsoft WindowsプラットフォームでのNextcloud Serverの実行はサポートされていません。サーバー自体を移行するオプションがない場合は、仮想マシンでLinuxサーバーを使用することをお勧めします。 <a href=\"%s\"> %s </a>でLinuxパッケージを見つけたり、簡単に仮想マシンイメージを展開したりできます。既存のインストールをLinuxに移行するには、<a href=\"%s\">こちらのドキュメント</a>にいくつかのヒントと移行スクリプトがあります。", + "This can usually be fixed by <a href=\"%s\" target=\"_blank\">giving the webserver write access to the root directory</a>." : "多くの場合、<a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">Webサーバーのルートディレクトリに書き込み権限を与える</a>ことで解決できます。" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/ja.json b/lib/l10n/ja.json index f6117c76723..c7694e53fd6 100644 --- a/lib/l10n/ja.json +++ b/lib/l10n/ja.json @@ -3,6 +3,7 @@ "This can usually be fixed by giving the webserver write access to the config directory" : "多くの場合、これはWebサーバーにconfigディレクトリへの書き込み権限を与えることで解決できます。", "See %s" : "%s を閲覧", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "多くの場合、これは %s Webサーバーにconfigディレクトリ %s への書き込み権限を与えることで解決できます。", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "アプリ %1$s のファイルが正しく置き換えられませんでした。サーバーと互換性のあるバージョンであることを確認してください。", "Sample configuration detected" : "サンプル設定が見つかりました。", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "サンプル設定がコピーされてそのままです。このままではインストールが失敗し、サポート対象外になります。config.phpを変更する前にドキュメントを確認してください。", "PHP %s or higher is required." : "PHP %s 以上が必要です。", @@ -18,6 +19,7 @@ "Server version %s or lower is required." : "サーバーの %s よりも低いバージョンが必要です。", "Unknown filetype" : "不明なファイルタイプ", "Invalid image" : "無効な画像", + "Avatar image is not square" : "アバター画像が正方形ではありません", "today" : "今日", "yesterday" : "1日前", "_%n day ago_::_%n days ago_" : ["%n 日前"], @@ -40,7 +42,6 @@ "Server settings" : "サーバー設定", "Sharing" : "共有", "Encryption" : "暗号化", - "Logging" : "ロギング", "Additional settings" : "追加設定", "Tips & tricks" : "ヒントとコツ", "%s enter the database username and name." : "%s データベース名とデータベースのユーザー名を入力してください。", @@ -98,6 +99,51 @@ "Expiration date is in the past" : "有効期限が切れています", "Cannot set expiration date more than %s days in the future" : "有効期限を%s日以降に設定できません。", "Could not find category \"%s\"" : "カテゴリ \"%s\" が見つかりませんでした", + "Sunday" : "日曜日", + "Monday" : "月曜日", + "Tuesday" : "火曜日", + "Wednesday" : "水曜日", + "Thursday" : "木曜日", + "Friday" : "金曜日", + "Saturday" : "土曜日", + "Sun." : "日", + "Mon." : "月", + "Tue." : "火", + "Wed." : "水", + "Thu." : "木", + "Fri." : "金", + "Sat." : "土", + "Su" : "日", + "Mo" : "月", + "Tu" : "火", + "We" : "水", + "Th" : "木", + "Fr" : "金", + "Sa" : "土", + "January" : "1月", + "February" : "2月", + "March" : "3月", + "April" : "4月", + "May" : "5月", + "June" : "6月", + "July" : "7月", + "August" : "8月", + "September" : "9月", + "October" : "10月", + "November" : "11月", + "December" : "12月", + "Jan." : "1月", + "Feb." : "2月", + "Mar." : "3月", + "Apr." : "4月", + "May." : "5月", + "Jun." : "6月", + "Jul." : "7月", + "Aug." : "8月", + "Sep." : "9月", + "Oct." : "10月", + "Nov." : "11月", + "Dec." : "12月", "Apps" : "アプリ", "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "ユーザー名で利用できる文字列は、次のものです: \"a-z\", \"A-Z\", \"0-9\", \"_.@-\"", "A valid username must be provided" : "有効なユーザー名を指定する必要があります", @@ -113,6 +159,7 @@ "App \"%s\" cannot be installed because appinfo file cannot be read." : "appinfoファイルが読み込めないため、アプリ名 \"%s\" がインストールできません。", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "\"%s\" アプリは、このバージョンのサーバーと互換性がないためインストールされませんでした。", "No app name specified" : "アプリ名が未指定", + "App '%s' could not be installed!" : "'%s' アプリをインストールできませんでした。", "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "次の依存関係が満たされないため、\"%s\" アプリをインストールできません:%s", "a safe home for all your data" : "あなたの全データの安全な家", "File is currently busy, please try again later" : "現在ファイルはビジーです。後でもう一度試してください。", @@ -171,11 +218,18 @@ "App can't be installed because it is not compatible with this version of the server" : "アプリは、このバージョンのサーバーと互換性がないためインストールされませんでした。", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "非shippedアプリには許可されない<shipped>true</shipped>タグが含まれているためにアプリをインストールできません。", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "info.xmlのバージョンがアプリストアのバージョンと合っていないため、アプリはインストールされません", + "Logging" : "ロギング", "Recommended" : "おすすめ", "Microsoft Windows Platform is not supported" : "Microsoft Windows プラットフォームはサポートしていません。", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "マイクロソフト Windowsプラットフォーム上での Nextcloudの動作をサポートしていません。サーバー丸ごと移行する方式をとれない場合は仮想マシンで Linux を動かすことをお勧めします。", "Storage not available" : "ストレージが利用できません", "ownCloud %s or higher is required." : "ownCloud %s 以上が必要です", - "ownCloud %s or lower is required." : "ownCloud %s 以下が必要です" + "ownCloud %s or lower is required." : "ownCloud %s 以下が必要です", + "App \"%s\" cannot be installed because it is not compatible with this version of Nextcloud." : "\"%s\" アプリはこのバージョンのNextcloudと互換性がないためインストールできません。", + "App can't be installed because it is not compatible with this version of Nextcloud" : "このバージョンのNextcloudと互換性がないため、アプリケーションをインストールできません", + "App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" : "info.xml/version のバージョンがアプリストアのバージョンと合っていないため、アプリはインストールされません", + "Hint: You can speed up the upgrade by executing this SQL command manually: ALTER TABLE %s ADD COLUMN checksum varchar(255) DEFAULT NULL AFTER permissions;" : "ヒント:次のSQLコマンドを手動で実行すると、アップグレードを高速化できます: ALTER TABLE %s ADD COLUMN checksum varchar(255) DEFAULT NULL AFTER permissions;", + "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself. Find Linux packages as well as easy to deploy virtual machine images on <a href=\"%s\">%s</a>. For migrating existing installations to Linux you can find some tips and a migration script in <a href=\"%s\">our documentation</a>." : "Microsoft WindowsプラットフォームでのNextcloud Serverの実行はサポートされていません。サーバー自体を移行するオプションがない場合は、仮想マシンでLinuxサーバーを使用することをお勧めします。 <a href=\"%s\"> %s </a>でLinuxパッケージを見つけたり、簡単に仮想マシンイメージを展開したりできます。既存のインストールをLinuxに移行するには、<a href=\"%s\">こちらのドキュメント</a>にいくつかのヒントと移行スクリプトがあります。", + "This can usually be fixed by <a href=\"%s\" target=\"_blank\">giving the webserver write access to the root directory</a>." : "多くの場合、<a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">Webサーバーのルートディレクトリに書き込み権限を与える</a>ことで解決できます。" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/l10n/nb_NO.js b/lib/l10n/nb_NO.js index b66d75a267e..a8c58da4e89 100644 --- a/lib/l10n/nb_NO.js +++ b/lib/l10n/nb_NO.js @@ -42,7 +42,6 @@ OC.L10N.register( "Server settings" : "Tjenerinnstillinger", "Sharing" : "Deling", "Encryption" : "Kryptering", - "Logging" : "Logging", "Additional settings" : "Flere innstillinger", "Tips & tricks" : "Tips og triks", "%s enter the database username and name." : "%s legg inn database brukernavn og navn.", @@ -219,6 +218,7 @@ OC.L10N.register( "App can't be installed because it is not compatible with this version of the server" : "Appen kan ikke installere fordi den ikke er kompatibel med denne tjenerversjonen.", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "App kan ikke installeres fordi den er merket med <shipped>true</shipped> som ikke er tillatt for apper som ikke leveres med systemet", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "App kan ikke installeres fordi versjonen i info.xml ikke er den samme som versjonen som rapporteres fra app-butikken", + "Logging" : "Logging", "Recommended" : "Anbefalt", "Microsoft Windows Platform is not supported" : "Microsoft Windows-plattform støttes ikke", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Kjøring av Nextcloud tjeneren på en Microsoft Windows plattform er ikke støttet. Vi foreslår at du bruker en Linux tjener i en virtuell maskin hvis du ikke har mulighet til å migrere tjeneren selv.", diff --git a/lib/l10n/nb_NO.json b/lib/l10n/nb_NO.json index 45f168b8275..43351d07f07 100644 --- a/lib/l10n/nb_NO.json +++ b/lib/l10n/nb_NO.json @@ -40,7 +40,6 @@ "Server settings" : "Tjenerinnstillinger", "Sharing" : "Deling", "Encryption" : "Kryptering", - "Logging" : "Logging", "Additional settings" : "Flere innstillinger", "Tips & tricks" : "Tips og triks", "%s enter the database username and name." : "%s legg inn database brukernavn og navn.", @@ -217,6 +216,7 @@ "App can't be installed because it is not compatible with this version of the server" : "Appen kan ikke installere fordi den ikke er kompatibel med denne tjenerversjonen.", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "App kan ikke installeres fordi den er merket med <shipped>true</shipped> som ikke er tillatt for apper som ikke leveres med systemet", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "App kan ikke installeres fordi versjonen i info.xml ikke er den samme som versjonen som rapporteres fra app-butikken", + "Logging" : "Logging", "Recommended" : "Anbefalt", "Microsoft Windows Platform is not supported" : "Microsoft Windows-plattform støttes ikke", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Kjøring av Nextcloud tjeneren på en Microsoft Windows plattform er ikke støttet. Vi foreslår at du bruker en Linux tjener i en virtuell maskin hvis du ikke har mulighet til å migrere tjeneren selv.", diff --git a/lib/l10n/nl.js b/lib/l10n/nl.js index ed9100bfaf8..150354a1f0a 100644 --- a/lib/l10n/nl.js +++ b/lib/l10n/nl.js @@ -5,7 +5,7 @@ OC.L10N.register( "This can usually be fixed by giving the webserver write access to the config directory" : "Dit kan hersteld worden door de webserver schrijfrechten te geven op de de config directory", "See %s" : "Zie %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Dit kan hersteld worden door de webserver %sschrijfrechten te geven op de de config directory%s", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "Het bestand van de app \"%$1s\" (%$2s) zijn niet correct vervangen.", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "De bestanden van de app %$1s zijn niet correct vervangen. Zorg ervoor dat hij compatible is met de server.", "Sample configuration detected" : "Voorbeeldconfiguratie gevonden", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Blijkbaar is de voorbeeldconfiguratie gekopieerd. Dit kan je installatie beschadigen en wordt dan ook niet ondersteund. Lees de documentatie voordat je wijzigingen aan config.php doorvoert", "PHP %s or higher is required." : "PHP %s of hoger vereist.", @@ -44,7 +44,6 @@ OC.L10N.register( "Server settings" : "Serverinstellingen", "Sharing" : "Delen", "Encryption" : "Versleuteling", - "Logging" : "Logging", "Additional settings" : "Aanvullende instellingen", "Tips & tricks" : "Tips & trucs", "%s enter the database username and name." : "%s voer de database gebruikersnaam en naam in .", @@ -221,6 +220,7 @@ OC.L10N.register( "App can't be installed because it is not compatible with this version of the server" : "De app kan niet worden geïnstalleerd, omdat die niet compatible is met deze versie van de server", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "De app kan niet worden geïnstalleerd, omdat het de <shipped>true</shipped> markering bevat die niet is toegestaan voor niet gepubliceerde apps", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "De app kan niet worden geïnstalleerd, omdat de versie in info.xml niet dezelfde is als de versie zoals die in de app store staat vermeld", + "Logging" : "Logging", "Recommended" : "Aanbevolen", "Microsoft Windows Platform is not supported" : "Microsoft Windows Platform wordt niet ondersteund", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Het draaien van Nextcloud server op het Microsoft Windows platform wordt niet ondersteund. We adviseren je om een Linux server op een virtuele server te gebruiken als je geen mogelijkheid hebt om een server zelf te migreren.", diff --git a/lib/l10n/nl.json b/lib/l10n/nl.json index 53394c890ab..598be59ad14 100644 --- a/lib/l10n/nl.json +++ b/lib/l10n/nl.json @@ -3,7 +3,7 @@ "This can usually be fixed by giving the webserver write access to the config directory" : "Dit kan hersteld worden door de webserver schrijfrechten te geven op de de config directory", "See %s" : "Zie %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "Dit kan hersteld worden door de webserver %sschrijfrechten te geven op de de config directory%s", - "The files of the app \"%$1s\" (%$2s) were not replaced correctly." : "Het bestand van de app \"%$1s\" (%$2s) zijn niet correct vervangen.", + "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "De bestanden van de app %$1s zijn niet correct vervangen. Zorg ervoor dat hij compatible is met de server.", "Sample configuration detected" : "Voorbeeldconfiguratie gevonden", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Blijkbaar is de voorbeeldconfiguratie gekopieerd. Dit kan je installatie beschadigen en wordt dan ook niet ondersteund. Lees de documentatie voordat je wijzigingen aan config.php doorvoert", "PHP %s or higher is required." : "PHP %s of hoger vereist.", @@ -42,7 +42,6 @@ "Server settings" : "Serverinstellingen", "Sharing" : "Delen", "Encryption" : "Versleuteling", - "Logging" : "Logging", "Additional settings" : "Aanvullende instellingen", "Tips & tricks" : "Tips & trucs", "%s enter the database username and name." : "%s voer de database gebruikersnaam en naam in .", @@ -219,6 +218,7 @@ "App can't be installed because it is not compatible with this version of the server" : "De app kan niet worden geïnstalleerd, omdat die niet compatible is met deze versie van de server", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "De app kan niet worden geïnstalleerd, omdat het de <shipped>true</shipped> markering bevat die niet is toegestaan voor niet gepubliceerde apps", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "De app kan niet worden geïnstalleerd, omdat de versie in info.xml niet dezelfde is als de versie zoals die in de app store staat vermeld", + "Logging" : "Logging", "Recommended" : "Aanbevolen", "Microsoft Windows Platform is not supported" : "Microsoft Windows Platform wordt niet ondersteund", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Het draaien van Nextcloud server op het Microsoft Windows platform wordt niet ondersteund. We adviseren je om een Linux server op een virtuele server te gebruiken als je geen mogelijkheid hebt om een server zelf te migreren.", diff --git a/lib/l10n/pl.js b/lib/l10n/pl.js index 67f241424d4..cfbfaea9199 100644 --- a/lib/l10n/pl.js +++ b/lib/l10n/pl.js @@ -41,7 +41,6 @@ OC.L10N.register( "Server settings" : "Ustawienia serwera", "Sharing" : "Udostępnianie", "Encryption" : "Szyfrowanie", - "Logging" : "Logowanie", "Additional settings" : "Ustawienia dodatkowe", "Tips & tricks" : "Porady i wskazówki", "%s enter the database username." : "%s wpisz nazwę użytkownika do bazy", @@ -182,6 +181,7 @@ OC.L10N.register( "Signature could not get checked. Please contact the app developer and check your admin screen." : "Sygnatura nie mogła zostać sprawdzona. Proszę o skontaktownie się z twórcą aplikacji i sprawdzenie panelu administratora.", "App can't be installed because of not allowed code in the App" : "Aplikacja nie może być zainstalowany ponieważ nie dopuszcza kod w aplikacji", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Aplikacja nie może być zainstalowana ponieważ true tag nie jest <shipped>true</shipped> , co nie jest dozwolone dla aplikacji nie wysłanych", + "Logging" : "Logowanie", "Recommended" : "Polecane", "Microsoft Windows Platform is not supported" : "Platforma Microsoft Windows nie jest wspierana", "Storage not available" : "Pamięć nie dostępna", diff --git a/lib/l10n/pl.json b/lib/l10n/pl.json index 89f945a8650..7511c6787e6 100644 --- a/lib/l10n/pl.json +++ b/lib/l10n/pl.json @@ -39,7 +39,6 @@ "Server settings" : "Ustawienia serwera", "Sharing" : "Udostępnianie", "Encryption" : "Szyfrowanie", - "Logging" : "Logowanie", "Additional settings" : "Ustawienia dodatkowe", "Tips & tricks" : "Porady i wskazówki", "%s enter the database username." : "%s wpisz nazwę użytkownika do bazy", @@ -180,6 +179,7 @@ "Signature could not get checked. Please contact the app developer and check your admin screen." : "Sygnatura nie mogła zostać sprawdzona. Proszę o skontaktownie się z twórcą aplikacji i sprawdzenie panelu administratora.", "App can't be installed because of not allowed code in the App" : "Aplikacja nie może być zainstalowany ponieważ nie dopuszcza kod w aplikacji", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Aplikacja nie może być zainstalowana ponieważ true tag nie jest <shipped>true</shipped> , co nie jest dozwolone dla aplikacji nie wysłanych", + "Logging" : "Logowanie", "Recommended" : "Polecane", "Microsoft Windows Platform is not supported" : "Platforma Microsoft Windows nie jest wspierana", "Storage not available" : "Pamięć nie dostępna", diff --git a/lib/l10n/ru.js b/lib/l10n/ru.js index 00cf3969e22..72876e799cd 100644 --- a/lib/l10n/ru.js +++ b/lib/l10n/ru.js @@ -43,7 +43,6 @@ OC.L10N.register( "Server settings" : "Настройки сервера", "Sharing" : "Общий доступ", "Encryption" : "Шифрование", - "Logging" : "Журнал", "Additional settings" : "Дополнительные настройки", "Tips & tricks" : "Советы и трюки", "%s enter the database username and name." : "%s укажите имя пользователя и название для базы данных.", @@ -220,6 +219,7 @@ OC.L10N.register( "App can't be installed because it is not compatible with this version of the server" : "Приложение не может быть установлено, потому что оно несовместимо с этой версией сервера", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Приложение невозможно установить. Оно содержит параметр <shipped>true</shipped> который не допустим для приложений, не входящих в поставку.", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Приложение невозможно установить. Версия в файле info.xml не совпадает с версией заявленной в магазине приложений", + "Logging" : "Журнал", "Recommended" : "Рекомендовано", "Microsoft Windows Platform is not supported" : "Платформа Microsoft Windows не поддерживается", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Работа Nextcloud Server на платформе Microsoft Windows не поддерживается. Мы рекомендуем использовать Linux в качестве виртуальный машины, если у вас нет возможности перевести сам сервер.", diff --git a/lib/l10n/ru.json b/lib/l10n/ru.json index 0b43e8ae35a..c17b3ffe609 100644 --- a/lib/l10n/ru.json +++ b/lib/l10n/ru.json @@ -41,7 +41,6 @@ "Server settings" : "Настройки сервера", "Sharing" : "Общий доступ", "Encryption" : "Шифрование", - "Logging" : "Журнал", "Additional settings" : "Дополнительные настройки", "Tips & tricks" : "Советы и трюки", "%s enter the database username and name." : "%s укажите имя пользователя и название для базы данных.", @@ -218,6 +217,7 @@ "App can't be installed because it is not compatible with this version of the server" : "Приложение не может быть установлено, потому что оно несовместимо с этой версией сервера", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "Приложение невозможно установить. Оно содержит параметр <shipped>true</shipped> который не допустим для приложений, не входящих в поставку.", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "Приложение невозможно установить. Версия в файле info.xml не совпадает с версией заявленной в магазине приложений", + "Logging" : "Журнал", "Recommended" : "Рекомендовано", "Microsoft Windows Platform is not supported" : "Платформа Microsoft Windows не поддерживается", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "Работа Nextcloud Server на платформе Microsoft Windows не поддерживается. Мы рекомендуем использовать Linux в качестве виртуальный машины, если у вас нет возможности перевести сам сервер.", diff --git a/lib/l10n/zh_TW.js b/lib/l10n/zh_TW.js index acba2269658..417c991337d 100644 --- a/lib/l10n/zh_TW.js +++ b/lib/l10n/zh_TW.js @@ -42,7 +42,6 @@ OC.L10N.register( "Server settings" : "伺服器設定", "Sharing" : "分享", "Encryption" : "加密", - "Logging" : "記錄", "Additional settings" : "其他設定", "Tips & tricks" : "使用祕訣", "%s enter the database username and name." : "%s 輸入資料庫名稱及使用者名稱", @@ -100,6 +99,51 @@ OC.L10N.register( "Expiration date is in the past" : "到期日是之前的時間", "Cannot set expiration date more than %s days in the future" : "無法設定到期日超過未來%s天", "Could not find category \"%s\"" : "找不到分類:\"%s\"", + "Sunday" : "週日", + "Monday" : "週一", + "Tuesday" : "週二", + "Wednesday" : "週三", + "Thursday" : "週四", + "Friday" : "週五", + "Saturday" : "週六", + "Sun." : "日", + "Mon." : "一", + "Tue." : "二", + "Wed." : "三", + "Thu." : "四", + "Fri." : "五", + "Sat." : "六", + "Su" : "日", + "Mo" : "一", + "Tu" : "二", + "We" : "三", + "Th" : "四", + "Fr" : "五", + "Sa" : "六", + "January" : "一月", + "February" : "二月", + "March" : "三月", + "April" : "四月", + "May" : "五月", + "June" : "六月", + "July" : "七月", + "August" : "八月", + "September" : "九月", + "October" : "十月", + "November" : "十一月", + "December" : "十二月", + "Jan." : "一月", + "Feb." : "二月", + "Mar." : "三月", + "Apr." : "四月", + "May." : "五月", + "Jun." : "六月", + "Jul." : "七月", + "Aug." : "八月", + "Sep." : "九月", + "Oct." : "十月", + "Nov." : "十一月", + "Dec." : "十二月", "Apps" : "應用程式", "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "使用者名稱當中只能包含下列字元:\"a-z\", \"A-Z\", \"0-9\", 和 \"_.@-'\"", "A valid username must be provided" : "必須提供一個有效的用戶名", @@ -173,6 +217,7 @@ OC.L10N.register( "App can't be installed because it is not compatible with this version of the server" : "程式無法安裝,因為伺服器版本不符。", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "無法安裝應用程式,因為它包含了 <shipped>true</shipped> 標籤,在未發行的應用程式當中這是不允許的", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "程式無法安裝,因為info.xml檔案中版本與app商店中要求不同。", + "Logging" : "記錄", "Recommended" : "建議", "Microsoft Windows Platform is not supported" : "不支援微軟Windows系統", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "微軟Windows不支援Nextcloud伺服器,如果您一定要使用,我們建議您在虛擬機中安裝Linux版本伺服器。", diff --git a/lib/l10n/zh_TW.json b/lib/l10n/zh_TW.json index 1356943df67..24f4eb07ec8 100644 --- a/lib/l10n/zh_TW.json +++ b/lib/l10n/zh_TW.json @@ -40,7 +40,6 @@ "Server settings" : "伺服器設定", "Sharing" : "分享", "Encryption" : "加密", - "Logging" : "記錄", "Additional settings" : "其他設定", "Tips & tricks" : "使用祕訣", "%s enter the database username and name." : "%s 輸入資料庫名稱及使用者名稱", @@ -98,6 +97,51 @@ "Expiration date is in the past" : "到期日是之前的時間", "Cannot set expiration date more than %s days in the future" : "無法設定到期日超過未來%s天", "Could not find category \"%s\"" : "找不到分類:\"%s\"", + "Sunday" : "週日", + "Monday" : "週一", + "Tuesday" : "週二", + "Wednesday" : "週三", + "Thursday" : "週四", + "Friday" : "週五", + "Saturday" : "週六", + "Sun." : "日", + "Mon." : "一", + "Tue." : "二", + "Wed." : "三", + "Thu." : "四", + "Fri." : "五", + "Sat." : "六", + "Su" : "日", + "Mo" : "一", + "Tu" : "二", + "We" : "三", + "Th" : "四", + "Fr" : "五", + "Sa" : "六", + "January" : "一月", + "February" : "二月", + "March" : "三月", + "April" : "四月", + "May" : "五月", + "June" : "六月", + "July" : "七月", + "August" : "八月", + "September" : "九月", + "October" : "十月", + "November" : "十一月", + "December" : "十二月", + "Jan." : "一月", + "Feb." : "二月", + "Mar." : "三月", + "Apr." : "四月", + "May." : "五月", + "Jun." : "六月", + "Jul." : "七月", + "Aug." : "八月", + "Sep." : "九月", + "Oct." : "十月", + "Nov." : "十一月", + "Dec." : "十二月", "Apps" : "應用程式", "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "使用者名稱當中只能包含下列字元:\"a-z\", \"A-Z\", \"0-9\", 和 \"_.@-'\"", "A valid username must be provided" : "必須提供一個有效的用戶名", @@ -171,6 +215,7 @@ "App can't be installed because it is not compatible with this version of the server" : "程式無法安裝,因為伺服器版本不符。", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" : "無法安裝應用程式,因為它包含了 <shipped>true</shipped> 標籤,在未發行的應用程式當中這是不允許的", "App can't be installed because the version in info.xml is not the same as the version reported from the app store" : "程式無法安裝,因為info.xml檔案中版本與app商店中要求不同。", + "Logging" : "記錄", "Recommended" : "建議", "Microsoft Windows Platform is not supported" : "不支援微軟Windows系統", "Running Nextcloud Server on the Microsoft Windows platform is not supported. We suggest you use a Linux server in a virtual machine if you have no option for migrating the server itself." : "微軟Windows不支援Nextcloud伺服器,如果您一定要使用,我們建議您在虛擬機中安裝Linux版本伺服器。", diff --git a/lib/private/Accounts/AccountManager.php b/lib/private/Accounts/AccountManager.php new file mode 100644 index 00000000000..6496a521326 --- /dev/null +++ b/lib/private/Accounts/AccountManager.php @@ -0,0 +1,201 @@ +<?php +/** + * @author Björn Schießle <bjoern@schiessle.org> + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2016, Björn Schießle + * @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 OC\Accounts; + +use OCP\IDBConnection; +use OCP\IUser; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\GenericEvent; + +/** + * Class AccountManager + * + * Manage system accounts table + * + * @group DB + * @package OC\Accounts + */ +class AccountManager { + + /** nobody can see my account details */ + const VISIBILITY_PRIVATE = 'private'; + /** only contacts, especially trusted servers can see my contact details */ + const VISIBILITY_CONTACTS_ONLY = 'contacts'; + /** every body ca see my contact detail, will be published to the lookup server */ + const VISIBILITY_PUBLIC = 'public'; + + const PROPERTY_AVATAR = 'avatar'; + const PROPERTY_DISPLAYNAME = 'displayname'; + const PROPERTY_PHONE = 'phone'; + const PROPERTY_EMAIL = 'email'; + const PROPERTY_WEBSITE = 'website'; + const PROPERTY_ADDRESS = 'address'; + const PROPERTY_TWITTER = 'twitter'; + + /** @var IDBConnection database connection */ + private $connection; + + /** @var string table name */ + private $table = 'accounts'; + + /** @var EventDispatcherInterface */ + private $eventDispatcher; + + /** + * AccountManager constructor. + * + * @param IDBConnection $connection + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(IDBConnection $connection, EventDispatcherInterface $eventDispatcher) { + $this->connection = $connection; + $this->eventDispatcher = $eventDispatcher; + } + + /** + * update user record + * + * @param IUser $user + * @param $data + */ + public function updateUser(IUser $user, $data) { + $userData = $this->getUser($user); + if (empty($userData)) { + $this->insertNewUser($user, $data); + } else { + $this->updateExistingUser($user, $data); + } + + $this->eventDispatcher->dispatch( + 'OC\AccountManager::userUpdated', + new GenericEvent($user) + ); + } + + /** + * get stored data from a given user + * + * @param IUser $user + * @return array + */ + public function getUser(IUser $user) { + $uid = $user->getUID(); + $query = $this->connection->getQueryBuilder(); + $query->select('data')->from($this->table) + ->where($query->expr()->eq('uid', $query->createParameter('uid'))) + ->setParameter('uid', $uid); + $query->execute(); + $result = $query->execute()->fetchAll(); + + if (empty($result)) { + $userData = $this->buildDefaultUserRecord($user); + $this->insertNewUser($user, $userData); + return $userData; + } + + return json_decode($result[0]['data'], true); + } + + /** + * add new user to accounts table + * + * @param IUser $user + * @param array $data + */ + protected function insertNewUser(IUser $user, $data) { + $uid = $user->getUID(); + $jsonEncodedData = json_encode($data); + $query = $this->connection->getQueryBuilder(); + $query->insert($this->table) + ->values( + [ + 'uid' => $query->createNamedParameter($uid), + 'data' => $query->createNamedParameter($jsonEncodedData), + ] + ) + ->execute(); + } + + /** + * update existing user in accounts table + * + * @param IUser $user + * @param array $data + */ + protected function updateExistingUser(IUser $user, $data) { + $uid = $user->getUID(); + $jsonEncodedData = json_encode($data); + $query = $this->connection->getQueryBuilder(); + $query->update($this->table) + ->set('data', $query->createNamedParameter($jsonEncodedData)) + ->where($query->expr()->eq('uid', $query->createNamedParameter($uid))) + ->execute(); + } + + /** + * build default user record in case not data set exists yet + * + * @param IUser $user + * @return array + */ + protected function buildDefaultUserRecord(IUser $user) { + return [ + self::PROPERTY_DISPLAYNAME => + [ + 'value' => $user->getDisplayName(), + 'scope' => self::VISIBILITY_CONTACTS_ONLY, + ], + self::PROPERTY_ADDRESS => + [ + 'value' => '', + 'scope' => self::VISIBILITY_PRIVATE, + ], + self::PROPERTY_WEBSITE => + [ + 'value' => '', + 'scope' => self::VISIBILITY_PRIVATE, + ], + self::PROPERTY_EMAIL => + [ + 'value' => $user->getEMailAddress(), + 'scope' => self::VISIBILITY_CONTACTS_ONLY, + ], + self::PROPERTY_AVATAR => + [ + 'scope' => self::VISIBILITY_CONTACTS_ONLY + ], + self::PROPERTY_PHONE => + [ + 'value' => '', + 'scope' => self::VISIBILITY_PRIVATE, + ], + self::PROPERTY_TWITTER => + [ + 'value' => '', + 'scope' => self::VISIBILITY_PRIVATE, + ], + ]; + } + +} diff --git a/lib/private/Activity/Event.php b/lib/private/Activity/Event.php index df6756940a0..a66ebd3c906 100644 --- a/lib/private/Activity/Event.php +++ b/lib/private/Activity/Event.php @@ -1,6 +1,7 @@ <?php /** * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> * * @author Joas Schilling <coding@schilljs.com> * @author Phil Davis <phil.davis@inf.org> diff --git a/lib/private/Activity/Manager.php b/lib/private/Activity/Manager.php index f102d2576fd..a8810a3e16b 100644 --- a/lib/private/Activity/Manager.php +++ b/lib/private/Activity/Manager.php @@ -1,6 +1,7 @@ <?php /** * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> * * @author Björn Schießle <bjoern@schiessle.org> * @author Joas Schilling <coding@schilljs.com> diff --git a/lib/private/AllConfig.php b/lib/private/AllConfig.php index af26d30d8e9..4e13d70371b 100644 --- a/lib/private/AllConfig.php +++ b/lib/private/AllConfig.php @@ -215,11 +215,13 @@ class AllConfig implements \OCP\IConfig { // TODO - FIXME $this->fixDIInit(); - if (isset($this->userCache[$userId][$appName][$key])) { - if ($this->userCache[$userId][$appName][$key] === (string)$value) { - return; - } else if ($preCondition !== null && $this->userCache[$userId][$appName][$key] !== (string)$preCondition) { + $prevValue = $this->getUserValue($userId, $appName, $key, null); + + if ($prevValue !== null) { + if ($prevValue === (string)$value) { return; + } else if ($preCondition !== null && $prevValue !== (string)$preCondition) { + throw new PreConditionNotMetException(); } else { $qb = $this->connection->getQueryBuilder(); $qb->update('preferences') diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index 55fd575e129..fca5c9b87ac 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -31,6 +31,7 @@ namespace OC\App; +use OCP\App\AppPathNotFoundException; use OCP\App\IAppManager; use OCP\App\ManagerEvent; use OCP\IAppConfig; @@ -266,6 +267,21 @@ class AppManager implements IAppManager { } /** + * Get the directory for the given app. + * + * @param string $appId + * @return string + * @throws AppPathNotFoundException if app folder can't be found + */ + public function getAppPath($appId) { + $appPath = \OC_App::getAppPath($appId); + if($appPath === false) { + throw new AppPathNotFoundException('Could not find path for ' . $appId); + } + return $appPath; + } + + /** * Clear the cached list of apps when enabling/disabling an app */ public function clearAppsCache() { diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php index e1516c47ed6..48c9b6f4589 100644 --- a/lib/private/AppFramework/DependencyInjection/DIContainer.php +++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php @@ -383,6 +383,7 @@ class DIContainer extends SimpleContainer implements IAppContainer { $app->getServer()->getNavigationManager(), $app->getServer()->getURLGenerator(), $app->getServer()->getLogger(), + $app->getServer()->getSession(), $c['AppName'], $app->isLoggedIn(), $app->isAdminUser(), diff --git a/lib/private/AppFramework/Http/Output.php b/lib/private/AppFramework/Http/Output.php index 85f0e6f8feb..1d77350b1a2 100644 --- a/lib/private/AppFramework/Http/Output.php +++ b/lib/private/AppFramework/Http/Output.php @@ -48,12 +48,17 @@ class Output implements IOutput { } /** - * @param string $path + * @param string|resource $path or file handle * * @return bool false if an error occurred */ public function setReadfile($path) { - return @readfile($path); + if (is_resource($path)) { + $output = fopen('php://output', 'w'); + return stream_copy_to_stream($path, $output) > 0; + } else { + return @readfile($path); + } } /** diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php new file mode 100644 index 00000000000..1ecd463b004 --- /dev/null +++ b/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php @@ -0,0 +1,37 @@ +<?php + +/** + * @copyright Copyright (c) 2016 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 OC\AppFramework\Middleware\Security\Exceptions; + +use OCP\AppFramework\Http; + +/** + * Class NotConfirmedException is thrown when a resource has been requested by a + * user that has not confirmed their password in the last 30 minutes. + * + * @package OC\AppFramework\Middleware\Security\Exceptions + */ +class NotConfirmedException extends SecurityException { + public function __construct() { + parent::__construct('Password confirmation is required', Http::STATUS_FORBIDDEN); + } +} diff --git a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php index 183e55740ea..d5f7a7660a7 100644 --- a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php @@ -32,6 +32,7 @@ namespace OC\AppFramework\Middleware\Security; use OC\AppFramework\Middleware\Security\Exceptions\AppNotEnabledException; use OC\AppFramework\Middleware\Security\Exceptions\CrossSiteRequestForgeryException; use OC\AppFramework\Middleware\Security\Exceptions\NotAdminException; +use OC\AppFramework\Middleware\Security\Exceptions\NotConfirmedException; use OC\AppFramework\Middleware\Security\Exceptions\NotLoggedInException; use OC\AppFramework\Middleware\Security\Exceptions\StrictCookieMissingException; use OC\AppFramework\Utility\ControllerMethodReflector; @@ -47,6 +48,7 @@ use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\OCSController; use OCP\INavigationManager; +use OCP\ISession; use OCP\IURLGenerator; use OCP\IRequest; use OCP\ILogger; @@ -73,6 +75,8 @@ class SecurityMiddleware extends Middleware { private $urlGenerator; /** @var ILogger */ private $logger; + /** @var ISession */ + private $session; /** @var bool */ private $isLoggedIn; /** @var bool */ @@ -90,6 +94,7 @@ class SecurityMiddleware extends Middleware { * @param INavigationManager $navigationManager * @param IURLGenerator $urlGenerator * @param ILogger $logger + * @param ISession $session * @param string $appName * @param bool $isLoggedIn * @param bool $isAdminUser @@ -102,6 +107,7 @@ class SecurityMiddleware extends Middleware { INavigationManager $navigationManager, IURLGenerator $urlGenerator, ILogger $logger, + ISession $session, $appName, $isLoggedIn, $isAdminUser, @@ -114,6 +120,7 @@ class SecurityMiddleware extends Middleware { $this->appName = $appName; $this->urlGenerator = $urlGenerator; $this->logger = $logger; + $this->session = $session; $this->isLoggedIn = $isLoggedIn; $this->isAdminUser = $isAdminUser; $this->contentSecurityPolicyManager = $contentSecurityPolicyManager; @@ -150,6 +157,13 @@ class SecurityMiddleware extends Middleware { } } + if ($this->reflector->hasAnnotation('PasswordConfirmationRequired')) { + $lastConfirm = (int) $this->session->get('last-password-confirm'); + if ($lastConfirm < (time() - (30 * 60 + 15))) { // allow 15 seconds delay + throw new NotConfirmedException(); + } + } + // Check for strict cookie requirement if($this->reflector->hasAnnotation('StrictCookieRequired') || !$this->reflector->hasAnnotation('NoCSRFRequired')) { if(!$this->request->passesStrictCookieCheck()) { diff --git a/lib/private/Authentication/Token/DefaultToken.php b/lib/private/Authentication/Token/DefaultToken.php index faef2f73b33..127430ea6cb 100644 --- a/lib/private/Authentication/Token/DefaultToken.php +++ b/lib/private/Authentication/Token/DefaultToken.php @@ -87,6 +87,17 @@ class DefaultToken extends Entity implements IToken { */ protected $lastCheck; + /** + * @var string + */ + protected $scope; + + public function __construct() { + $this->addType('type', 'int'); + $this->addType('lastActivity', 'int'); + $this->addType('lastCheck', 'int'); + } + public function getId() { return $this->id; } @@ -119,6 +130,7 @@ class DefaultToken extends Entity implements IToken { 'name' => $this->name, 'lastActivity' => $this->lastActivity, 'type' => $this->type, + 'scope' => $this->getScopeAsArray() ]; } @@ -140,4 +152,25 @@ class DefaultToken extends Entity implements IToken { return parent::setLastCheck($time); } + public function getScope() { + return parent::getScope(); + } + + public function getScopeAsArray() { + $scope = json_decode($this->getScope(), true); + if (!$scope) { + return [ + 'filesystem'=> true + ]; + } + return $scope; + } + + public function setScope($scope) { + if (is_array($scope)) { + parent::setScope(json_encode($scope)); + } else { + parent::setScope((string)$scope); + } + } } diff --git a/lib/private/Authentication/Token/DefaultTokenMapper.php b/lib/private/Authentication/Token/DefaultTokenMapper.php index 752974ff240..8848cd3ec56 100644 --- a/lib/private/Authentication/Token/DefaultTokenMapper.php +++ b/lib/private/Authentication/Token/DefaultTokenMapper.php @@ -72,10 +72,9 @@ class DefaultTokenMapper extends Mapper { public function getToken($token) { /* @var $qb IQueryBuilder */ $qb = $this->db->getQueryBuilder(); - $result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'remember', 'token', 'last_activity', 'last_check') + $result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'remember', 'token', 'last_activity', 'last_check', 'scope') ->from('authtoken') - ->where($qb->expr()->eq('token', $qb->createParameter('token'))) - ->setParameter('token', $token) + ->where($qb->expr()->eq('token', $qb->createNamedParameter($token))) ->execute(); $data = $result->fetch(); @@ -83,6 +82,30 @@ class DefaultTokenMapper extends Mapper { if ($data === false) { throw new DoesNotExistException('token does not exist'); } +; + return DefaultToken::fromRow($data); + } + + /** + * Get the token for $id + * + * @param string $id + * @throws DoesNotExistException + * @return DefaultToken + */ + public function getTokenById($id) { + /* @var $qb IQueryBuilder */ + $qb = $this->db->getQueryBuilder(); + $result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'token', 'last_activity', 'last_check', 'scope') + ->from('authtoken') + ->where($qb->expr()->eq('id', $qb->createNamedParameter($id))) + ->execute(); + + $data = $result->fetch(); + $result->closeCursor(); + if ($data === false) { + throw new DoesNotExistException('token does not exist'); + }; return DefaultToken::fromRow($data); } @@ -98,7 +121,7 @@ class DefaultTokenMapper extends Mapper { public function getTokenByUser(IUser $user) { /* @var $qb IQueryBuilder */ $qb = $this->db->getQueryBuilder(); - $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'remember', 'token', 'last_activity', 'last_check') + $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'remember', 'token', 'last_activity', 'last_check', 'scope') ->from('authtoken') ->where($qb->expr()->eq('uid', $qb->createNamedParameter($user->getUID()))) ->setMaxResults(1000); diff --git a/lib/private/Authentication/Token/DefaultTokenProvider.php b/lib/private/Authentication/Token/DefaultTokenProvider.php index 87f434c684c..ec4cc10c269 100644 --- a/lib/private/Authentication/Token/DefaultTokenProvider.php +++ b/lib/private/Authentication/Token/DefaultTokenProvider.php @@ -145,7 +145,7 @@ class DefaultTokenProvider implements IProvider { } /** - * Get a token by token id + * Get a token by token * * @param string $tokenId * @throws InvalidTokenException @@ -160,6 +160,21 @@ class DefaultTokenProvider implements IProvider { } /** + * Get a token by token id + * + * @param string $tokenId + * @throws InvalidTokenException + * @return DefaultToken + */ + public function getTokenById($tokenId) { + try { + return $this->mapper->getTokenById($tokenId); + } catch (DoesNotExistException $ex) { + throw new InvalidTokenException(); + } + } + + /** * @param string $oldSessionId * @param string $sessionId * @throws InvalidTokenException @@ -237,10 +252,10 @@ class DefaultTokenProvider implements IProvider { */ public function invalidateOldTokens() { $olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24); - $this->logger->info('Invalidating session tokens older than ' . date('c', $olderThan)); + $this->logger->debug('Invalidating session tokens older than ' . date('c', $olderThan)); $this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER); $rememberThreshold = $this->time->getTime() - (int) $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); - $this->logger->info('Invalidating remembered session tokens older than ' . date('c', $rememberThreshold)); + $this->logger->debug('Invalidating remembered session tokens older than ' . date('c', $rememberThreshold)); $this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER); } diff --git a/lib/private/Authentication/Token/IProvider.php b/lib/private/Authentication/Token/IProvider.php index ce14a5880c5..9f280263d76 100644 --- a/lib/private/Authentication/Token/IProvider.php +++ b/lib/private/Authentication/Token/IProvider.php @@ -50,7 +50,16 @@ interface IProvider { * @throws InvalidTokenException * @return IToken */ - public function getToken($tokenId) ; + public function getToken($tokenId); + + /** + * Get a token by token id + * + * @param string $tokenId + * @throws InvalidTokenException + * @return DefaultToken + */ + public function getTokenById($tokenId); /** * Duplicate an existing session token diff --git a/lib/private/Authentication/Token/IToken.php b/lib/private/Authentication/Token/IToken.php index 14811dd3201..49745b266c4 100644 --- a/lib/private/Authentication/Token/IToken.php +++ b/lib/private/Authentication/Token/IToken.php @@ -67,9 +67,30 @@ interface IToken extends JsonSerializable { public function getLastCheck(); /** - * Get the timestamp of the last password check + * Set the timestamp of the last password check * * @param int $time */ public function setLastCheck($time); + + /** + * Get the authentication scope for this token + * + * @return string + */ + public function getScope(); + + /** + * Get the authentication scope for this token + * + * @return array + */ + public function getScopeAsArray(); + + /** + * Set the authentication scope for this token + * + * @param array $scope + */ + public function setScope($scope); } diff --git a/lib/private/DB/QueryBuilder/QuoteHelper.php b/lib/private/DB/QueryBuilder/QuoteHelper.php index 6d15cec5a05..041718bce5a 100644 --- a/lib/private/DB/QueryBuilder/QuoteHelper.php +++ b/lib/private/DB/QueryBuilder/QuoteHelper.php @@ -61,6 +61,11 @@ class QuoteHelper { throw new \InvalidArgumentException('Only strings, Literals and Parameters are allowed'); } + $string = str_replace(' AS ', ' as ', $string); + if (substr_count($string, ' as ')) { + return implode(' as ', array_map([$this, 'quoteColumnName'], explode(' as ', $string, 2))); + } + if (substr_count($string, '.')) { list($alias, $columnName) = explode('.', $string, 2); diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index 5083b99b862..3a3f51488e6 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -142,26 +142,38 @@ class Cache implements ICache { } return $data; } else { - //fix types - $data['fileid'] = (int)$data['fileid']; - $data['parent'] = (int)$data['parent']; - $data['size'] = 0 + $data['size']; - $data['mtime'] = (int)$data['mtime']; - $data['storage_mtime'] = (int)$data['storage_mtime']; - $data['encryptedVersion'] = (int)$data['encrypted']; - $data['encrypted'] = (bool)$data['encrypted']; - $data['storage'] = $this->storageId; - $data['mimetype'] = $this->mimetypeLoader->getMimetypeById($data['mimetype']); - $data['mimepart'] = $this->mimetypeLoader->getMimetypeById($data['mimepart']); - if ($data['storage_mtime'] == 0) { - $data['storage_mtime'] = $data['mtime']; - } - $data['permissions'] = (int)$data['permissions']; - return new CacheEntry($data); + return self::cacheEntryFromData($data, $this->storageId, $this->mimetypeLoader); } } /** + * Create a CacheEntry from database row + * + * @param array $data + * @param string $storageId + * @param IMimeTypeLoader $mimetypeLoader + * @return CacheEntry + */ + public static function cacheEntryFromData($data, $storageId, IMimeTypeLoader $mimetypeLoader) { + //fix types + $data['fileid'] = (int)$data['fileid']; + $data['parent'] = (int)$data['parent']; + $data['size'] = 0 + $data['size']; + $data['mtime'] = (int)$data['mtime']; + $data['storage_mtime'] = (int)$data['storage_mtime']; + $data['encryptedVersion'] = (int)$data['encrypted']; + $data['encrypted'] = (bool)$data['encrypted']; + $data['storage'] = $storageId; + $data['mimetype'] = $mimetypeLoader->getMimetypeById($data['mimetype']); + $data['mimepart'] = $mimetypeLoader->getMimetypeById($data['mimepart']); + if ($data['storage_mtime'] == 0) { + $data['storage_mtime'] = $data['mtime']; + } + $data['permissions'] = (int)$data['permissions']; + return new CacheEntry($data); + } + + /** * get the metadata of all files stored in $folder * * @param string $folder diff --git a/lib/private/Files/Cache/Wrapper/CacheJail.php b/lib/private/Files/Cache/Wrapper/CacheJail.php index 1196c6b0760..d8bdca6a3c4 100644 --- a/lib/private/Files/Cache/Wrapper/CacheJail.php +++ b/lib/private/Files/Cache/Wrapper/CacheJail.php @@ -27,6 +27,7 @@ namespace OC\Files\Cache\Wrapper; use OC\Files\Cache\Cache; +use OCP\Files\Cache\ICacheEntry; /** * Jail to a subdirectory of the wrapped cache @@ -73,7 +74,7 @@ class CacheJail extends CacheWrapper { } /** - * @param array $entry + * @param ICacheEntry|array $entry * @return array */ protected function formatCacheEntry($entry) { @@ -111,7 +112,7 @@ class CacheJail extends CacheWrapper { * @throws \RuntimeException */ public function insert($file, array $data) { - return $this->cache->insert($this->getSourcePath($file), $data); + return $this->getCache()->insert($this->getSourcePath($file), $data); } /** @@ -121,7 +122,7 @@ class CacheJail extends CacheWrapper { * @param array $data */ public function update($id, array $data) { - $this->cache->update($id, $data); + $this->getCache()->update($id, $data); } /** @@ -131,7 +132,7 @@ class CacheJail extends CacheWrapper { * @return int */ public function getId($file) { - return $this->cache->getId($this->getSourcePath($file)); + return $this->getCache()->getId($this->getSourcePath($file)); } /** @@ -144,7 +145,7 @@ class CacheJail extends CacheWrapper { if ($file === '') { return -1; } else { - return $this->cache->getParentId($this->getSourcePath($file)); + return $this->getCache()->getParentId($this->getSourcePath($file)); } } @@ -155,7 +156,7 @@ class CacheJail extends CacheWrapper { * @return bool */ public function inCache($file) { - return $this->cache->inCache($this->getSourcePath($file)); + return $this->getCache()->inCache($this->getSourcePath($file)); } /** @@ -164,7 +165,7 @@ class CacheJail extends CacheWrapper { * @param string $file */ public function remove($file) { - $this->cache->remove($this->getSourcePath($file)); + $this->getCache()->remove($this->getSourcePath($file)); } /** @@ -174,14 +175,14 @@ class CacheJail extends CacheWrapper { * @param string $target */ public function move($source, $target) { - $this->cache->move($this->getSourcePath($source), $this->getSourcePath($target)); + $this->getCache()->move($this->getSourcePath($source), $this->getSourcePath($target)); } /** * remove all entries for files that are stored on the storage from the cache */ public function clear() { - $this->cache->remove($this->root); + $this->getCache()->remove($this->root); } /** @@ -190,7 +191,7 @@ class CacheJail extends CacheWrapper { * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE */ public function getStatus($file) { - return $this->cache->getStatus($this->getSourcePath($file)); + return $this->getCache()->getStatus($this->getSourcePath($file)); } private function formatSearchResults($results) { @@ -206,7 +207,7 @@ class CacheJail extends CacheWrapper { * @return array an array of file data */ public function search($pattern) { - $results = $this->cache->search($pattern); + $results = $this->getCache()->search($pattern); return $this->formatSearchResults($results); } @@ -217,7 +218,7 @@ class CacheJail extends CacheWrapper { * @return array */ public function searchByMime($mimetype) { - $results = $this->cache->searchByMime($mimetype); + $results = $this->getCache()->searchByMime($mimetype); return $this->formatSearchResults($results); } @@ -229,7 +230,7 @@ class CacheJail extends CacheWrapper { * @return array */ public function searchByTag($tag, $userId) { - $results = $this->cache->searchByTag($tag, $userId); + $results = $this->getCache()->searchByTag($tag, $userId); return $this->formatSearchResults($results); } @@ -240,8 +241,8 @@ class CacheJail extends CacheWrapper { * @param array $data (optional) meta data of the folder */ public function correctFolderSize($path, $data = null) { - if ($this->cache instanceof Cache) { - $this->cache->correctFolderSize($this->getSourcePath($path), $data); + if ($this->getCache() instanceof Cache) { + $this->getCache()->correctFolderSize($this->getSourcePath($path), $data); } } @@ -253,8 +254,8 @@ class CacheJail extends CacheWrapper { * @return int */ public function calculateFolderSize($path, $entry = null) { - if ($this->cache instanceof Cache) { - return $this->cache->calculateFolderSize($this->getSourcePath($path), $entry); + if ($this->getCache() instanceof Cache) { + return $this->getCache()->calculateFolderSize($this->getSourcePath($path), $entry); } else { return 0; } @@ -292,7 +293,7 @@ class CacheJail extends CacheWrapper { * @return string|null */ public function getPathById($id) { - $path = $this->cache->getPathById($id); + $path = $this->getCache()->getPathById($id); return $this->getJailedPath($path); } @@ -309,6 +310,6 @@ class CacheJail extends CacheWrapper { if ($sourceCache === $this) { return $this->move($sourcePath, $targetPath); } - return $this->cache->moveFromCache($sourceCache, $sourcePath, $this->getSourcePath($targetPath)); + return $this->getCache()->moveFromCache($sourceCache, $sourcePath, $this->getSourcePath($targetPath)); } } diff --git a/lib/private/Files/Cache/Wrapper/CacheWrapper.php b/lib/private/Files/Cache/Wrapper/CacheWrapper.php index 7a8177566c7..83fe7e5f43e 100644 --- a/lib/private/Files/Cache/Wrapper/CacheWrapper.php +++ b/lib/private/Files/Cache/Wrapper/CacheWrapper.php @@ -45,6 +45,10 @@ class CacheWrapper extends Cache { $this->cache = $cache; } + protected function getCache() { + return $this->cache; + } + /** * Make it easy for wrappers to modify every returned cache entry * @@ -62,7 +66,7 @@ class CacheWrapper extends Cache { * @return ICacheEntry|false */ public function get($file) { - $result = $this->cache->get($file); + $result = $this->getCache()->get($file); if ($result) { $result = $this->formatCacheEntry($result); } @@ -76,7 +80,7 @@ class CacheWrapper extends Cache { * @return ICacheEntry[] */ public function getFolderContents($folder) { - // can't do a simple $this->cache->.... call here since getFolderContentsById needs to be called on this + // can't do a simple $this->getCache()->.... call here since getFolderContentsById needs to be called on this // and not the wrapped cache $fileId = $this->getId($folder); return $this->getFolderContentsById($fileId); @@ -89,7 +93,7 @@ class CacheWrapper extends Cache { * @return array */ public function getFolderContentsById($fileId) { - $results = $this->cache->getFolderContentsById($fileId); + $results = $this->getCache()->getFolderContentsById($fileId); return array_map(array($this, 'formatCacheEntry'), $results); } @@ -121,7 +125,7 @@ class CacheWrapper extends Cache { * @throws \RuntimeException */ public function insert($file, array $data) { - return $this->cache->insert($file, $data); + return $this->getCache()->insert($file, $data); } /** @@ -131,7 +135,7 @@ class CacheWrapper extends Cache { * @param array $data */ public function update($id, array $data) { - $this->cache->update($id, $data); + $this->getCache()->update($id, $data); } /** @@ -141,7 +145,7 @@ class CacheWrapper extends Cache { * @return int */ public function getId($file) { - return $this->cache->getId($file); + return $this->getCache()->getId($file); } /** @@ -151,7 +155,7 @@ class CacheWrapper extends Cache { * @return int */ public function getParentId($file) { - return $this->cache->getParentId($file); + return $this->getCache()->getParentId($file); } /** @@ -161,7 +165,7 @@ class CacheWrapper extends Cache { * @return bool */ public function inCache($file) { - return $this->cache->inCache($file); + return $this->getCache()->inCache($file); } /** @@ -170,7 +174,7 @@ class CacheWrapper extends Cache { * @param string $file */ public function remove($file) { - $this->cache->remove($file); + $this->getCache()->remove($file); } /** @@ -180,18 +184,18 @@ class CacheWrapper extends Cache { * @param string $target */ public function move($source, $target) { - $this->cache->move($source, $target); + $this->getCache()->move($source, $target); } public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) { - $this->cache->moveFromCache($sourceCache, $sourcePath, $targetPath); + $this->getCache()->moveFromCache($sourceCache, $sourcePath, $targetPath); } /** * remove all entries for files that are stored on the storage from the cache */ public function clear() { - $this->cache->clear(); + $this->getCache()->clear(); } /** @@ -200,7 +204,7 @@ class CacheWrapper extends Cache { * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE */ public function getStatus($file) { - return $this->cache->getStatus($file); + return $this->getCache()->getStatus($file); } /** @@ -210,7 +214,7 @@ class CacheWrapper extends Cache { * @return ICacheEntry[] an array of file data */ public function search($pattern) { - $results = $this->cache->search($pattern); + $results = $this->getCache()->search($pattern); return array_map(array($this, 'formatCacheEntry'), $results); } @@ -221,7 +225,7 @@ class CacheWrapper extends Cache { * @return ICacheEntry[] */ public function searchByMime($mimetype) { - $results = $this->cache->searchByMime($mimetype); + $results = $this->getCache()->searchByMime($mimetype); return array_map(array($this, 'formatCacheEntry'), $results); } @@ -233,7 +237,7 @@ class CacheWrapper extends Cache { * @return ICacheEntry[] file data */ public function searchByTag($tag, $userId) { - $results = $this->cache->searchByTag($tag, $userId); + $results = $this->getCache()->searchByTag($tag, $userId); return array_map(array($this, 'formatCacheEntry'), $results); } @@ -244,8 +248,8 @@ class CacheWrapper extends Cache { * @param array $data (optional) meta data of the folder */ public function correctFolderSize($path, $data = null) { - if ($this->cache instanceof Cache) { - $this->cache->correctFolderSize($path, $data); + if ($this->getCache() instanceof Cache) { + $this->getCache()->correctFolderSize($path, $data); } } @@ -257,8 +261,8 @@ class CacheWrapper extends Cache { * @return int */ public function calculateFolderSize($path, $entry = null) { - if ($this->cache instanceof Cache) { - return $this->cache->calculateFolderSize($path, $entry); + if ($this->getCache() instanceof Cache) { + return $this->getCache()->calculateFolderSize($path, $entry); } else { return 0; } @@ -270,7 +274,7 @@ class CacheWrapper extends Cache { * @return int[] */ public function getAll() { - return $this->cache->getAll(); + return $this->getCache()->getAll(); } /** @@ -283,7 +287,7 @@ class CacheWrapper extends Cache { * @return string|bool the path of the folder or false when no folder matched */ public function getIncomplete() { - return $this->cache->getIncomplete(); + return $this->getCache()->getIncomplete(); } /** @@ -293,7 +297,7 @@ class CacheWrapper extends Cache { * @return string|null */ public function getPathById($id) { - return $this->cache->getPathById($id); + return $this->getCache()->getPathById($id); } /** @@ -302,7 +306,7 @@ class CacheWrapper extends Cache { * @return int */ public function getNumericStorageId() { - return $this->cache->getNumericStorageId(); + return $this->getCache()->getNumericStorageId(); } /** diff --git a/lib/private/Files/FileInfo.php b/lib/private/Files/FileInfo.php index 14a32ba8f76..3ad2932e597 100644 --- a/lib/private/Files/FileInfo.php +++ b/lib/private/Files/FileInfo.php @@ -33,6 +33,7 @@ namespace OC\Files; use OCP\Files\Cache\ICacheEntry; use OCP\Files\Mount\IMountPoint; use OCP\Files\Storage\IStorage; +use OCP\Files\IHomeStorage; use OCP\IUser; class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess { @@ -305,7 +306,11 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess { } public function isMounted() { - $sid = $this->getStorage()->getId(); + $storage = $this->getStorage(); + if ($storage->instanceOfStorage('\OCP\Files\IHomeStorage')) { + return false; + } + $sid = $storage->getId(); if (!is_null($sid)) { $sid = explode(':', $sid); return ($sid[0] !== 'home' and $sid[0] !== 'shared'); diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php index 55cf38bbdc9..51e494c372e 100644 --- a/lib/private/Files/Filesystem.php +++ b/lib/private/Files/Filesystem.php @@ -62,6 +62,7 @@ use OC\Cache\CappedMemoryCache; use OC\Files\Config\MountProviderCollection; use OC\Files\Mount\MountPoint; use OC\Files\Storage\StorageFactory; +use OC\Lockdown\Filesystem\NullStorage; use OCP\Files\Config\IMountProvider; use OCP\Files\Mount\IMountPoint; use OCP\Files\NotFoundException; @@ -213,10 +214,13 @@ class Filesystem { /** * @param bool $shouldLog + * @return bool previous value * @internal */ public static function logWarningWhenAddingStorageWrapper($shouldLog) { + $previousValue = self::$logWarningWhenAddingStorageWrapper; self::$logWarningWhenAddingStorageWrapper = (bool) $shouldLog; + return $previousValue; } /** @@ -225,7 +229,7 @@ class Filesystem { * @param int $priority */ public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) { - if (self::$logWarningWhenAddingStorageWrapper && $wrapperName !== 'readonly') { + if (self::$logWarningWhenAddingStorageWrapper) { \OC::$server->getLogger()->warning("Storage wrapper '{wrapper}' was not registered via the 'OC_Filesystem - preSetup' hook which could cause potential problems.", [ 'wrapper' => $wrapperName, 'app' => 'filesystem', @@ -426,25 +430,36 @@ class Filesystem { self::$usersSetup[$user] = true; } - /** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */ - $mountConfigManager = \OC::$server->getMountProviderCollection(); + if (\OC::$server->getLockdownManager()->canAccessFilesystem()) { + /** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */ + $mountConfigManager = \OC::$server->getMountProviderCollection(); - // home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers - $homeMount = $mountConfigManager->getHomeMountForUser($userObject); + // home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers + $homeMount = $mountConfigManager->getHomeMountForUser($userObject); - self::getMountManager()->addMount($homeMount); + self::getMountManager()->addMount($homeMount); - \OC\Files\Filesystem::getStorage($user); + \OC\Files\Filesystem::getStorage($user); - // Chance to mount for other storages - if ($userObject) { - $mounts = $mountConfigManager->getMountsForUser($userObject); - array_walk($mounts, array(self::$mounts, 'addMount')); - $mounts[] = $homeMount; - $mountConfigManager->registerMounts($userObject, $mounts); - } + // Chance to mount for other storages + if ($userObject) { + $mounts = $mountConfigManager->getMountsForUser($userObject); + array_walk($mounts, array(self::$mounts, 'addMount')); + $mounts[] = $homeMount; + $mountConfigManager->registerMounts($userObject, $mounts); + } - self::listenForNewMountProviders($mountConfigManager, $userManager); + self::listenForNewMountProviders($mountConfigManager, $userManager); + } else { + self::getMountManager()->addMount(new MountPoint( + new NullStorage([]), + '/' . $user + )); + self::getMountManager()->addMount(new MountPoint( + new NullStorage([]), + '/' . $user . '/files' + )); + } \OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', array('user' => $user)); } diff --git a/lib/private/Files/Mount/ObjectHomeMountProvider.php b/lib/private/Files/Mount/ObjectHomeMountProvider.php index 87878562a42..440a8bc4608 100644 --- a/lib/private/Files/Mount/ObjectHomeMountProvider.php +++ b/lib/private/Files/Mount/ObjectHomeMountProvider.php @@ -51,7 +51,7 @@ class ObjectHomeMountProvider implements IHomeMountProvider { * * @param IUser $user * @param IStorageFactory $loader - * @return \OCP\Files\Mount\IMountPoint[] + * @return \OCP\Files\Mount\IMountPoint */ public function getHomeMountForUser(IUser $user, IStorageFactory $loader) { diff --git a/lib/private/Files/ObjectStore/S3.php b/lib/private/Files/ObjectStore/S3.php new file mode 100644 index 00000000000..5251b473bdf --- /dev/null +++ b/lib/private/Files/ObjectStore/S3.php @@ -0,0 +1,107 @@ +<?php +/** + * @copyright Copyright (c) 2016 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 OC\Files\ObjectStore; + +use OCP\Files\ObjectStore\IObjectStore; + +// TODO: proper composer +set_include_path(get_include_path() . PATH_SEPARATOR . + \OC_App::getAppPath('files_external') . '/3rdparty/aws-sdk-php'); +require_once 'aws-autoloader.php'; + +class S3 implements IObjectStore { + use S3ConnectionTrait; + + public function __construct($parameters) { + $this->parseParams($parameters); + } + + /** + * @return string the container or bucket name where objects are stored + * @since 7.0.0 + */ + function getStorageId() { + return $this->id; + } + + /** + * @param string $urn the unified resource name used to identify the object + * @return resource stream with the read data + * @throws \Exception when something goes wrong, message will be logged + * @since 7.0.0 + */ + function readObject($urn) { + // Create the command and serialize the request + $request = $this->getConnection()->getCommand('GetObject', [ + 'Bucket' => $this->bucket, + 'Key' => $urn + ])->prepare(); + + $request->dispatch('request.before_send', array( + 'request' => $request + )); + + $headers = $request->getHeaderLines(); + $headers[] = 'Connection: close'; + + $opts = [ + 'http' => [ + 'method' => "GET", + 'header' => $headers + ], + 'ssl' => [ + 'verify_peer' => true + ] + ]; + + $context = stream_context_create($opts); + return fopen($request->getUrl(), 'r', false, $context); + } + + /** + * @param string $urn the unified resource name used to identify the object + * @param resource $stream stream with the data to write + * @throws \Exception when something goes wrong, message will be logged + * @since 7.0.0 + */ + function writeObject($urn, $stream) { + $this->getConnection()->putObject([ + 'Bucket' => $this->bucket, + 'Key' => $urn, + 'Body' => $stream + ]); + } + + /** + * @param string $urn the unified resource name used to identify the object + * @return void + * @throws \Exception when something goes wrong, message will be logged + * @since 7.0.0 + */ + function deleteObject($urn) { + $this->getConnection()->deleteObject([ + 'Bucket' => $this->bucket, + 'Key' => $urn + ]); + } + +} diff --git a/lib/private/Files/ObjectStore/S3ConnectionTrait.php b/lib/private/Files/ObjectStore/S3ConnectionTrait.php new file mode 100644 index 00000000000..a8b57cb18d3 --- /dev/null +++ b/lib/private/Files/ObjectStore/S3ConnectionTrait.php @@ -0,0 +1,124 @@ +<?php +/** + * @copyright Copyright (c) 2016 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 OC\Files\ObjectStore; + +use Aws\S3\Exception\S3Exception; +use Aws\S3\S3Client; + +trait S3ConnectionTrait { + /** @var array */ + protected $params; + + /** @var S3Client */ + protected $connection; + + /** @var string */ + protected $id; + + /** @var string */ + protected $bucket; + + /** @var int */ + protected $timeout; + + protected $test; + + protected function parseParams($params) { + if (empty($params['key']) || empty($params['secret']) || empty($params['bucket'])) { + throw new \Exception("Access Key, Secret and Bucket have to be configured."); + } + + $this->id = 'amazon::' . $params['bucket']; + + $this->test = isset($params['test']); + $this->bucket = $params['bucket']; + $this->timeout = (!isset($params['timeout'])) ? 15 : $params['timeout']; + $params['region'] = empty($params['region']) ? 'eu-west-1' : $params['region']; + $params['hostname'] = empty($params['hostname']) ? 's3.amazonaws.com' : $params['hostname']; + if (!isset($params['port']) || $params['port'] === '') { + $params['port'] = (isset($params['use_ssl']) && $params['use_ssl'] === false) ? 80 : 443; + } + $this->params = $params; + } + + + /** + * Returns the connection + * + * @return S3Client connected client + * @throws \Exception if connection could not be made + */ + protected function getConnection() { + if (!is_null($this->connection)) { + return $this->connection; + } + + $scheme = (isset($this->params['use_ssl']) && $this->params['use_ssl'] === false) ? 'http' : 'https'; + $base_url = $scheme . '://' . $this->params['hostname'] . ':' . $this->params['port'] . '/'; + + $options = [ + 'key' => $this->params['key'], + 'secret' => $this->params['secret'], + 'base_url' => $base_url, + 'region' => $this->params['region'], + S3Client::COMMAND_PARAMS => [ + 'PathStyle' => isset($this->params['use_path_style']) ? $this->params['use_path_style'] : false, + ] + ]; + if (isset($this->params['proxy'])) { + $options[S3Client::REQUEST_OPTIONS] = ['proxy' => $this->params['proxy']]; + } + $this->connection = S3Client::factory($options); + + if (!$this->connection->isValidBucketName($this->bucket)) { + throw new \Exception("The configured bucket name is invalid."); + } + + if (!$this->connection->doesBucketExist($this->bucket)) { + try { + $this->connection->createBucket(array( + 'Bucket' => $this->bucket + )); + $this->connection->waitUntilBucketExists(array( + 'Bucket' => $this->bucket, + 'waiter.interval' => 1, + 'waiter.max_attempts' => 15 + )); + $this->testTimeout(); + } catch (S3Exception $e) { + \OCP\Util::logException('files_external', $e); + throw new \Exception('Creation of bucket failed. ' . $e->getMessage()); + } + } + + return $this->connection; + } + + /** + * when running the tests wait to let the buckets catch up + */ + private function testTimeout() { + if ($this->test) { + sleep($this->timeout); + } + } +} diff --git a/lib/private/Files/ObjectStore/StorageObjectStore.php b/lib/private/Files/ObjectStore/StorageObjectStore.php new file mode 100644 index 00000000000..044243c1ee6 --- /dev/null +++ b/lib/private/Files/ObjectStore/StorageObjectStore.php @@ -0,0 +1,90 @@ +<?php +/** + * @copyright Copyright (c) 2016 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 OC\Files\ObjectStore; + +use OCP\Files\ObjectStore\IObjectStore; +use OCP\Files\Storage\IStorage; + +/** + * Object store that wraps a storage backend, mostly for testing purposes + */ +class StorageObjectStore implements IObjectStore { + /** @var IStorage */ + private $storage; + + /** + * @param IStorage $storage + */ + public function __construct(IStorage $storage) { + $this->storage = $storage; + } + + /** + * @return string the container or bucket name where objects are stored + * @since 7.0.0 + */ + function getStorageId() { + $this->storage->getId(); + } + + /** + * @param string $urn the unified resource name used to identify the object + * @return resource stream with the read data + * @throws \Exception when something goes wrong, message will be logged + * @since 7.0.0 + */ + function readObject($urn) { + $handle = $this->storage->fopen($urn, 'r'); + if ($handle) { + return $handle; + } else { + throw new \Exception(); + } + } + + /** + * @param string $urn the unified resource name used to identify the object + * @param resource $stream stream with the data to write + * @throws \Exception when something goes wrong, message will be logged + * @since 7.0.0 + */ + function writeObject($urn, $stream) { + $handle = $this->storage->fopen($urn, 'w'); + if ($handle) { + stream_copy_to_stream($stream, $handle); + fclose($handle); + } else { + throw new \Exception(); + } + } + + /** + * @param string $urn the unified resource name used to identify the object + * @return void + * @throws \Exception when something goes wrong, message will be logged + * @since 7.0.0 + */ + function deleteObject($urn) { + $this->storage->unlink($urn); + } + +} diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php index 3514c829691..7866f90157e 100644 --- a/lib/private/Files/View.php +++ b/lib/private/Files/View.php @@ -431,6 +431,7 @@ class View { echo fread($handle, $chunkSize); flush(); } + fclose($handle); $size = $this->filesize($path); return $size; } diff --git a/lib/private/Lockdown/Filesystem/NullCache.php b/lib/private/Lockdown/Filesystem/NullCache.php new file mode 100644 index 00000000000..8c6b5258aa8 --- /dev/null +++ b/lib/private/Lockdown/Filesystem/NullCache.php @@ -0,0 +1,122 @@ +<?php + +/** + * @copyright Copyright (c) 2016, Robin Appelman <robin@icewind.nl> + * + * 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 OC\Lockdown\Filesystem; + +use OC\Files\Cache\CacheEntry; +use OCP\Constants; +use OCP\Files\Cache\ICache; +use OCP\Files\Cache\ICacheEntry; +use OCP\Files\FileInfo; + +class NullCache implements ICache { + public function getNumericStorageId() { + return -1; + } + + public function get($file) { + return $file !== '' ? null : + new CacheEntry([ + 'fileid' => -1, + 'parent' => -1, + 'name' => '', + 'path' => '', + 'size' => '0', + 'mtime' => time(), + 'storage_mtime' => time(), + 'etag' => '', + 'mimetype' => FileInfo::MIMETYPE_FOLDER, + 'mimepart' => 'httpd', + 'permissions' => Constants::PERMISSION_READ + ]); + } + + public function getFolderContents($folder) { + return []; + } + + public function getFolderContentsById($fileId) { + return []; + } + + public function put($file, array $data) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function insert($file, array $data) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function update($id, array $data) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function getId($file) { + return -1; + } + + public function getParentId($file) { + return -1; + } + + public function inCache($file) { + return $file === ''; + } + + public function remove($file) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function move($source, $target) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function getStatus($file) { + return ICache::COMPLETE; + } + + public function search($pattern) { + return []; + } + + public function searchByMime($mimetype) { + return []; + } + + public function searchByTag($tag, $userId) { + return []; + } + + public function getIncomplete() { + return []; + } + + public function getPathById($id) { + return ''; + } + + public function normalize($path) { + return $path; + } + +} diff --git a/lib/private/Lockdown/Filesystem/NullStorage.php b/lib/private/Lockdown/Filesystem/NullStorage.php new file mode 100644 index 00000000000..967b6d2c6e7 --- /dev/null +++ b/lib/private/Lockdown/Filesystem/NullStorage.php @@ -0,0 +1,177 @@ +<?php + +/** + * @copyright Copyright (c) 2016, Robin Appelman <robin@icewind.nl> + * + * 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 OC\Lockdown\Filesystem; + +use Icewind\Streams\IteratorDirectory; +use OC\Files\Storage\Common; + +class NullStorage extends Common { + public function __construct($parameters) { + parent::__construct($parameters); + } + + public function getId() { + return 'null'; + } + + public function mkdir($path) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function rmdir($path) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function opendir($path) { + return new IteratorDirectory([]); + } + + public function is_dir($path) { + return $path === ''; + } + + public function is_file($path) { + return false; + } + + public function stat($path) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function filetype($path) { + return ($path === '') ? 'dir' : false; + } + + public function filesize($path) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function isCreatable($path) { + return false; + } + + public function isReadable($path) { + return $path === ''; + } + + public function isUpdatable($path) { + return false; + } + + public function isDeletable($path) { + return false; + } + + public function isSharable($path) { + return false; + } + + public function getPermissions($path) { + return null; + } + + public function file_exists($path) { + return $path === ''; + } + + public function filemtime($path) { + return ($path === '') ? time() : false; + } + + public function file_get_contents($path) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function file_put_contents($path, $data) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function unlink($path) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function rename($path1, $path2) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function copy($path1, $path2) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function fopen($path, $mode) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function getMimeType($path) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function hash($type, $path, $raw = false) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function free_space($path) { + return 0; + } + + public function touch($path, $mtime = null) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function getLocalFile($path) { + return false; + } + + public function hasUpdated($path, $time) { + return false; + } + + public function getETag($path) { + return ''; + } + + public function isLocal() { + return false; + } + + public function getDirectDownload($path) { + return false; + } + + public function copyFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function moveFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath) { + throw new \OC\ForbiddenException('This request is not allowed to access the filesystem'); + } + + public function test() { + return true; + } + + public function getOwner($path) { + return null; + } + + public function getCache($path = '', $storage = null) { + return new NullCache(); + } +} diff --git a/lib/private/Lockdown/LockdownManager.php b/lib/private/Lockdown/LockdownManager.php new file mode 100644 index 00000000000..5ce52a03683 --- /dev/null +++ b/lib/private/Lockdown/LockdownManager.php @@ -0,0 +1,46 @@ +<?php + +/** + * @copyright Copyright (c) 2016, Robin Appelman <robin@icewind.nl> + * + * 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 OC\Lockdown; + +use OC\Authentication\Token\IToken; +use OCP\Lockdown\ILockdownManager; + +class LockdownManager implements ILockdownManager { + private $enabled = false; + + /** @var array|null */ + private $scope; + + public function enable() { + $this->enabled = true; + } + + public function setToken(IToken $token) { + $this->scope = $token->getScopeAsArray(); + $this->enable(); + } + + public function canAccessFilesystem() { + if (!$this->enabled) { + return true; + } + return !$this->scope || $this->scope['filesystem']; + } +} diff --git a/lib/private/OCS/Person.php b/lib/private/OCS/Person.php deleted file mode 100644 index d14465c5ce9..00000000000 --- a/lib/private/OCS/Person.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Bart Visscher <bartv@thisnet.nl> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Tom Needham <tom@owncloud.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 OC\OCS; - -class Person { - - public static function check() { - $login = isset($_POST['login']) ? $_POST['login'] : false; - $password = isset($_POST['password']) ? $_POST['password'] : false; - if($login && $password) { - $remoteIp = \OC::$server->getRequest()->getRemoteAddress(); - \OC::$server->getBruteForceThrottler()->sleepDelay($remoteIp); - if(\OC_User::checkPassword($login, $password)) { - $xml['person']['personid'] = $login; - return new Result($xml); - } else { - \OC::$server->getBruteForceThrottler()->registerAttempt('login', $remoteIp); - return new Result(null, 102); - } - } else { - return new Result(null, 101); - } - } - -} diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php index 3d4e9bf3677..32a732d8580 100644 --- a/lib/private/Preview/Generator.php +++ b/lib/private/Preview/Generator.php @@ -32,6 +32,8 @@ use OCP\IConfig; use OCP\IImage; use OCP\IPreview; use OCP\Preview\IProvider; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\GenericEvent; class Generator { @@ -43,23 +45,28 @@ class Generator { private $appData; /** @var GeneratorHelper */ private $helper; + /** @var EventDispatcherInterface */ + private $eventDispatcher; /** * @param IConfig $config * @param IPreview $previewManager * @param IAppData $appData * @param GeneratorHelper $helper + * @param EventDispatcherInterface $eventDispatcher */ public function __construct( IConfig $config, IPreview $previewManager, IAppData $appData, - GeneratorHelper $helper + GeneratorHelper $helper, + EventDispatcherInterface $eventDispatcher ) { $this->config = $config; $this->previewManager = $previewManager; $this->appData = $appData; $this->helper = $helper; + $this->eventDispatcher = $eventDispatcher; } /** @@ -78,6 +85,16 @@ class Generator { * @throws NotFoundException */ public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) { + $this->eventDispatcher->dispatch( + IPreview::EVENT, + new GenericEvent($file,[ + 'width' => $width, + 'height' => $height, + 'crop' => $crop, + 'mode' => $mode + ]) + ); + if ($mimeType === null) { $mimeType = $file->getMimeType(); } diff --git a/lib/private/PreviewManager.php b/lib/private/PreviewManager.php index 600557da5a0..36b3730a720 100644 --- a/lib/private/PreviewManager.php +++ b/lib/private/PreviewManager.php @@ -35,6 +35,7 @@ use OCP\Files\SimpleFS\ISimpleFile; use OCP\IConfig; use OCP\IPreview; use OCP\Preview\IProvider; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; class PreviewManager implements IPreview { /** @var IConfig */ @@ -46,6 +47,9 @@ class PreviewManager implements IPreview { /** @var IAppData */ protected $appData; + /** @var EventDispatcherInterface */ + protected $eventDispatcher; + /** @var Generator */ private $generator; @@ -65,16 +69,21 @@ class PreviewManager implements IPreview { protected $defaultProviders; /** - * Constructor + * PreviewManager constructor. * - * @param \OCP\IConfig $config + * @param IConfig $config + * @param IRootFolder $rootFolder + * @param IAppData $appData + * @param EventDispatcherInterface $eventDispatcher */ public function __construct(IConfig $config, IRootFolder $rootFolder, - IAppData $appData) { + IAppData $appData, + EventDispatcherInterface $eventDispatcher) { $this->config = $config; $this->rootFolder = $rootFolder; $this->appData = $appData; + $this->eventDispatcher = $eventDispatcher; } /** @@ -165,7 +174,8 @@ class PreviewManager implements IPreview { $this->appData, new GeneratorHelper( $this->rootFolder - ) + ), + $this->eventDispatcher ); } diff --git a/lib/private/Route/Router.php b/lib/private/Route/Router.php index 59f403d66e8..fd15400dad4 100644 --- a/lib/private/Route/Router.php +++ b/lib/private/Route/Router.php @@ -4,6 +4,7 @@ * * @author Bart Visscher <bartv@thisnet.nl> * @author Bernhard Posselt <dev@bernhard-posselt.com> + * @author Felix Anand Epp <work@felixepp.de> * @author Joas Schilling <coding@schilljs.com> * @author Jörn Friedrich Dreyer <jfd@butonic.de> * @author Lukas Reschke <lukas@statuscode.ch> @@ -71,7 +72,7 @@ class Router implements IRouter { public function __construct(ILogger $logger) { $this->logger = $logger; $baseUrl = \OC::$WEBROOT; - if(!(getenv('front_controller_active') === 'true')) { + if(!(\OC::$server->getConfig()->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true')) { $baseUrl = \OC::$server->getURLGenerator()->linkTo('', 'index.php'); } if (!\OC::$CLI) { diff --git a/lib/private/Security/IdentityProof/Key.php b/lib/private/Security/IdentityProof/Key.php new file mode 100644 index 00000000000..9739a9571bb --- /dev/null +++ b/lib/private/Security/IdentityProof/Key.php @@ -0,0 +1,46 @@ +<?php +/** + * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> + * + * @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 OC\Security\IdentityProof; + +class Key { + /** @var string */ + private $publicKey; + /** @var string */ + private $privateKey; + + /** + * @param string $publicKey + * @param string $privateKey + */ + public function __construct($publicKey, $privateKey) { + $this->publicKey = $publicKey; + $this->privateKey = $privateKey; + } + + public function getPrivate() { + return $this->privateKey; + } + + public function getPublic() { + return $this->publicKey; + } +} diff --git a/lib/private/Security/IdentityProof/Manager.php b/lib/private/Security/IdentityProof/Manager.php new file mode 100644 index 00000000000..d2a9e57e338 --- /dev/null +++ b/lib/private/Security/IdentityProof/Manager.php @@ -0,0 +1,108 @@ +<?php +/** + * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> + * + * @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 OC\Security\IdentityProof; + +use OCP\Files\IAppData; +use OCP\IUser; +use OCP\Security\ICrypto; + +class Manager { + /** @var IAppData */ + private $appData; + /** @var ICrypto */ + private $crypto; + + /** + * @param IAppData $appData + * @param ICrypto $crypto + */ + public function __construct(IAppData $appData, + ICrypto $crypto) { + $this->appData = $appData; + $this->crypto = $crypto; + } + + /** + * Calls the openssl functions to generate a public and private key. + * In a separate function for unit testing purposes. + * + * @return array [$publicKey, $privateKey] + */ + protected function generateKeyPair() { + $config = [ + 'digest_alg' => 'sha512', + 'private_key_bits' => 2048, + ]; + + // Generate new key + $res = openssl_pkey_new($config); + openssl_pkey_export($res, $privateKey); + + // Extract the public key from $res to $pubKey + $publicKey = openssl_pkey_get_details($res); + $publicKey = $publicKey['key']; + + return [$publicKey, $privateKey]; + } + + /** + * Generate a key for $user + * Note: If a key already exists it will be overwritten + * + * @param IUser $user + * @return Key + */ + protected function generateKey(IUser $user) { + list($publicKey, $privateKey) = $this->generateKeyPair(); + + // Write the private and public key to the disk + try { + $this->appData->newFolder($user->getUID()); + } catch (\Exception $e) {} + $folder = $this->appData->getFolder($user->getUID()); + $folder->newFile('private') + ->putContent($this->crypto->encrypt($privateKey)); + $folder->newFile('public') + ->putContent($publicKey); + + return new Key($publicKey, $privateKey); + } + + /** + * Get public and private key for $user + * + * @param IUser $user + * @return Key + */ + public function getKey(IUser $user) { + try { + $folder = $this->appData->getFolder($user->getUID()); + $privateKey = $this->crypto->decrypt( + $folder->getFile('private')->getContent() + ); + $publicKey = $folder->getFile('public')->getContent(); + return new Key($publicKey, $privateKey); + } catch (\Exception $e) { + return $this->generateKey($user); + } + } +} diff --git a/lib/private/Security/IdentityProof/Signer.php b/lib/private/Security/IdentityProof/Signer.php new file mode 100644 index 00000000000..50c36b26966 --- /dev/null +++ b/lib/private/Security/IdentityProof/Signer.php @@ -0,0 +1,120 @@ +<?php +/** + * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch> + * + * @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 OC\Security\IdentityProof; + +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\IUserManager; + +class Signer { + /** @var Manager */ + private $keyManager; + /** @var ITimeFactory */ + private $timeFactory; + /** @var IURLGenerator */ + private $urlGenerator; + /** @var IUserManager */ + private $userManager; + + /** + * @param Manager $keyManager + * @param ITimeFactory $timeFactory + * @param IURLGenerator $urlGenerator + * @param IUserManager $userManager + */ + public function __construct(Manager $keyManager, + ITimeFactory $timeFactory, + IURLGenerator $urlGenerator, + IUserManager $userManager) { + $this->keyManager = $keyManager; + $this->timeFactory = $timeFactory; + $this->userManager = $userManager; + } + + /** + * Returns a signed blob for $data + * + * @param string $type + * @param array $data + * @param IUser $user + * @return array ['message', 'signature'] + */ + public function sign($type, array $data, IUser $user) { + $privateKey = $this->keyManager->getKey($user)->getPrivate(); + $data = [ + 'data' => $data, + 'type' => $type, + 'signer' => $user->getCloudId(), + 'timestamp' => $this->timeFactory->getTime(), + ]; + openssl_sign(json_encode($data), $signature, $privateKey, OPENSSL_ALGO_SHA512); + + return [ + 'message' => $data, + 'signature' => base64_encode($signature), + ]; + } + + /** + * @param string $url + * @return string + */ + private function removeProtocolFromUrl($url) { + if (strpos($url, 'https://') === 0) { + return substr($url, strlen('https://')); + } else if (strpos($url, 'http://') === 0) { + return substr($url, strlen('http://')); + } + + return $url; + } + + /** + * Whether the data is signed properly + * + * @param array $data + * @return bool + */ + public function verify(array $data) { + if(isset($data['message']) + && isset($data['signature']) + && isset($data['message']['signer']) + ) { + $server = $this->urlGenerator->getAbsoluteURL('/'); + $postfix = strlen('@' . rtrim($this->removeProtocolFromUrl($server), '/')); + $userId = substr($data['message']['signer'], -$postfix); + + $user = $this->userManager->get($userId); + if($user !== null) { + $key = $this->keyManager->getKey($user); + return (bool)openssl_verify( + json_encode($data['message']), + base64_decode($data['signature']), + $key->getPublic() + ); + } + } + + return false; + } +} diff --git a/lib/private/Server.php b/lib/private/Server.php index abedf8230ed..1d3d588e9fc 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -69,6 +69,7 @@ use OC\IntegrityCheck\Helpers\FileAccessHelper; use OC\Lock\DBLockingProvider; use OC\Lock\MemcacheLockingProvider; use OC\Lock\NoopLockingProvider; +use OC\Lockdown\LockdownManager; use OC\Mail\Mailer; use OC\Memcache\ArrayCache; use OC\Notification\Manager; @@ -122,7 +123,8 @@ class Server extends ServerContainer implements IServerContainer { return new PreviewManager( $c->getConfig(), $c->getRootFolder(), - $c->getAppDataDir('preview') + $c->getAppDataDir('preview'), + $c->getEventDispatcher() ); }); @@ -702,7 +704,8 @@ class Server extends ServerContainer implements IServerContainer { $c->getL10N('theming'), $c->getURLGenerator(), new \OC_Defaults(), - $c->getLazyRootFolder() + $c->getLazyRootFolder(), + $c->getMemCacheFactory() ); } return new \OC_Defaults(); @@ -795,6 +798,9 @@ class Server extends ServerContainer implements IServerContainer { $c->getSystemConfig() ); }); + $this->registerService('LockdownManager', function (Server $c) { + return new LockdownManager(); + }); } /** @@ -1534,4 +1540,11 @@ class Server extends ServerContainer implements IServerContainer { $factory = $this->query(\OC\Files\AppData\Factory::class); return $factory->get($app); } + + /** + * @return \OCP\Lockdown\ILockdownManager + */ + public function getLockdownManager() { + return $this->query('LockdownManager'); + } } diff --git a/lib/private/Settings/Admin/Logging.php b/lib/private/Settings/Admin/ServerDevNotice.php index 407248ac4b1..1d7f34f782d 100644 --- a/lib/private/Settings/Admin/Logging.php +++ b/lib/private/Settings/Admin/ServerDevNotice.php @@ -1,8 +1,8 @@ <?php /** - * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de> + * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * @author Roeland Jago Douma <roeland@famdouma.nl> * * @license GNU AGPL version 3 or any later version * @@ -20,57 +20,33 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ - namespace OC\Settings\Admin; -use OC\Log\File as LogFile; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Platforms\SqlitePlatform; +use OC\Lock\DBLockingProvider; +use OC\Lock\NoopLockingProvider; use OCP\AppFramework\Http\TemplateResponse; use OCP\IConfig; +use OCP\IDBConnection; +use OCP\IL10N; +use OCP\Lock\ILockingProvider; use OCP\Settings\ISettings; -class Logging implements ISettings { - /** @var IConfig */ - private $config; - - /** - * @param IConfig $config - */ - public function __construct(IConfig $config) { - $this->config = $config; - } - +class ServerDevNotice implements ISettings { /** * @return TemplateResponse */ public function getForm() { - $logType = $this->config->getSystemValue('log_type', 'file'); - $showLog = ($logType === 'file' || $logType === 'owncloud'); - - $numEntriesToLoad = 5; - $entries = LogFile::getEntries($numEntriesToLoad + 1); - $entriesRemaining = count($entries) > $numEntriesToLoad; - $entries = array_slice($entries, 0, $numEntriesToLoad); - - $logFileExists = file_exists(LogFile::getLogFilePath()) ; - $logFileSize = $logFileExists ? filesize(LogFile::getLogFilePath()) : 0; - - $parameters = [ - 'loglevel' => $this->config->getSystemValue('loglevel', 2), - 'entries' => $entries, - 'entriesremain' => $entriesRemaining, - 'doesLogFileExist' => $logFileExists, - 'logFileSize' => $logFileSize, - 'showLog' => $showLog, - ]; - - return new TemplateResponse('settings', 'admin/logging', $parameters, ''); + return new TemplateResponse('settings', 'admin/server.development.notice'); } /** * @return string the section ID, e.g. 'sharing' */ public function getSection() { - return 'logging'; + return 'server'; } /** @@ -81,6 +57,6 @@ class Logging implements ISettings { * E.g.: 70 */ public function getPriority() { - return 0; + return 1000; } } diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php index e7be3d4e77d..990750848d3 100644 --- a/lib/private/Settings/Manager.php +++ b/lib/private/Settings/Manager.php @@ -332,7 +332,6 @@ class Manager implements IManager { 0 => [new Section('server', $this->l->t('Server settings'), 0)], 5 => [new Section('sharing', $this->l->t('Sharing'), 0)], 45 => [new Section('encryption', $this->l->t('Encryption'), 0)], - 90 => [new Section('logging', $this->l->t('Logging'), 0)], 98 => [new Section('additional', $this->l->t('Additional settings'), 0)], 99 => [new Section('tips-tricks', $this->l->t('Tips & tricks'), 0)], ]; @@ -369,6 +368,8 @@ class Manager implements IManager { /** @var ISettings $form */ $form = new Admin\Server($this->dbc, $this->config, $this->lockingProvider, $this->l); $forms[$form->getPriority()] = [$form]; + $form = new Admin\ServerDevNotice(); + $forms[$form->getPriority()] = [$form]; } if($section === 'encryption') { /** @var ISettings $form */ @@ -380,11 +381,6 @@ class Manager implements IManager { $form = new Admin\Sharing($this->config); $forms[$form->getPriority()] = [$form]; } - if($section === 'logging') { - /** @var ISettings $form */ - $form = new Admin\Logging($this->config); - $forms[$form->getPriority()] = [$form]; - } if($section === 'additional') { /** @var ISettings $form */ $form = new Admin\Additional($this->config); diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php index bdb6ac466ec..7a602950171 100644 --- a/lib/private/Share20/DefaultShareProvider.php +++ b/lib/private/Share20/DefaultShareProvider.php @@ -23,6 +23,8 @@ */ namespace OC\Share20; +use OC\Files\Cache\Cache; +use OC\Files\Cache\CacheEntry; use OCP\Files\File; use OCP\Files\Folder; use OCP\Share\IShareProvider; @@ -571,7 +573,7 @@ class DefaultShareProvider implements IShareProvider { $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) )); - + $cursor = $qb->execute(); $data = $cursor->fetch(); $cursor->closeCursor(); @@ -656,7 +658,11 @@ class DefaultShareProvider implements IShareProvider { if ($shareType === \OCP\Share::SHARE_TYPE_USER) { //Get shares directly with this user $qb = $this->dbConn->getQueryBuilder(); - $qb->select('s.*', 'f.fileid', 'f.path') + $qb->select('s.*', + 'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash', + 'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime', + 'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum' + ) ->selectAlias('st.id', 'storage_string_id') ->from('share', 's') ->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid')) @@ -709,7 +715,11 @@ class DefaultShareProvider implements IShareProvider { } $qb = $this->dbConn->getQueryBuilder(); - $qb->select('s.*', 'f.fileid', 'f.path') + $qb->select('s.*', + 'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash', + 'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime', + 'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum' + ) ->selectAlias('st.id', 'storage_string_id') ->from('share', 's') ->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid')) @@ -798,7 +808,7 @@ class DefaultShareProvider implements IShareProvider { return $share; } - + /** * Create a share object from an database row * @@ -838,6 +848,15 @@ class DefaultShareProvider implements IShareProvider { $share->setExpirationDate($expiration); } + if (isset($data['f_permissions'])) { + $entryData = $data; + $entryData['permissions'] = $entryData['f_permissions']; + $entryData['parent'] = $entryData['f_parent'];; + $share->setNodeCacheEntry(Cache::cacheEntryFromData($entryData, + $entryData['storage_string_id'], + \OC::$server->getMimeTypeLoader())); + } + $share->setProviderId($this->identifier()); return $share; diff --git a/lib/private/Share20/Share.php b/lib/private/Share20/Share.php index e3e8482f4e1..2e7e6d0ca2e 100644 --- a/lib/private/Share20/Share.php +++ b/lib/private/Share20/Share.php @@ -22,6 +22,7 @@ */ namespace OC\Share20; +use OCP\Files\Cache\ICacheEntry; use OCP\Files\File; use OCP\Files\IRootFolder; use OCP\Files\Node; @@ -72,6 +73,9 @@ class Share implements \OCP\Share\IShare { /** @var IUserManager */ private $userManager; + /** @var ICacheEntry|null */ + private $nodeCacheEntry; + public function __construct(IRootFolder $rootFolder, IUserManager $userManager) { $this->rootFolder = $rootFolder; $this->userManager = $userManager; @@ -418,4 +422,18 @@ class Share implements \OCP\Share\IShare { public function getMailSend() { return $this->mailSend; } + + /** + * @inheritdoc + */ + public function setNodeCacheEntry(ICacheEntry $entry) { + $this->nodeCacheEntry = $entry; + } + + /** + * @inheritdoc + */ + public function getNodeCacheEntry() { + return $this->nodeCacheEntry; + } } diff --git a/lib/private/Template/JSConfigHelper.php b/lib/private/Template/JSConfigHelper.php index a7f8c251cee..a724c124de0 100644 --- a/lib/private/Template/JSConfigHelper.php +++ b/lib/private/Template/JSConfigHelper.php @@ -27,6 +27,7 @@ use OCP\App\IAppManager; use OCP\IConfig; use OCP\IGroupManager; use OCP\IL10N; +use OCP\ISession; use OCP\IURLGenerator; use OCP\IUser; @@ -41,7 +42,10 @@ class JSConfigHelper { /** @var IAppManager */ private $appManager; - /** @var IUser */ + /** @var ISession */ + private $session; + + /** @var IUser|null */ private $currentUser; /** @var IConfig */ @@ -60,6 +64,7 @@ class JSConfigHelper { * @param IL10N $l * @param \OC_Defaults $defaults * @param IAppManager $appManager + * @param ISession $session * @param IUser|null $currentUser * @param IConfig $config * @param IGroupManager $groupManager @@ -69,6 +74,7 @@ class JSConfigHelper { public function __construct(IL10N $l, \OC_Defaults $defaults, IAppManager $appManager, + ISession $session, $currentUser, IConfig $config, IGroupManager $groupManager, @@ -77,6 +83,7 @@ class JSConfigHelper { $this->l = $l; $this->defaults = $defaults; $this->appManager = $appManager; + $this->session = $session; $this->currentUser = $currentUser; $this->config = $config; $this->groupManager = $groupManager; @@ -119,6 +126,16 @@ class JSConfigHelper { $dataLocation = false; } + if ($this->currentUser instanceof IUser) { + $lastConfirmTimestamp = $this->currentUser->getLastLogin(); + $sessionTime = $this->session->get('last-password-confirm'); + if (is_int($sessionTime)) { + $lastConfirmTimestamp = $sessionTime; + } + } else { + $lastConfirmTimestamp = 0; + } + $array = [ "oc_debug" => $this->config->getSystemValue('debug', false) ? 'true' : 'false', "oc_isadmin" => $this->groupManager->isAdmin($uid) ? 'true' : 'false', @@ -126,6 +143,7 @@ class JSConfigHelper { "oc_webroot" => "\"".\OC::$WEBROOT."\"", "oc_appswebroots" => str_replace('\\/', '/', json_encode($apps_paths)), // Ugly unescape slashes waiting for better solution "datepickerFormatDate" => json_encode($this->l->l('jsdate', null)), + 'nc_lastLogin' => $lastConfirmTimestamp, "dayNames" => json_encode([ (string)$this->l->t('Sunday'), (string)$this->l->t('Monday'), @@ -189,7 +207,7 @@ class JSConfigHelper { 'versionstring' => \OC_Util::getVersionString(), 'enable_avatars' => $this->config->getSystemValue('enable_avatars', true) === true, 'lost_password_link'=> $this->config->getSystemValue('lost_password_link', null), - 'modRewriteWorking' => (getenv('front_controller_active') === 'true'), + 'modRewriteWorking' => (\OC::$server->getConfig()->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true'), ]), "oc_appconfig" => json_encode([ 'core' => [ diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php index 7878737bdef..8919f14216e 100644 --- a/lib/private/TemplateLayout.php +++ b/lib/private/TemplateLayout.php @@ -148,6 +148,7 @@ class TemplateLayout extends \OC_Template { \OC::$server->getL10N('core'), \OC::$server->getThemingDefaults(), \OC::$server->getAppManager(), + \OC::$server->getSession(), \OC::$server->getUserSession()->getUser(), \OC::$server->getConfig(), \OC::$server->getGroupManager(), diff --git a/lib/private/URLGenerator.php b/lib/private/URLGenerator.php index 93517dc9f7e..c6f1ebd4594 100644 --- a/lib/private/URLGenerator.php +++ b/lib/private/URLGenerator.php @@ -3,6 +3,7 @@ * @copyright Copyright (c) 2016, ownCloud, Inc. * * @author Bart Visscher <bartv@thisnet.nl> + * @author Felix Anand Epp <work@felixepp.de> * @author Joas Schilling <coding@schilljs.com> * @author Jörn Friedrich Dreyer <jfd@butonic.de> * @author Lukas Reschke <lukas@statuscode.ch> @@ -93,7 +94,7 @@ class URLGenerator implements IURLGenerator { * Returns a url to the given app and file. */ public function linkTo( $app, $file, $args = array() ) { - $frontControllerActive = (getenv('front_controller_active') === 'true'); + $frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true'); if( $app != '' ) { $app_path = \OC_App::getAppPath($app); @@ -157,7 +158,16 @@ class URLGenerator implements IURLGenerator { // Check if the app is in the app folder $path = ''; - if (file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) { + $themingEnabled = $this->config->getSystemValue('installed', false) && \OCP\App::isEnabled('theming'); + if($themingEnabled && $image === "favicon.ico" && \OC::$server->getThemingDefaults()->shouldReplaceIcons()) { + $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0'); + if($app==="") { $app = "core"; } + $path = $this->linkToRoute('theming.Icon.getFavicon', [ 'app' => $app ]) . '?v='. $cacheBusterValue; + } elseif($themingEnabled && $image === "favicon-touch.png" && \OC::$server->getThemingDefaults()->shouldReplaceIcons()) { + $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0'); + if($app==="") { $app = "core"; } + $path = $this->linkToRoute('theming.Icon.getTouchIcon', [ 'app' => $app ]) . '?v='. $cacheBusterValue; + } elseif (file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) { $path = \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$image"; } elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.svg") && file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.png")) { diff --git a/lib/private/Updater.php b/lib/private/Updater.php index 2fed67988b8..c3d8ef9fea3 100644 --- a/lib/private/Updater.php +++ b/lib/private/Updater.php @@ -53,7 +53,7 @@ class Updater extends BasicEmitter { /** @var ILogger $log */ private $log; - + /** @var IConfig */ private $config; diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index ef408aa4077..a45b1dcd10f 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -525,10 +525,11 @@ class Session implements IUserSession, Emitter { //login $this->setUser($user); $this->setLoginName($dbToken->getLoginName()); + \OC::$server->getLockdownManager()->setToken($dbToken); $this->manager->emit('\OC\User', 'postLogin', array($user, $password)); if ($this->isLoggedIn()) { - $this->prepareUserLogin(); + $this->prepareUserLogin(false); // token login cant be the first } else { // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory $message = \OC::$server->getL10N('lib')->t('Login canceled by app'); diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php index 33b18c0c6a2..0d9adfa9d2b 100644 --- a/lib/private/legacy/app.php +++ b/lib/private/legacy/app.php @@ -376,11 +376,15 @@ class OC_App { $config, $l ); + $appPath = self::getAppPath($appId); + self::registerAutoloading($appId, $appPath); $installer->installApp($appId); } else { // check for required dependencies $info = self::getAppInfo($appId); self::checkAppDependencies($config, $l, $info); + $appPath = self::getAppPath($appId); + self::registerAutoloading($appId, $appPath); $installer->installApp($appId); } diff --git a/lib/private/legacy/defaults.php b/lib/private/legacy/defaults.php index 23590cd9235..6abc399bc82 100644 --- a/lib/private/legacy/defaults.php +++ b/lib/private/legacy/defaults.php @@ -283,4 +283,7 @@ class OC_Defaults { } } + public function shouldReplaceIcons() { + return false; + } } diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php index 3bd5b5586ab..cc665b5ec65 100644 --- a/lib/private/legacy/util.php +++ b/lib/private/legacy/util.php @@ -14,6 +14,7 @@ * @author Christoph Wurst <christoph@owncloud.com> * @author Clark Tomlinson <fallen013@gmail.com> * @author cmeh <cmeh@users.noreply.github.com> + * @author Felix Anand Epp <work@felixepp.de> * @author Florin Peter <github@florin-peter.de> * @author Frank Karlitschek <frank@karlitschek.de> * @author Georg Ehrke <georg@owncloud.com> @@ -524,7 +525,7 @@ class OC_Util { * * @param string $application application id * @param string $languageCode language code, defaults to the current language - * @param bool $prepend prepend the Script to the beginning of the list + * @param bool $prepend prepend the Script to the beginning of the list */ public static function addTranslations($application, $languageCode = null, $prepend = false) { if (is_null($languageCode)) { @@ -569,7 +570,7 @@ class OC_Util { * * @param string $application application id * @param bool $prepend prepend the file to the beginning of the list - * @param string $path + * @param string $path * @param string $type (script or style) * @return void */ @@ -1076,7 +1077,7 @@ class OC_Util { } } - if(getenv('front_controller_active') === 'true') { + if(\OC::$server->getConfig()->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true') { $location = $urlGenerator->getAbsoluteURL('/apps/' . $appId . '/'); } else { $location = $urlGenerator->getAbsoluteURL('/index.php/apps/' . $appId . '/'); diff --git a/lib/public/Activity/IEvent.php b/lib/public/Activity/IEvent.php index a12ba8642a1..850af06359e 100644 --- a/lib/public/Activity/IEvent.php +++ b/lib/public/Activity/IEvent.php @@ -1,6 +1,7 @@ <?php /** * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> * * @author Joas Schilling <coding@schilljs.com> * diff --git a/lib/public/Activity/IFilter.php b/lib/public/Activity/IFilter.php index e5b65a7d91f..bfe8ea9e472 100644 --- a/lib/public/Activity/IFilter.php +++ b/lib/public/Activity/IFilter.php @@ -1,24 +1,21 @@ <?php /** - * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> * - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Thomas Müller <thomas.mueller@tmit.eu> + * @license GNU AGPL version 3 or any later version * - * @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 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 + * 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/> + * 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/>. * */ diff --git a/lib/public/App/AppPathNotFoundException.php b/lib/public/App/AppPathNotFoundException.php new file mode 100644 index 00000000000..071eb2f8377 --- /dev/null +++ b/lib/public/App/AppPathNotFoundException.php @@ -0,0 +1,31 @@ +<?php +/** + * @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net> + * + * @author Julius Härtl <jus@bitgrid.net> + * + * @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 OCP\App; + +/** + * Class AppPathNotFoundException + * + * @package OCP\App + * @since 11.0.0 + */ +class AppPathNotFoundException extends \Exception {}
\ No newline at end of file diff --git a/lib/public/App/IAppManager.php b/lib/public/App/IAppManager.php index 44990b7c47c..057a964ce0a 100644 --- a/lib/public/App/IAppManager.php +++ b/lib/public/App/IAppManager.php @@ -79,6 +79,16 @@ interface IAppManager { public function disableApp($appId); /** + * Get the directory for the given app. + * + * @param string $appId + * @return string + * @since 11.0.0 + * @throws AppPathNotFoundException + */ + public function getAppPath($appId); + + /** * List all apps enabled for a user * * @param \OCP\IUser $user diff --git a/lib/public/AppFramework/Http/IOutput.php b/lib/public/AppFramework/Http/IOutput.php index 1544c7d6375..642bcf4170f 100644 --- a/lib/public/AppFramework/Http/IOutput.php +++ b/lib/public/AppFramework/Http/IOutput.php @@ -39,7 +39,7 @@ interface IOutput { public function setOutput($out); /** - * @param string $path + * @param string|resource $path or file handle * * @return bool false if an error occurred * @since 8.1.0 diff --git a/lib/public/AppFramework/Http/StreamResponse.php b/lib/public/AppFramework/Http/StreamResponse.php index b5852fb5620..e124bb4ccbf 100644 --- a/lib/public/AppFramework/Http/StreamResponse.php +++ b/lib/public/AppFramework/Http/StreamResponse.php @@ -37,7 +37,7 @@ class StreamResponse extends Response implements ICallbackResponse { private $filePath; /** - * @param string $filePath the path to the file which should be streamed + * @param string|resource $filePath the path to the file or a file handle which should be streamed * @since 8.1.0 */ public function __construct ($filePath) { @@ -54,7 +54,7 @@ class StreamResponse extends Response implements ICallbackResponse { public function callback (IOutput $output) { // handle caching if ($output->getHttpResponseCode() !== Http::STATUS_NOT_MODIFIED) { - if (!file_exists($this->filePath)) { + if (!(file_exists($this->filePath) || is_resource($this->filePath))) { $output->setHttpResponseCode(Http::STATUS_NOT_FOUND); } elseif ($output->setReadfile($this->filePath) === false) { $output->setHttpResponseCode(Http::STATUS_BAD_REQUEST); diff --git a/lib/public/IPreview.php b/lib/public/IPreview.php index cddf7fc6a66..a1a03fee3e1 100644 --- a/lib/public/IPreview.php +++ b/lib/public/IPreview.php @@ -43,6 +43,11 @@ use OCP\Files\NotFoundException; */ interface IPreview { + /** + * @since 9.2.0 + */ + const EVENT = self::class . ':' . 'PreviewRequested'; + const MODE_FILL = 'fill'; const MODE_COVER = 'cover'; diff --git a/lib/public/Lockdown/ILockdownManager.php b/lib/public/Lockdown/ILockdownManager.php new file mode 100644 index 00000000000..d4d05b37ff8 --- /dev/null +++ b/lib/public/Lockdown/ILockdownManager.php @@ -0,0 +1,50 @@ +<?php + +/** + * @copyright Copyright (c) 2016, Robin Appelman <robin@icewind.nl> + * + * 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 OCP\Lockdown; + +use OC\Authentication\Token\IToken; + +/** + * @since 9.2 + */ +interface ILockdownManager { + /** + * Enable the lockdown restrictions + * + * @since 9.2 + */ + public function enable(); + + /** + * Set the active token to get the restrictions from and enable the lockdown + * + * @param IToken $token + * @since 9.2 + */ + public function setToken(IToken $token); + + /** + * Check whether or not filesystem access is allowed + * + * @return bool + * @since 9.2 + */ + public function canAccessFilesystem(); +} diff --git a/lib/public/Share/IShare.php b/lib/public/Share/IShare.php index 206b0e286a2..5b552b51c3c 100644 --- a/lib/public/Share/IShare.php +++ b/lib/public/Share/IShare.php @@ -22,6 +22,7 @@ namespace OCP\Share; +use OCP\Files\Cache\ICacheEntry; use OCP\Files\File; use OCP\Files\Folder; use OCP\Files\Node; @@ -324,4 +325,20 @@ interface IShare { * @since 9.0.0 */ public function getMailSend(); + + /** + * Set the cache entry for the shared node + * + * @param ICacheEntry $entry + * @since 11.0.0 + */ + public function setNodeCacheEntry(ICacheEntry $entry); + + /** + * Get the cache entry for the shared node + * + * @return null|ICacheEntry + * @since 11.0.0 + */ + public function getNodeCacheEntry(); } |