diff options
Diffstat (limited to 'lib')
69 files changed, 1725 insertions, 161 deletions
diff --git a/lib/base.php b/lib/base.php index 29778f02a45..c76d83cd220 100644 --- a/lib/base.php +++ b/lib/base.php @@ -543,40 +543,21 @@ class OC { $requestUri = $request->getScriptName(); $processingScript = explode('/', $requestUri); $processingScript = $processingScript[count($processingScript)-1]; - // FIXME: In a SAML scenario we don't get any strict or lax cookie - // send for the ACS endpoint. Since we have some legacy code in Nextcloud - // (direct PHP files) the enforcement of lax cookies is performed here - // instead of the middleware. - // - // This means we cannot exclude some routes from the cookie validation, - // which normally is not a problem but is a little bit cumbersome for - // this use-case. - // Once the old legacy PHP endpoints have been removed we can move - // the verification into a middleware and also adds some exemptions. - // - // Questions about this code? Ask Lukas ;-) - $currentUrl = substr(explode('?',$request->getRequestUri(), 2)[0], strlen(\OC::$WEBROOT)); - if($currentUrl === '/index.php/apps/user_saml/saml/acs' || $currentUrl === '/apps/user_saml/saml/acs') { + + // index.php routes are handled in the middleware + if($processingScript === 'index.php') { return; } - // For the "index.php" endpoint only a lax cookie is required. - if($processingScript === 'index.php') { - if(!$request->passesLaxCookieCheck()) { - self::sendSameSiteCookies(); - header('Location: '.$_SERVER['REQUEST_URI']); + + // All other endpoints require the lax and the strict cookie + if(!$request->passesStrictCookieCheck()) { + self::sendSameSiteCookies(); + // Debug mode gets access to the resources without strict cookie + // due to the fact that the SabreDAV browser also lives there. + if(!\OC::$server->getConfig()->getSystemValue('debug', false)) { + http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE); exit(); } - } else { - // All other endpoints require the lax and the strict cookie - if(!$request->passesStrictCookieCheck()) { - self::sendSameSiteCookies(); - // Debug mode gets access to the resources without strict cookie - // due to the fact that the SabreDAV browser also lives there. - if(!\OC::$server->getConfig()->getSystemValue('debug', false)) { - http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE); - exit(); - } - } } } elseif(!isset($_COOKIE['nc_sameSiteCookielax']) || !isset($_COOKIE['nc_sameSiteCookiestrict'])) { self::sendSameSiteCookies(); diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 92793969c1b..9341bd1a762 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -68,6 +68,10 @@ return array( 'OCP\\BackgroundJob\\IJobList' => $baseDir . '/lib/public/BackgroundJob/IJobList.php', 'OCP\\Capabilities\\ICapability' => $baseDir . '/lib/public/Capabilities/ICapability.php', 'OCP\\Capabilities\\IPublicCapability' => $baseDir . '/lib/public/Capabilities/IPublicCapability.php', + 'OCP\\Collaboration\\Collaborators\\ISearch' => $baseDir . '/lib/public/Collaboration/Collaborators/ISearch.php', + 'OCP\\Collaboration\\Collaborators\\ISearchPlugin' => $baseDir . '/lib/public/Collaboration/Collaborators/ISearchPlugin.php', + 'OCP\\Collaboration\\Collaborators\\ISearchResult' => $baseDir . '/lib/public/Collaboration/Collaborators/ISearchResult.php', + 'OCP\\Collaboration\\Collaborators\\SearchResultType' => $baseDir . '/lib/public/Collaboration/Collaborators/SearchResultType.php', 'OCP\\Command\\IBus' => $baseDir . '/lib/public/Command/IBus.php', 'OCP\\Command\\ICommand' => $baseDir . '/lib/public/Command/ICommand.php', 'OCP\\Comments\\CommentsEntityEvent' => $baseDir . '/lib/public/Comments/CommentsEntityEvent.php', @@ -222,6 +226,7 @@ return array( 'OCP\\Lockdown\\ILockdownManager' => $baseDir . '/lib/public/Lockdown/ILockdownManager.php', 'OCP\\Mail\\IEMailTemplate' => $baseDir . '/lib/public/Mail/IEMailTemplate.php', 'OCP\\Mail\\IMailer' => $baseDir . '/lib/public/Mail/IMailer.php', + 'OCP\\Migration\\BigIntMigration' => $baseDir . '/lib/public/Migration/BigIntMigration.php', 'OCP\\Migration\\IMigrationStep' => $baseDir . '/lib/public/Migration/IMigrationStep.php', 'OCP\\Migration\\IOutput' => $baseDir . '/lib/public/Migration/IOutput.php', 'OCP\\Migration\\IRepairStep' => $baseDir . '/lib/public/Migration/IRepairStep.php', @@ -306,12 +311,14 @@ return array( 'OC\\AppFramework\\Middleware\\Security\\CORSMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php', '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\\LaxSameSiteCookieFailedException' => $baseDir . '/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.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', 'OC\\AppFramework\\Middleware\\Security\\RateLimitingMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php', + 'OC\\AppFramework\\Middleware\\Security\\SameSiteCookieMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php', 'OC\\AppFramework\\Middleware\\Security\\SecurityMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php', 'OC\\AppFramework\\Middleware\\SessionMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/SessionMiddleware.php', 'OC\\AppFramework\\OCS\\BaseResponse' => $baseDir . '/lib/private/AppFramework/OCS/BaseResponse.php', @@ -381,6 +388,13 @@ return array( 'OC\\Cache\\CappedMemoryCache' => $baseDir . '/lib/private/Cache/CappedMemoryCache.php', 'OC\\Cache\\File' => $baseDir . '/lib/private/Cache/File.php', 'OC\\CapabilitiesManager' => $baseDir . '/lib/private/CapabilitiesManager.php', + 'OC\\Collaboration\\Collaborators\\GroupPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/GroupPlugin.php', + 'OC\\Collaboration\\Collaborators\\LookupPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/LookupPlugin.php', + 'OC\\Collaboration\\Collaborators\\MailPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/MailPlugin.php', + 'OC\\Collaboration\\Collaborators\\RemotePlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/RemotePlugin.php', + 'OC\\Collaboration\\Collaborators\\Search' => $baseDir . '/lib/private/Collaboration/Collaborators/Search.php', + 'OC\\Collaboration\\Collaborators\\SearchResult' => $baseDir . '/lib/private/Collaboration/Collaborators/SearchResult.php', + 'OC\\Collaboration\\Collaborators\\UserPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/UserPlugin.php', 'OC\\Command\\AsyncBus' => $baseDir . '/lib/private/Command/AsyncBus.php', 'OC\\Command\\CallableJob' => $baseDir . '/lib/private/Command/CallableJob.php', 'OC\\Command\\ClosureJob' => $baseDir . '/lib/private/Command/ClosureJob.php', @@ -496,6 +510,7 @@ return array( 'OC\\Core\\Migrations\\Version13000Date20170718121200' => $baseDir . '/core/Migrations/Version13000Date20170718121200.php', 'OC\\Core\\Migrations\\Version13000Date20170814074715' => $baseDir . '/core/Migrations/Version13000Date20170814074715.php', 'OC\\Core\\Migrations\\Version13000Date20170919121250' => $baseDir . '/core/Migrations/Version13000Date20170919121250.php', + 'OC\\Core\\Migrations\\Version13000Date20170926101637' => $baseDir . '/core/Migrations/Version13000Date20170926101637.php', 'OC\\DB\\Adapter' => $baseDir . '/lib/private/DB/Adapter.php', 'OC\\DB\\AdapterMySQL' => $baseDir . '/lib/private/DB/AdapterMySQL.php', 'OC\\DB\\AdapterOCI8' => $baseDir . '/lib/private/DB/AdapterOCI8.php', @@ -512,6 +527,7 @@ return array( 'OC\\DB\\MySQLMigrator' => $baseDir . '/lib/private/DB/MySQLMigrator.php', 'OC\\DB\\MySqlTools' => $baseDir . '/lib/private/DB/MySqlTools.php', 'OC\\DB\\NoCheckMigrator' => $baseDir . '/lib/private/DB/NoCheckMigrator.php', + 'OC\\DB\\OCPostgreSqlPlatform' => $baseDir . '/lib/private/DB/OCPostgreSqlPlatform.php', 'OC\\DB\\OCSqlitePlatform' => $baseDir . '/lib/private/DB/OCSqlitePlatform.php', 'OC\\DB\\OracleConnection' => $baseDir . '/lib/private/DB/OracleConnection.php', 'OC\\DB\\OracleMigrator' => $baseDir . '/lib/private/DB/OracleMigrator.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index e8ce53061a2..5715ff6ed05 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -98,6 +98,10 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\BackgroundJob\\IJobList' => __DIR__ . '/../../..' . '/lib/public/BackgroundJob/IJobList.php', 'OCP\\Capabilities\\ICapability' => __DIR__ . '/../../..' . '/lib/public/Capabilities/ICapability.php', 'OCP\\Capabilities\\IPublicCapability' => __DIR__ . '/../../..' . '/lib/public/Capabilities/IPublicCapability.php', + 'OCP\\Collaboration\\Collaborators\\ISearch' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/ISearch.php', + 'OCP\\Collaboration\\Collaborators\\ISearchPlugin' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/ISearchPlugin.php', + 'OCP\\Collaboration\\Collaborators\\ISearchResult' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/ISearchResult.php', + 'OCP\\Collaboration\\Collaborators\\SearchResultType' => __DIR__ . '/../../..' . '/lib/public/Collaboration/Collaborators/SearchResultType.php', 'OCP\\Command\\IBus' => __DIR__ . '/../../..' . '/lib/public/Command/IBus.php', 'OCP\\Command\\ICommand' => __DIR__ . '/../../..' . '/lib/public/Command/ICommand.php', 'OCP\\Comments\\CommentsEntityEvent' => __DIR__ . '/../../..' . '/lib/public/Comments/CommentsEntityEvent.php', @@ -252,6 +256,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Lockdown\\ILockdownManager' => __DIR__ . '/../../..' . '/lib/public/Lockdown/ILockdownManager.php', 'OCP\\Mail\\IEMailTemplate' => __DIR__ . '/../../..' . '/lib/public/Mail/IEMailTemplate.php', 'OCP\\Mail\\IMailer' => __DIR__ . '/../../..' . '/lib/public/Mail/IMailer.php', + 'OCP\\Migration\\BigIntMigration' => __DIR__ . '/../../..' . '/lib/public/Migration/BigIntMigration.php', 'OCP\\Migration\\IMigrationStep' => __DIR__ . '/../../..' . '/lib/public/Migration/IMigrationStep.php', 'OCP\\Migration\\IOutput' => __DIR__ . '/../../..' . '/lib/public/Migration/IOutput.php', 'OCP\\Migration\\IRepairStep' => __DIR__ . '/../../..' . '/lib/public/Migration/IRepairStep.php', @@ -336,12 +341,14 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\AppFramework\\Middleware\\Security\\CORSMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php', '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\\LaxSameSiteCookieFailedException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.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', 'OC\\AppFramework\\Middleware\\Security\\RateLimitingMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php', + 'OC\\AppFramework\\Middleware\\Security\\SameSiteCookieMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php', 'OC\\AppFramework\\Middleware\\Security\\SecurityMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php', 'OC\\AppFramework\\Middleware\\SessionMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/SessionMiddleware.php', 'OC\\AppFramework\\OCS\\BaseResponse' => __DIR__ . '/../../..' . '/lib/private/AppFramework/OCS/BaseResponse.php', @@ -411,6 +418,13 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Cache\\CappedMemoryCache' => __DIR__ . '/../../..' . '/lib/private/Cache/CappedMemoryCache.php', 'OC\\Cache\\File' => __DIR__ . '/../../..' . '/lib/private/Cache/File.php', 'OC\\CapabilitiesManager' => __DIR__ . '/../../..' . '/lib/private/CapabilitiesManager.php', + 'OC\\Collaboration\\Collaborators\\GroupPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/GroupPlugin.php', + 'OC\\Collaboration\\Collaborators\\LookupPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/LookupPlugin.php', + 'OC\\Collaboration\\Collaborators\\MailPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/MailPlugin.php', + 'OC\\Collaboration\\Collaborators\\RemotePlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/RemotePlugin.php', + 'OC\\Collaboration\\Collaborators\\Search' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/Search.php', + 'OC\\Collaboration\\Collaborators\\SearchResult' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/SearchResult.php', + 'OC\\Collaboration\\Collaborators\\UserPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/UserPlugin.php', 'OC\\Command\\AsyncBus' => __DIR__ . '/../../..' . '/lib/private/Command/AsyncBus.php', 'OC\\Command\\CallableJob' => __DIR__ . '/../../..' . '/lib/private/Command/CallableJob.php', 'OC\\Command\\ClosureJob' => __DIR__ . '/../../..' . '/lib/private/Command/ClosureJob.php', @@ -526,6 +540,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Core\\Migrations\\Version13000Date20170718121200' => __DIR__ . '/../../..' . '/core/Migrations/Version13000Date20170718121200.php', 'OC\\Core\\Migrations\\Version13000Date20170814074715' => __DIR__ . '/../../..' . '/core/Migrations/Version13000Date20170814074715.php', 'OC\\Core\\Migrations\\Version13000Date20170919121250' => __DIR__ . '/../../..' . '/core/Migrations/Version13000Date20170919121250.php', + 'OC\\Core\\Migrations\\Version13000Date20170926101637' => __DIR__ . '/../../..' . '/core/Migrations/Version13000Date20170926101637.php', 'OC\\DB\\Adapter' => __DIR__ . '/../../..' . '/lib/private/DB/Adapter.php', 'OC\\DB\\AdapterMySQL' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterMySQL.php', 'OC\\DB\\AdapterOCI8' => __DIR__ . '/../../..' . '/lib/private/DB/AdapterOCI8.php', @@ -542,6 +557,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\DB\\MySQLMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/MySQLMigrator.php', 'OC\\DB\\MySqlTools' => __DIR__ . '/../../..' . '/lib/private/DB/MySqlTools.php', 'OC\\DB\\NoCheckMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/NoCheckMigrator.php', + 'OC\\DB\\OCPostgreSqlPlatform' => __DIR__ . '/../../..' . '/lib/private/DB/OCPostgreSqlPlatform.php', 'OC\\DB\\OCSqlitePlatform' => __DIR__ . '/../../..' . '/lib/private/DB/OCSqlitePlatform.php', 'OC\\DB\\OracleConnection' => __DIR__ . '/../../..' . '/lib/private/DB/OracleConnection.php', 'OC\\DB\\OracleMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/OracleMigrator.php', diff --git a/lib/l10n/cs.js b/lib/l10n/cs.js index aec9881d4c8..20c6ad9d241 100644 --- a/lib/l10n/cs.js +++ b/lib/l10n/cs.js @@ -173,6 +173,7 @@ OC.L10N.register( "Username must not consist of dots only" : "Uživatelské jméno se nesmí skládat ze samých teček", "A valid password must be provided" : "Musíte zadat platné heslo", "The username is already being used" : "Uživatelské jméno je již využíváno", + "Could not create user" : "Nepodařilo se vytvořit uživatele", "User disabled" : "Uživatel zakázán", "Login canceled by app" : "Přihlášení zrušeno aplikací", "No app name specified" : "Nebyl zadan název aplikace", diff --git a/lib/l10n/cs.json b/lib/l10n/cs.json index 410829a38af..d9f4b8ba636 100644 --- a/lib/l10n/cs.json +++ b/lib/l10n/cs.json @@ -171,6 +171,7 @@ "Username must not consist of dots only" : "Uživatelské jméno se nesmí skládat ze samých teček", "A valid password must be provided" : "Musíte zadat platné heslo", "The username is already being used" : "Uživatelské jméno je již využíváno", + "Could not create user" : "Nepodařilo se vytvořit uživatele", "User disabled" : "Uživatel zakázán", "Login canceled by app" : "Přihlášení zrušeno aplikací", "No app name specified" : "Nebyl zadan název aplikace", diff --git a/lib/l10n/de.js b/lib/l10n/de.js index 57ff861609e..55cb34bebca 100644 --- a/lib/l10n/de.js +++ b/lib/l10n/de.js @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Einen Administrator-Benutzernamen setzen.", "Set an admin password." : "Ein Administrator-Passwort setzen.", "Can't create or write into the data directory %s" : "Das Datenverzeichnis %s kann nicht erstellt oder es kann darin nicht geschrieben werden.", + "Given database host is invalid and must not contain the port: %s" : "Der angegebene Datenbank-Host ist ungültig und muss den Port beinhalten: %s", "Invalid Federated Cloud ID" : "Ungültige Federated-Cloud-ID", "Sharing %s failed, because the backend does not allow shares from type %i" : "Freigabe von %s fehlgeschlagen, da das Backend die Freigabe vom Typ %i nicht erlaubt.", "Sharing %s failed, because the file does not exist" : "Freigabe von %s fehlgeschlagen, da die Datei nicht existiert", diff --git a/lib/l10n/de.json b/lib/l10n/de.json index e3d3bbc508b..bb4de9e6f27 100644 --- a/lib/l10n/de.json +++ b/lib/l10n/de.json @@ -82,6 +82,7 @@ "Set an admin username." : "Einen Administrator-Benutzernamen setzen.", "Set an admin password." : "Ein Administrator-Passwort setzen.", "Can't create or write into the data directory %s" : "Das Datenverzeichnis %s kann nicht erstellt oder es kann darin nicht geschrieben werden.", + "Given database host is invalid and must not contain the port: %s" : "Der angegebene Datenbank-Host ist ungültig und muss den Port beinhalten: %s", "Invalid Federated Cloud ID" : "Ungültige Federated-Cloud-ID", "Sharing %s failed, because the backend does not allow shares from type %i" : "Freigabe von %s fehlgeschlagen, da das Backend die Freigabe vom Typ %i nicht erlaubt.", "Sharing %s failed, because the file does not exist" : "Freigabe von %s fehlgeschlagen, da die Datei nicht existiert", diff --git a/lib/l10n/de_DE.js b/lib/l10n/de_DE.js index 6daa00b3a4f..a4fdf0dc371 100644 --- a/lib/l10n/de_DE.js +++ b/lib/l10n/de_DE.js @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Einen Administrator-Benutzernamen setzen.", "Set an admin password." : "Ein Administrator-Passwort setzen.", "Can't create or write into the data directory %s" : "Das Datenverzeichnis %s kann nicht erstellt oder es kann darin nicht geschrieben werden.", + "Given database host is invalid and must not contain the port: %s" : "Der angegebene Datenbank-Host ist ungültig und muss den Port beinhalten: %s", "Invalid Federated Cloud ID" : "Ungültige Federated-Cloud-ID", "Sharing %s failed, because the backend does not allow shares from type %i" : "Freigabe von %s fehlgeschlagen, da das Backend die Freigabe vom Typ %i nicht erlaubt.", "Sharing %s failed, because the file does not exist" : "Freigabe von %s fehlgeschlagen, da die Datei nicht existiert", diff --git a/lib/l10n/de_DE.json b/lib/l10n/de_DE.json index 1311285bc77..6a8299bc31f 100644 --- a/lib/l10n/de_DE.json +++ b/lib/l10n/de_DE.json @@ -82,6 +82,7 @@ "Set an admin username." : "Einen Administrator-Benutzernamen setzen.", "Set an admin password." : "Ein Administrator-Passwort setzen.", "Can't create or write into the data directory %s" : "Das Datenverzeichnis %s kann nicht erstellt oder es kann darin nicht geschrieben werden.", + "Given database host is invalid and must not contain the port: %s" : "Der angegebene Datenbank-Host ist ungültig und muss den Port beinhalten: %s", "Invalid Federated Cloud ID" : "Ungültige Federated-Cloud-ID", "Sharing %s failed, because the backend does not allow shares from type %i" : "Freigabe von %s fehlgeschlagen, da das Backend die Freigabe vom Typ %i nicht erlaubt.", "Sharing %s failed, because the file does not exist" : "Freigabe von %s fehlgeschlagen, da die Datei nicht existiert", diff --git a/lib/l10n/en_GB.js b/lib/l10n/en_GB.js index aedd831de38..a169502af15 100644 --- a/lib/l10n/en_GB.js +++ b/lib/l10n/en_GB.js @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Set an admin username.", "Set an admin password." : "Set an admin password.", "Can't create or write into the data directory %s" : "Can't create or write into the data directory %s", + "Given database host is invalid and must not contain the port: %s" : "Given database host is invalid and must not contain the port: %s", "Invalid Federated Cloud ID" : "Invalid Federated Cloud ID", "Sharing %s failed, because the backend does not allow shares from type %i" : "Sharing %s failed, because the backend does not allow shares from type %i", "Sharing %s failed, because the file does not exist" : "Sharing %s failed, because the file does not exist", diff --git a/lib/l10n/en_GB.json b/lib/l10n/en_GB.json index 9a113df3b16..bf08239be71 100644 --- a/lib/l10n/en_GB.json +++ b/lib/l10n/en_GB.json @@ -82,6 +82,7 @@ "Set an admin username." : "Set an admin username.", "Set an admin password." : "Set an admin password.", "Can't create or write into the data directory %s" : "Can't create or write into the data directory %s", + "Given database host is invalid and must not contain the port: %s" : "Given database host is invalid and must not contain the port: %s", "Invalid Federated Cloud ID" : "Invalid Federated Cloud ID", "Sharing %s failed, because the backend does not allow shares from type %i" : "Sharing %s failed, because the backend does not allow shares from type %i", "Sharing %s failed, because the file does not exist" : "Sharing %s failed, because the file does not exist", diff --git a/lib/l10n/es.js b/lib/l10n/es.js index f7805c86832..14eda42f187 100644 --- a/lib/l10n/es.js +++ b/lib/l10n/es.js @@ -1,13 +1,13 @@ OC.L10N.register( "lib", { - "Cannot write into \"config\" directory!" : "¡No se puede escribir en el directorio \"config\"!", - "This can usually be fixed by giving the webserver write access to the config directory" : "Esto puede solucionarse fácilmente dándole al servidor permisos de escritura del directorio de configuración", - "See %s" : "Mirar %s", - "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Habitualmente, esto puede arreglarse dando al servidor web acceso de escritura al directorio de configuración. Véase %s", + "Cannot write into \"config\" directory!" : "No se puede escribir en la carpeta \"config\"", + "This can usually be fixed by giving the webserver write access to the config directory" : "Esto podría ser solucionado dándole al servidor permisos de escritura del directorio de configuración", + "See %s" : "Ver %s", + "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Esto podría ser solucionado dándole al servidor permisos de escritura del directorio de configuración. Ver %s", "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Los archivos de la aplicación %$1s no fueron reemplazados correctamente. Asegúrese que es una versión compatible con el servidor.", "Sample configuration detected" : "Ejemplo de configuración detectado", - "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" : "Se ha detectado que el ejemplo de configuración ha sido copiado. Esto puede arruinar su instalación y es un caso para el que no se brinda soporte. Lea la documentación antes de hacer cambios en config.php", + "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" : "Se ha detectado que el ejemplo de configuración ha sido copiado. Esto podría afectar a su instalación, por lo que no tiene soporte. Lea la documentación antes de hacer cambios en config.php", "%1$s and %2$s" : "%1$s y %2$s", "%1$s, %2$s and %3$s" : "%1$s, %2$s y %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s, y %4$s", @@ -17,7 +17,7 @@ OC.L10N.register( "Groupware bundle" : "Conjunto de groupware", "Social sharing bundle" : "Conjunto para compartir en redes", "PHP %s or higher is required." : "Se requiere PHP %s o superior.", - "PHP with a version lower than %s is required." : "PHP con una versión inferior que %s la requerida.", + "PHP with a version lower than %s is required." : "Se necesita una versión de PHP inferior a %s", "%sbit or higher PHP required." : "Se requiere PHP %sbit o superior.", "Following databases are supported: %s" : "Las siguientes bases de datos están soportadas: %s", "The command line tool %s could not be found" : "No se encontró la herramienta %s de línea de comandos", @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Configurar un nombre de usuario del administrador", "Set an admin password." : "Configurar la contraseña del administrador.", "Can't create or write into the data directory %s" : "No es posible crear o escribir en el directorio de datos %s", + "Given database host is invalid and must not contain the port: %s" : "El servidor de la base de datos dado es inválido y no debe contener el puerto: %s", "Invalid Federated Cloud ID" : "ID Nube federada inválida", "Sharing %s failed, because the backend does not allow shares from type %i" : "No se pudo compartir %s porque el repositorio no permite recursos compartidos del tipo %i", "Sharing %s failed, because the file does not exist" : "No se pudo compartir %s porque el archivo no existe", diff --git a/lib/l10n/es.json b/lib/l10n/es.json index f599a8ffc10..23227e69ac6 100644 --- a/lib/l10n/es.json +++ b/lib/l10n/es.json @@ -1,11 +1,11 @@ { "translations": { - "Cannot write into \"config\" directory!" : "¡No se puede escribir en el directorio \"config\"!", - "This can usually be fixed by giving the webserver write access to the config directory" : "Esto puede solucionarse fácilmente dándole al servidor permisos de escritura del directorio de configuración", - "See %s" : "Mirar %s", - "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Habitualmente, esto puede arreglarse dando al servidor web acceso de escritura al directorio de configuración. Véase %s", + "Cannot write into \"config\" directory!" : "No se puede escribir en la carpeta \"config\"", + "This can usually be fixed by giving the webserver write access to the config directory" : "Esto podría ser solucionado dándole al servidor permisos de escritura del directorio de configuración", + "See %s" : "Ver %s", + "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Esto podría ser solucionado dándole al servidor permisos de escritura del directorio de configuración. Ver %s", "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Los archivos de la aplicación %$1s no fueron reemplazados correctamente. Asegúrese que es una versión compatible con el servidor.", "Sample configuration detected" : "Ejemplo de configuración detectado", - "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" : "Se ha detectado que el ejemplo de configuración ha sido copiado. Esto puede arruinar su instalación y es un caso para el que no se brinda soporte. Lea la documentación antes de hacer cambios en config.php", + "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" : "Se ha detectado que el ejemplo de configuración ha sido copiado. Esto podría afectar a su instalación, por lo que no tiene soporte. Lea la documentación antes de hacer cambios en config.php", "%1$s and %2$s" : "%1$s y %2$s", "%1$s, %2$s and %3$s" : "%1$s, %2$s y %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s, y %4$s", @@ -15,7 +15,7 @@ "Groupware bundle" : "Conjunto de groupware", "Social sharing bundle" : "Conjunto para compartir en redes", "PHP %s or higher is required." : "Se requiere PHP %s o superior.", - "PHP with a version lower than %s is required." : "PHP con una versión inferior que %s la requerida.", + "PHP with a version lower than %s is required." : "Se necesita una versión de PHP inferior a %s", "%sbit or higher PHP required." : "Se requiere PHP %sbit o superior.", "Following databases are supported: %s" : "Las siguientes bases de datos están soportadas: %s", "The command line tool %s could not be found" : "No se encontró la herramienta %s de línea de comandos", @@ -82,6 +82,7 @@ "Set an admin username." : "Configurar un nombre de usuario del administrador", "Set an admin password." : "Configurar la contraseña del administrador.", "Can't create or write into the data directory %s" : "No es posible crear o escribir en el directorio de datos %s", + "Given database host is invalid and must not contain the port: %s" : "El servidor de la base de datos dado es inválido y no debe contener el puerto: %s", "Invalid Federated Cloud ID" : "ID Nube federada inválida", "Sharing %s failed, because the backend does not allow shares from type %i" : "No se pudo compartir %s porque el repositorio no permite recursos compartidos del tipo %i", "Sharing %s failed, because the file does not exist" : "No se pudo compartir %s porque el archivo no existe", diff --git a/lib/l10n/es_MX.js b/lib/l10n/es_MX.js index ecec10607b4..bc252633450 100644 --- a/lib/l10n/es_MX.js +++ b/lib/l10n/es_MX.js @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Establecer un Usuario administrador", "Set an admin password." : "Establecer la contraseña del administrador.", "Can't create or write into the data directory %s" : "No es posible crear o escribir en el directorio de datos %s", + "Given database host is invalid and must not contain the port: %s" : "El servidor de base de datos ingresado es inválido y no debe contener el puerto: %s", "Invalid Federated Cloud ID" : "ID Inválido", "Sharing %s failed, because the backend does not allow shares from type %i" : "Se presentó una falla al compartir %s, porque el backend no permite elementos compartidos de tipo %i", "Sharing %s failed, because the file does not exist" : "Se presentó una falla al compartir %s porque el archivo no existe", diff --git a/lib/l10n/es_MX.json b/lib/l10n/es_MX.json index 5f05674435c..6a7c6474bb9 100644 --- a/lib/l10n/es_MX.json +++ b/lib/l10n/es_MX.json @@ -82,6 +82,7 @@ "Set an admin username." : "Establecer un Usuario administrador", "Set an admin password." : "Establecer la contraseña del administrador.", "Can't create or write into the data directory %s" : "No es posible crear o escribir en el directorio de datos %s", + "Given database host is invalid and must not contain the port: %s" : "El servidor de base de datos ingresado es inválido y no debe contener el puerto: %s", "Invalid Federated Cloud ID" : "ID Inválido", "Sharing %s failed, because the backend does not allow shares from type %i" : "Se presentó una falla al compartir %s, porque el backend no permite elementos compartidos de tipo %i", "Sharing %s failed, because the file does not exist" : "Se presentó una falla al compartir %s porque el archivo no existe", diff --git a/lib/l10n/fr.js b/lib/l10n/fr.js index 9257203dfff..09685ca62a3 100644 --- a/lib/l10n/fr.js +++ b/lib/l10n/fr.js @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Spécifiez un nom d'utilisateur pour l'administrateur.", "Set an admin password." : "Spécifiez un mot de passe pour l'administrateur.", "Can't create or write into the data directory %s" : "Impossible de créer, ou d'écrire dans, le répertoire des données %s", + "Given database host is invalid and must not contain the port: %s" : "L'hôte de la base de donnée donné est invalide et ne doit pas contenir le port: %s", "Invalid Federated Cloud ID" : "ID Federated Cloud incorrect", "Sharing %s failed, because the backend does not allow shares from type %i" : "Le partage de %s a échoué car l’infrastructure n'autorise pas les partages de type %i", "Sharing %s failed, because the file does not exist" : "Le partage de %s a échoué car le fichier n'existe pas", diff --git a/lib/l10n/fr.json b/lib/l10n/fr.json index da9e80b617c..0fdb86e49a0 100644 --- a/lib/l10n/fr.json +++ b/lib/l10n/fr.json @@ -82,6 +82,7 @@ "Set an admin username." : "Spécifiez un nom d'utilisateur pour l'administrateur.", "Set an admin password." : "Spécifiez un mot de passe pour l'administrateur.", "Can't create or write into the data directory %s" : "Impossible de créer, ou d'écrire dans, le répertoire des données %s", + "Given database host is invalid and must not contain the port: %s" : "L'hôte de la base de donnée donné est invalide et ne doit pas contenir le port: %s", "Invalid Federated Cloud ID" : "ID Federated Cloud incorrect", "Sharing %s failed, because the backend does not allow shares from type %i" : "Le partage de %s a échoué car l’infrastructure n'autorise pas les partages de type %i", "Sharing %s failed, because the file does not exist" : "Le partage de %s a échoué car le fichier n'existe pas", diff --git a/lib/l10n/it.js b/lib/l10n/it.js index 03b6dc69a2d..e044abfa39d 100644 --- a/lib/l10n/it.js +++ b/lib/l10n/it.js @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Imposta un nome utente di amministrazione.", "Set an admin password." : "Imposta una password di amministrazione.", "Can't create or write into the data directory %s" : "Impossibile creare o scrivere nella cartella dei dati %s", + "Given database host is invalid and must not contain the port: %s" : "L'host del database fornito non è valido e deve contenere la porta: %s", "Invalid Federated Cloud ID" : "ID di cloud federata non valido", "Sharing %s failed, because the backend does not allow shares from type %i" : "Condivisione di %s non riuscita, poiché il motore non consente condivisioni del tipo %i", "Sharing %s failed, because the file does not exist" : "Condivisione di %s non riuscita, poiché il file non esiste", diff --git a/lib/l10n/it.json b/lib/l10n/it.json index bdfa78d45bb..2d7734ea007 100644 --- a/lib/l10n/it.json +++ b/lib/l10n/it.json @@ -82,6 +82,7 @@ "Set an admin username." : "Imposta un nome utente di amministrazione.", "Set an admin password." : "Imposta una password di amministrazione.", "Can't create or write into the data directory %s" : "Impossibile creare o scrivere nella cartella dei dati %s", + "Given database host is invalid and must not contain the port: %s" : "L'host del database fornito non è valido e deve contenere la porta: %s", "Invalid Federated Cloud ID" : "ID di cloud federata non valido", "Sharing %s failed, because the backend does not allow shares from type %i" : "Condivisione di %s non riuscita, poiché il motore non consente condivisioni del tipo %i", "Sharing %s failed, because the file does not exist" : "Condivisione di %s non riuscita, poiché il file non esiste", diff --git a/lib/l10n/nb.js b/lib/l10n/nb.js index 4ee0de2cc9b..07a63961ba6 100644 --- a/lib/l10n/nb.js +++ b/lib/l10n/nb.js @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Sett et admin-brukernavn.", "Set an admin password." : "Sett et admin-passord.", "Can't create or write into the data directory %s" : "Kan ikke opprette eller skrive i datamappen %s", + "Given database host is invalid and must not contain the port: %s" : "Oppgitt databasevert er ugyldig og kan ikke inneholde porten: %s", "Invalid Federated Cloud ID" : "Ugyldig ID for sammenknyttet sky", "Sharing %s failed, because the backend does not allow shares from type %i" : "Deling av %s mislyktes, fordi tjeneren ikke tillater delinger fra type %i", "Sharing %s failed, because the file does not exist" : "Deling av %s mislyktes, fordi filen ikke eksisterer", @@ -109,7 +110,7 @@ OC.L10N.register( "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Deling av %s mislyktes, fordi tillatelsene går utover tillatelsene som er gitt til %s", "Sharing %s failed, because resharing is not allowed" : "Deling av %s mislyktes, fordi videre-deling ikke er tillatt", "Sharing %s failed, because the sharing backend for %s could not find its source" : "Deling av %s mislyktes, fordi delings-bakenden for %s ikke kunne finne kilden", - "Sharing %s failed, because the file could not be found in the file cache" : "Deling av %s mislyktes, fordi filen ikke ble funnet i fil-mellomlageret", + "Sharing %s failed, because the file could not be found in the file cache" : "Deling av %s mislyktes, fordi filen ikke ble funnet i fil-hurtiglageret", "Can’t increase permissions of %s" : "Kan ikke øke tillatelser for %s", "Files can’t be shared with delete permissions" : "Filer kan ikke deles med tilgang til sletting", "Files can’t be shared with create permissions" : "Filer kan ikke deles med tilgang til opprettelse", @@ -204,7 +205,7 @@ OC.L10N.register( "libxml2 2.7.0 is at least required. Currently %s is installed." : "Krever minst libxml2 2.7.0. Per nå er %s installert.", "To fix this issue update your libxml2 version and restart your web server." : "For å fikse dette problemet, oppdater din libxml2 versjon og omstart vevtjeneren.", "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "Det ser ut til at at PHP er satt opp til å fjerne innebygde doc-blokker. Dette gjør at flere av kjerneapplikasjonene blir utilgjengelige.", - "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dette forårsakes sannsynligvis av en bufrer/akselerator, som f.eks. Zend OPcache eller eAccelerator.", + "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dette forårsakes sannsynligvis av hurtiglager/akselerator, som f.eks. Zend OPcache eller eAccelerator.", "PHP modules have been installed, but they are still listed as missing?" : "PHP-moduler har blitt installert, men de listes fortsatt som fraværende?", "Please ask your server administrator to restart the web server." : "Be tjener-administratoren om å starte vevtjeneren på nytt.", "PostgreSQL >= 9 required" : "PostgreSQL >= 9 kreves", diff --git a/lib/l10n/nb.json b/lib/l10n/nb.json index d62b5998f73..f69217b3b18 100644 --- a/lib/l10n/nb.json +++ b/lib/l10n/nb.json @@ -82,6 +82,7 @@ "Set an admin username." : "Sett et admin-brukernavn.", "Set an admin password." : "Sett et admin-passord.", "Can't create or write into the data directory %s" : "Kan ikke opprette eller skrive i datamappen %s", + "Given database host is invalid and must not contain the port: %s" : "Oppgitt databasevert er ugyldig og kan ikke inneholde porten: %s", "Invalid Federated Cloud ID" : "Ugyldig ID for sammenknyttet sky", "Sharing %s failed, because the backend does not allow shares from type %i" : "Deling av %s mislyktes, fordi tjeneren ikke tillater delinger fra type %i", "Sharing %s failed, because the file does not exist" : "Deling av %s mislyktes, fordi filen ikke eksisterer", @@ -107,7 +108,7 @@ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Deling av %s mislyktes, fordi tillatelsene går utover tillatelsene som er gitt til %s", "Sharing %s failed, because resharing is not allowed" : "Deling av %s mislyktes, fordi videre-deling ikke er tillatt", "Sharing %s failed, because the sharing backend for %s could not find its source" : "Deling av %s mislyktes, fordi delings-bakenden for %s ikke kunne finne kilden", - "Sharing %s failed, because the file could not be found in the file cache" : "Deling av %s mislyktes, fordi filen ikke ble funnet i fil-mellomlageret", + "Sharing %s failed, because the file could not be found in the file cache" : "Deling av %s mislyktes, fordi filen ikke ble funnet i fil-hurtiglageret", "Can’t increase permissions of %s" : "Kan ikke øke tillatelser for %s", "Files can’t be shared with delete permissions" : "Filer kan ikke deles med tilgang til sletting", "Files can’t be shared with create permissions" : "Filer kan ikke deles med tilgang til opprettelse", @@ -202,7 +203,7 @@ "libxml2 2.7.0 is at least required. Currently %s is installed." : "Krever minst libxml2 2.7.0. Per nå er %s installert.", "To fix this issue update your libxml2 version and restart your web server." : "For å fikse dette problemet, oppdater din libxml2 versjon og omstart vevtjeneren.", "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "Det ser ut til at at PHP er satt opp til å fjerne innebygde doc-blokker. Dette gjør at flere av kjerneapplikasjonene blir utilgjengelige.", - "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dette forårsakes sannsynligvis av en bufrer/akselerator, som f.eks. Zend OPcache eller eAccelerator.", + "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dette forårsakes sannsynligvis av hurtiglager/akselerator, som f.eks. Zend OPcache eller eAccelerator.", "PHP modules have been installed, but they are still listed as missing?" : "PHP-moduler har blitt installert, men de listes fortsatt som fraværende?", "Please ask your server administrator to restart the web server." : "Be tjener-administratoren om å starte vevtjeneren på nytt.", "PostgreSQL >= 9 required" : "PostgreSQL >= 9 kreves", diff --git a/lib/l10n/pl.js b/lib/l10n/pl.js index 89a5842b88b..20965576b7b 100644 --- a/lib/l10n/pl.js +++ b/lib/l10n/pl.js @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Ustaw nazwę administratora.", "Set an admin password." : "Ustaw hasło administratora.", "Can't create or write into the data directory %s" : "Nie można tworzyć ani zapisywać w katalogu %s", + "Given database host is invalid and must not contain the port: %s" : "Podany host bazy danych jest nieprawidłowy i nie może zawierać portu: %s", "Invalid Federated Cloud ID" : "Nieprawidłowy ID Stowarzyszonej Chmury", "Sharing %s failed, because the backend does not allow shares from type %i" : "Współdzielenie %s nie udało się, ponieważ backend nie pozwala na współdzielenie takiego typu jak %i.", "Sharing %s failed, because the file does not exist" : "Wspóldzielenie %s nie powiodło się. ponieważ plik nie istnieje", diff --git a/lib/l10n/pl.json b/lib/l10n/pl.json index 1967561da88..6d4a34b7c6b 100644 --- a/lib/l10n/pl.json +++ b/lib/l10n/pl.json @@ -82,6 +82,7 @@ "Set an admin username." : "Ustaw nazwę administratora.", "Set an admin password." : "Ustaw hasło administratora.", "Can't create or write into the data directory %s" : "Nie można tworzyć ani zapisywać w katalogu %s", + "Given database host is invalid and must not contain the port: %s" : "Podany host bazy danych jest nieprawidłowy i nie może zawierać portu: %s", "Invalid Federated Cloud ID" : "Nieprawidłowy ID Stowarzyszonej Chmury", "Sharing %s failed, because the backend does not allow shares from type %i" : "Współdzielenie %s nie udało się, ponieważ backend nie pozwala na współdzielenie takiego typu jak %i.", "Sharing %s failed, because the file does not exist" : "Wspóldzielenie %s nie powiodło się. ponieważ plik nie istnieje", diff --git a/lib/l10n/pt_BR.js b/lib/l10n/pt_BR.js index 85959121d24..c9ee6e9cc02 100644 --- a/lib/l10n/pt_BR.js +++ b/lib/l10n/pt_BR.js @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Defina um nome do usuário administrador.", "Set an admin password." : "Defina uma senha para o administrador.", "Can't create or write into the data directory %s" : "Não foi possível criar ou gravar no diretório de dados %s", + "Given database host is invalid and must not contain the port: %s" : "O host do banco de dados é inválido e não deve conter a porta: %s", "Invalid Federated Cloud ID" : "ID inválida de Nuvem Federada", "Sharing %s failed, because the backend does not allow shares from type %i" : "O compartilhamento %s falhou pois a plataforma de serviço não permite ações de tipo %i", "Sharing %s failed, because the file does not exist" : "Compartilhamento %s falhou pois o arquivo não existe", diff --git a/lib/l10n/pt_BR.json b/lib/l10n/pt_BR.json index b6f9bcbbc0e..b1eb976064f 100644 --- a/lib/l10n/pt_BR.json +++ b/lib/l10n/pt_BR.json @@ -82,6 +82,7 @@ "Set an admin username." : "Defina um nome do usuário administrador.", "Set an admin password." : "Defina uma senha para o administrador.", "Can't create or write into the data directory %s" : "Não foi possível criar ou gravar no diretório de dados %s", + "Given database host is invalid and must not contain the port: %s" : "O host do banco de dados é inválido e não deve conter a porta: %s", "Invalid Federated Cloud ID" : "ID inválida de Nuvem Federada", "Sharing %s failed, because the backend does not allow shares from type %i" : "O compartilhamento %s falhou pois a plataforma de serviço não permite ações de tipo %i", "Sharing %s failed, because the file does not exist" : "Compartilhamento %s falhou pois o arquivo não existe", diff --git a/lib/l10n/ru.js b/lib/l10n/ru.js index a5c32da43d1..109c0f66938 100644 --- a/lib/l10n/ru.js +++ b/lib/l10n/ru.js @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Задать имя пользователя для администратора.", "Set an admin password." : "Задать пароль для admin.", "Can't create or write into the data directory %s" : "Невозможно создать или записать в каталог данных %s", + "Given database host is invalid and must not contain the port: %s" : "Узел базы данных указан неверно: он не должен содержать номер порта: %s", "Invalid Federated Cloud ID" : "Неверный ID в объединении облачных хранилищ.", "Sharing %s failed, because the backend does not allow shares from type %i" : "Не удалось поделиться %s, так как механизм хранения не допускает публикации из элементов типа %i", "Sharing %s failed, because the file does not exist" : "Не удалось поделиться %s, файл не существует", diff --git a/lib/l10n/ru.json b/lib/l10n/ru.json index 660469dda56..553aa793810 100644 --- a/lib/l10n/ru.json +++ b/lib/l10n/ru.json @@ -82,6 +82,7 @@ "Set an admin username." : "Задать имя пользователя для администратора.", "Set an admin password." : "Задать пароль для admin.", "Can't create or write into the data directory %s" : "Невозможно создать или записать в каталог данных %s", + "Given database host is invalid and must not contain the port: %s" : "Узел базы данных указан неверно: он не должен содержать номер порта: %s", "Invalid Federated Cloud ID" : "Неверный ID в объединении облачных хранилищ.", "Sharing %s failed, because the backend does not allow shares from type %i" : "Не удалось поделиться %s, так как механизм хранения не допускает публикации из элементов типа %i", "Sharing %s failed, because the file does not exist" : "Не удалось поделиться %s, файл не существует", diff --git a/lib/l10n/sv.js b/lib/l10n/sv.js index bd5576e87b3..364b64aa550 100644 --- a/lib/l10n/sv.js +++ b/lib/l10n/sv.js @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Ange ett användarnamn för administratören.", "Set an admin password." : "Ange ett administratörslösenord.", "Can't create or write into the data directory %s" : "Kan inte skapa eller skriva till data-katalogen %s", + "Given database host is invalid and must not contain the port: %s" : "Angiven databasvärd är ogiltig och måste innehålla porten: %s", "Invalid Federated Cloud ID" : "Ogiltigt Federerat Moln-ID", "Sharing %s failed, because the backend does not allow shares from type %i" : "Misslyckades dela ut %s då backend inte tillåter delningar från typ %i", "Sharing %s failed, because the file does not exist" : "Delning av %s misslyckades på grund av att filen inte existerar", @@ -179,7 +180,7 @@ OC.L10N.register( "No app name specified" : "Inget appnamn angivet", "App '%s' could not be installed!" : "Applikationen \"%s\" gick inte att installera!", "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "Applikationen \"%s\" kan ej installeras eftersom följande kriterier inte är uppfyllda: %s", - "a safe home for all your data" : "En säker plats för dina filer och data", + "a safe home for all your data" : "En säker lagringsplats för all din data", "File is currently busy, please try again later" : "Filen är för tillfället upptagen, vänligen försök igen senare", "Can't read file" : "Kan ej läsa filen", "Application is not enabled" : "Applikationen är inte aktiverad", diff --git a/lib/l10n/sv.json b/lib/l10n/sv.json index 49101a5889c..1b599ae3e96 100644 --- a/lib/l10n/sv.json +++ b/lib/l10n/sv.json @@ -82,6 +82,7 @@ "Set an admin username." : "Ange ett användarnamn för administratören.", "Set an admin password." : "Ange ett administratörslösenord.", "Can't create or write into the data directory %s" : "Kan inte skapa eller skriva till data-katalogen %s", + "Given database host is invalid and must not contain the port: %s" : "Angiven databasvärd är ogiltig och måste innehålla porten: %s", "Invalid Federated Cloud ID" : "Ogiltigt Federerat Moln-ID", "Sharing %s failed, because the backend does not allow shares from type %i" : "Misslyckades dela ut %s då backend inte tillåter delningar från typ %i", "Sharing %s failed, because the file does not exist" : "Delning av %s misslyckades på grund av att filen inte existerar", @@ -177,7 +178,7 @@ "No app name specified" : "Inget appnamn angivet", "App '%s' could not be installed!" : "Applikationen \"%s\" gick inte att installera!", "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "Applikationen \"%s\" kan ej installeras eftersom följande kriterier inte är uppfyllda: %s", - "a safe home for all your data" : "En säker plats för dina filer och data", + "a safe home for all your data" : "En säker lagringsplats för all din data", "File is currently busy, please try again later" : "Filen är för tillfället upptagen, vänligen försök igen senare", "Can't read file" : "Kan ej läsa filen", "Application is not enabled" : "Applikationen är inte aktiverad", diff --git a/lib/l10n/tr.js b/lib/l10n/tr.js index b1d5f60a905..12c64e8b2b1 100644 --- a/lib/l10n/tr.js +++ b/lib/l10n/tr.js @@ -39,7 +39,7 @@ OC.L10N.register( "_%n year ago_::_%n years ago_" : ["%n yıl önce","%n yıl önce"], "_%n hour ago_::_%n hours ago_" : ["%n saat önce","%n saat önce"], "_%n minute ago_::_%n minutes ago_" : ["%n dakika önce","%n dakika önce"], - "seconds ago" : "saniye önce", + "seconds ago" : "saniyeler önce", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "%s kodlu modül bulunamadı. Lütfen uygulamalarınız içinden modülü etkinleştirin ya da sistem yöneticinizle görüşün.", "File name is a reserved word" : "Bu dosya adı sistem kullanıma ayrılmıştır", "File name contains at least one invalid character" : "Dosya adında en az bir geçersiz karakter var", @@ -84,6 +84,7 @@ OC.L10N.register( "Set an admin username." : "Bir yönetici kullanıcı adı yazın.", "Set an admin password." : "Bir yönetici parolası yazın.", "Can't create or write into the data directory %s" : "%s veri klasörü oluşturulamadı ya da içine yazılamadı", + "Given database host is invalid and must not contain the port: %s" : "Belirtilen veritabanı sunucusu geçersiz ve şu kapıyı kullanmamalı: %s", "Invalid Federated Cloud ID" : "Birleşmiş Bulut Kimliği Geçersiz", "Sharing %s failed, because the backend does not allow shares from type %i" : "Arka uç %s türündeki paylaşımlara izin vermediğinden %s paylaşılamadı", "Sharing %s failed, because the file does not exist" : "Dosya bulunamadığından %s paylaşılamadı", diff --git a/lib/l10n/tr.json b/lib/l10n/tr.json index a8d82273338..3ed52c7fe26 100644 --- a/lib/l10n/tr.json +++ b/lib/l10n/tr.json @@ -37,7 +37,7 @@ "_%n year ago_::_%n years ago_" : ["%n yıl önce","%n yıl önce"], "_%n hour ago_::_%n hours ago_" : ["%n saat önce","%n saat önce"], "_%n minute ago_::_%n minutes ago_" : ["%n dakika önce","%n dakika önce"], - "seconds ago" : "saniye önce", + "seconds ago" : "saniyeler önce", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "%s kodlu modül bulunamadı. Lütfen uygulamalarınız içinden modülü etkinleştirin ya da sistem yöneticinizle görüşün.", "File name is a reserved word" : "Bu dosya adı sistem kullanıma ayrılmıştır", "File name contains at least one invalid character" : "Dosya adında en az bir geçersiz karakter var", @@ -82,6 +82,7 @@ "Set an admin username." : "Bir yönetici kullanıcı adı yazın.", "Set an admin password." : "Bir yönetici parolası yazın.", "Can't create or write into the data directory %s" : "%s veri klasörü oluşturulamadı ya da içine yazılamadı", + "Given database host is invalid and must not contain the port: %s" : "Belirtilen veritabanı sunucusu geçersiz ve şu kapıyı kullanmamalı: %s", "Invalid Federated Cloud ID" : "Birleşmiş Bulut Kimliği Geçersiz", "Sharing %s failed, because the backend does not allow shares from type %i" : "Arka uç %s türündeki paylaşımlara izin vermediğinden %s paylaşılamadı", "Sharing %s failed, because the file does not exist" : "Dosya bulunamadığından %s paylaşılamadı", diff --git a/lib/private/App/InfoParser.php b/lib/private/App/InfoParser.php index fef8ab7a1e8..40eaaf21bca 100644 --- a/lib/private/App/InfoParser.php +++ b/lib/private/App/InfoParser.php @@ -122,6 +122,21 @@ class InfoParser { if (!array_key_exists('providers', $array['activity'])) { $array['activity']['providers'] = []; } + if (!array_key_exists('settings', $array)) { + $array['settings'] = []; + } + if (!array_key_exists('admin', $array['settings'])) { + $array['settings']['admin'] = []; + } + if (!array_key_exists('admin-section', $array['settings'])) { + $array['settings']['admin-section'] = []; + } + if (!array_key_exists('personal', $array['settings'])) { + $array['settings']['personal'] = []; + } + if (!array_key_exists('personal-section', $array['settings'])) { + $array['settings']['personal-section'] = []; + } if (array_key_exists('types', $array)) { if (is_array($array['types'])) { @@ -165,6 +180,24 @@ class InfoParser { if (isset($array['activity']['providers']['provider']) && is_array($array['activity']['providers']['provider'])) { $array['activity']['providers'] = $array['activity']['providers']['provider']; } + if (isset($array['collaboration']['collaborators']['searchPlugins']['searchPlugin']) + && is_array($array['collaboration']['collaborators']['searchPlugins']['searchPlugin']) + && !isset($array['collaboration']['collaborators']['searchPlugins']['searchPlugin']['class']) + ) { + $array['collaboration']['collaborators']['searchPlugins'] = $array['collaboration']['collaborators']['searchPlugins']['searchPlugin']; + } + if (isset($array['settings']['admin']) && !is_array($array['settings']['admin'])) { + $array['settings']['admin'] = [$array['settings']['admin']]; + } + if (isset($array['settings']['admin-section']) && !is_array($array['settings']['admin-section'])) { + $array['settings']['admin-section'] = [$array['settings']['admin-section']]; + } + if (isset($array['settings']['personal']) && !is_array($array['settings']['personal'])) { + $array['settings']['personal'] = [$array['settings']['personal']]; + } + if (isset($array['settings']['personal-section']) && !is_array($array['settings']['personal-section'])) { + $array['settings']['personal-section'] = [$array['settings']['personal-section']]; + } if(!is_null($this->cache)) { $this->cache->set($fileCacheKey, json_encode($array)); diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php index e33ffdca96c..2290f0d0045 100644 --- a/lib/private/AppFramework/DependencyInjection/DIContainer.php +++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php @@ -291,9 +291,17 @@ class DIContainer extends SimpleContainer implements IAppContainer { ); }); + $this->registerService(OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware::class, function (SimpleContainer $c) { + return new OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware( + $c['Request'], + $c['ControllerMethodReflector'] + ); + }); + $middleWares = &$this->middleWares; $this->registerService('MiddlewareDispatcher', function($c) use (&$middleWares) { $dispatcher = new MiddlewareDispatcher(); + $dispatcher->registerMiddleware($c[OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware::class]); $dispatcher->registerMiddleware($c['CORSMiddleware']); $dispatcher->registerMiddleware($c['OCSMiddleware']); $dispatcher->registerMiddleware($c['SecurityMiddleware']); diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php index 7e21434c734..d2347ba4b28 100644 --- a/lib/private/AppFramework/Http/Request.php +++ b/lib/private/AppFramework/Http/Request.php @@ -507,7 +507,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { * * @return array */ - protected function getCookieParams() { + public function getCookieParams() { return session_get_cookie_params(); } diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.php new file mode 100644 index 00000000000..5161886d02e --- /dev/null +++ b/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.php @@ -0,0 +1,38 @@ +<?php +/** + * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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\AppFramework\Middleware\Security\Exceptions; + +use OCP\AppFramework\Http; + +/** + * Class LaxSameSiteCookieFailedException is thrown when a request doesn't pass + * the required LaxCookie check on index.php + * + * @package OC\AppFramework\Middleware\Security\Exceptions + */ +class LaxSameSiteCookieFailedException extends SecurityException { + public function __construct() { + parent::__construct('Lax Same Site Cookie is invalid in request.', Http::STATUS_PRECONDITION_FAILED); + } +} diff --git a/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php b/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php new file mode 100644 index 00000000000..22a9246d661 --- /dev/null +++ b/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php @@ -0,0 +1,106 @@ +<?php +/** + * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.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\AppFramework\Middleware\Security; + +use OC\AppFramework\Http\Request; +use OC\AppFramework\Middleware\Security\Exceptions\LaxSameSiteCookieFailedException; +use OC\AppFramework\Utility\ControllerMethodReflector; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Response; +use OCP\AppFramework\Middleware; + +class SameSiteCookieMiddleware extends Middleware { + + /** @var Request */ + private $request; + + /** @var ControllerMethodReflector */ + private $reflector; + + public function __construct(Request $request, + ControllerMethodReflector $reflector) { + $this->request = $request; + $this->reflector = $reflector; + } + + public function beforeController($controller, $methodName) { + $requestUri = $this->request->getScriptName(); + $processingScript = explode('/', $requestUri); + $processingScript = $processingScript[count($processingScript)-1]; + + if ($processingScript !== 'index.php') { + return; + } + + $noSSC = $this->reflector->hasAnnotation('NoSameSiteCookieRequired'); + if ($noSSC) { + return; + } + + if (!$this->request->passesLaxCookieCheck()) { + throw new LaxSameSiteCookieFailedException(); + } + } + + public function afterException($controller, $methodName, \Exception $exception) { + if ($exception instanceof LaxSameSiteCookieFailedException) { + $respone = new Response(); + $respone->setStatus(Http::STATUS_FOUND); + $respone->addHeader('Location', $this->request->getRequestUri()); + + $this->setSameSiteCookie(); + + return $respone; + } + + throw $exception; + } + + protected function setSameSiteCookie() { + $cookieParams = $this->request->getCookieParams(); + $secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : ''; + $policies = [ + 'lax', + 'strict', + ]; + + // Append __Host to the cookie if it meets the requirements + $cookiePrefix = ''; + if($cookieParams['secure'] === true && $cookieParams['path'] === '/') { + $cookiePrefix = '__Host-'; + } + + foreach($policies as $policy) { + header( + sprintf( + 'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s', + $cookiePrefix, + $policy, + $cookieParams['path'], + $policy + ), + false + ); + } + } +} diff --git a/lib/private/Authentication/Token/DefaultTokenProvider.php b/lib/private/Authentication/Token/DefaultTokenProvider.php index a1a7e83ea21..80bcc4aeac8 100644 --- a/lib/private/Authentication/Token/DefaultTokenProvider.php +++ b/lib/private/Authentication/Token/DefaultTokenProvider.php @@ -195,6 +195,7 @@ class DefaultTokenProvider implements IProvider { $newToken->setRemember($token->getRemember()); $newToken->setLastActivity($this->time->getTime()); $this->mapper->insert($newToken); + $this->mapper->delete($token); } /** diff --git a/lib/private/Collaboration/Collaborators/GroupPlugin.php b/lib/private/Collaboration/Collaborators/GroupPlugin.php new file mode 100644 index 00000000000..0b2b3d71028 --- /dev/null +++ b/lib/private/Collaboration/Collaborators/GroupPlugin.php @@ -0,0 +1,124 @@ +<?php +/** + * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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\Collaboration\Collaborators; + +use OCP\Collaboration\Collaborators\ISearchPlugin; +use OCP\Collaboration\Collaborators\ISearchResult; +use OCP\Collaboration\Collaborators\SearchResultType; +use OCP\IConfig; +use OCP\IGroup; +use OCP\IGroupManager; +use OCP\IUserSession; +use OCP\Share; + +class GroupPlugin implements ISearchPlugin { + protected $shareeEnumeration; + protected $shareWithGroupOnly; + + /** @var IGroupManager */ + private $groupManager; + /** @var IConfig */ + private $config; + /** @var IUserSession */ + private $userSession; + + public function __construct(IConfig $config, IGroupManager $groupManager, IUserSession $userSession) { + $this->groupManager = $groupManager; + $this->config = $config; + $this->userSession = $userSession; + + $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; + $this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes'; + } + + public function search($search, $limit, $offset, ISearchResult $searchResult) { + $hasMoreResults = false; + $result = ['wide' => [], 'exact' => []]; + + $groups = $this->groupManager->search($search, $limit, $offset); + $groupIds = array_map(function (IGroup $group) { return $group->getGID(); }, $groups); + + if (!$this->shareeEnumeration || sizeof($groups) < $limit) { + $hasMoreResults = true; + } + + $userGroups = []; + if (!empty($groups) && $this->shareWithGroupOnly) { + // Intersect all the groups that match with the groups this user is a member of + $userGroups = $this->groupManager->getUserGroups($this->userSession->getUser()); + $userGroups = array_map(function (IGroup $group) { return $group->getGID(); }, $userGroups); + $groupIds = array_intersect($groupIds, $userGroups); + } + + $lowerSearch = strtolower($search); + foreach ($groups as $group) { + // FIXME: use a more efficient approach + $gid = $group->getGID(); + if (!in_array($gid, $groupIds)) { + continue; + } + if (strtolower($gid) === $lowerSearch || strtolower($group->getDisplayName()) === $lowerSearch) { + $result['exact'][] = [ + 'label' => $group->getDisplayName(), + 'value' => [ + 'shareType' => Share::SHARE_TYPE_GROUP, + 'shareWith' => $gid, + ], + ]; + } else { + $result['wide'][] = [ + 'label' => $group->getDisplayName(), + 'value' => [ + 'shareType' => Share::SHARE_TYPE_GROUP, + 'shareWith' => $gid, + ], + ]; + } + } + + if ($offset === 0 && empty($result['exact'])) { + // On page one we try if the search result has a direct hit on the + // user id and if so, we add that to the exact match list + $group = $this->groupManager->get($search); + if ($group instanceof IGroup && (!$this->shareWithGroupOnly || in_array($group->getGID(), $userGroups))) { + array_push($result['exact'], [ + 'label' => $group->getDisplayName(), + 'value' => [ + 'shareType' => Share::SHARE_TYPE_GROUP, + 'shareWith' => $group->getGID(), + ], + ]); + } + } + + if (!$this->shareeEnumeration) { + $result['wide'] = []; + } + + $type = new SearchResultType('groups'); + $searchResult->addResultSet($type, $result['wide'], $result['exact']); + + return $hasMoreResults; + } +} diff --git a/lib/private/Collaboration/Collaborators/LookupPlugin.php b/lib/private/Collaboration/Collaborators/LookupPlugin.php new file mode 100644 index 00000000000..3a6a0943772 --- /dev/null +++ b/lib/private/Collaboration/Collaborators/LookupPlugin.php @@ -0,0 +1,85 @@ +<?php +/** + * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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\Collaboration\Collaborators; + + +use OCP\Collaboration\Collaborators\ISearchPlugin; +use OCP\Collaboration\Collaborators\ISearchResult; +use OCP\Collaboration\Collaborators\SearchResultType; +use OCP\Http\Client\IClientService; +use OCP\IConfig; +use OCP\Share; + +class LookupPlugin implements ISearchPlugin { + + /** @var IConfig */ + private $config; + /** @var IClientService */ + private $clientService; + + public function __construct(IConfig $config, IClientService $clientService) { + $this->config = $config; + $this->clientService = $clientService; + } + + public function search($search, $limit, $offset, ISearchResult $searchResult) { + if ($this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no') !== 'yes') { + return false; + } + + $lookupServerUrl = $this->config->getSystemValue('lookup_server', 'https://lookup.nextcloud.com'); + $lookupServerUrl = rtrim($lookupServerUrl, '/'); + $result = []; + + try { + $client = $this->clientService->newClient(); + $response = $client->get( + $lookupServerUrl . '/users?search=' . urlencode($search), + [ + 'timeout' => 10, + 'connect_timeout' => 3, + ] + ); + + $body = json_decode($response->getBody(), true); + + foreach ($body as $lookup) { + $result[] = [ + 'label' => $lookup['federationId'], + 'value' => [ + 'shareType' => Share::SHARE_TYPE_REMOTE, + 'shareWith' => $lookup['federationId'], + ], + 'extra' => $lookup, + ]; + } + } catch (\Exception $e) { + } + + $type = new SearchResultType('lookup'); + $searchResult->addResultSet($type, $result, []); + + return false; + } +} diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php new file mode 100644 index 00000000000..d28bd3692a4 --- /dev/null +++ b/lib/private/Collaboration/Collaborators/MailPlugin.php @@ -0,0 +1,164 @@ +<?php +/** + * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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\Collaboration\Collaborators; + + +use OCP\Collaboration\Collaborators\ISearchPlugin; +use OCP\Collaboration\Collaborators\ISearchResult; +use OCP\Collaboration\Collaborators\SearchResultType; +use OCP\Contacts\IManager; +use OCP\Federation\ICloudIdManager; +use OCP\IConfig; +use OCP\Share; + +class MailPlugin implements ISearchPlugin { + protected $shareeEnumeration; + + /** @var IManager */ + private $contactsManager; + /** @var ICloudIdManager */ + private $cloudIdManager; + /** @var IConfig */ + private $config; + + public function __construct(IManager $contactsManager, ICloudIdManager $cloudIdManager, IConfig $config) { + $this->contactsManager = $contactsManager; + $this->cloudIdManager = $cloudIdManager; + $this->config = $config; + + $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; + } + + /** + * @param $search + * @param $limit + * @param $offset + * @param ISearchResult $searchResult + * @return bool + * @since 13.0.0 + */ + public function search($search, $limit, $offset, ISearchResult $searchResult) { + $result = ['wide' => [], 'exact' => []]; + $userType = new SearchResultType('users'); + $emailType = new SearchResultType('emails'); + + // Search in contacts + //@todo Pagination missing + $addressBookContacts = $this->contactsManager->search($search, ['EMAIL', 'FN']); + $lowerSearch = strtolower($search); + foreach ($addressBookContacts as $contact) { + if (isset($contact['EMAIL'])) { + $emailAddresses = $contact['EMAIL']; + if (!is_array($emailAddresses)) { + $emailAddresses = [$emailAddresses]; + } + foreach ($emailAddresses as $emailAddress) { + $exactEmailMatch = strtolower($emailAddress) === $lowerSearch; + + if (isset($contact['isLocalSystemBook'])) { + if ($exactEmailMatch) { + try { + $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0]); + } catch (\InvalidArgumentException $e) { + continue; + } + + if (!$searchResult->hasResult($userType, $cloud->getUser())) { + $singleResult = [[ + 'label' => $contact['FN'] . " ($emailAddress)", + 'value' => [ + 'shareType' => Share::SHARE_TYPE_USER, + 'shareWith' => $cloud->getUser(), + ], + ]]; + $searchResult->addResultSet($userType, [], $singleResult); + $searchResult->markExactIdMatch($emailType); + } + return false; + } + + if ($this->shareeEnumeration) { + try { + $cloud = $this->cloudIdManager->resolveCloudId($contact['CLOUD'][0]); + } catch (\InvalidArgumentException $e) { + continue; + } + + if (!$searchResult->hasResult($userType, $cloud->getUser())) { + $singleResult = [[ + 'label' => $contact['FN'] . " ($emailAddress)", + 'value' => [ + 'shareType' => Share::SHARE_TYPE_USER, + 'shareWith' => $cloud->getUser(), + ]], + ]; + $searchResult->addResultSet($userType, $singleResult, []); + } + } + continue; + } + + if ($exactEmailMatch || strtolower($contact['FN']) === $lowerSearch) { + if ($exactEmailMatch) { + $searchResult->markExactIdMatch($emailType); + } + $result['exact'][] = [ + 'label' => $contact['FN'] . " ($emailAddress)", + 'value' => [ + 'shareType' => Share::SHARE_TYPE_EMAIL, + 'shareWith' => $emailAddress, + ], + ]; + } else { + $result['wide'][] = [ + 'label' => $contact['FN'] . " ($emailAddress)", + 'value' => [ + 'shareType' => Share::SHARE_TYPE_EMAIL, + 'shareWith' => $emailAddress, + ], + ]; + } + } + } + } + + if (!$this->shareeEnumeration) { + $result['wide'] = []; + } + + if (!$searchResult->hasExactIdMatch($emailType) && filter_var($search, FILTER_VALIDATE_EMAIL)) { + $result['exact'][] = [ + 'label' => $search, + 'value' => [ + 'shareType' => Share::SHARE_TYPE_EMAIL, + 'shareWith' => $search, + ], + ]; + } + + $searchResult->addResultSet($emailType, $result['wide'], $result['exact']); + + return true; + } +} diff --git a/lib/private/Collaboration/Collaborators/RemotePlugin.php b/lib/private/Collaboration/Collaborators/RemotePlugin.php new file mode 100644 index 00000000000..b17a64e4ff1 --- /dev/null +++ b/lib/private/Collaboration/Collaborators/RemotePlugin.php @@ -0,0 +1,137 @@ +<?php +/** + * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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\Collaboration\Collaborators; + + +use OCP\Collaboration\Collaborators\ISearchPlugin; +use OCP\Collaboration\Collaborators\ISearchResult; +use OCP\Collaboration\Collaborators\SearchResultType; +use OCP\Contacts\IManager; +use OCP\Federation\ICloudIdManager; +use OCP\IConfig; +use OCP\Share; + +class RemotePlugin implements ISearchPlugin { + protected $shareeEnumeration; + + /** @var IManager */ + private $contactsManager; + /** @var ICloudIdManager */ + private $cloudIdManager; + /** @var IConfig */ + private $config; + + public function __construct(IManager $contactsManager, ICloudIdManager $cloudIdManager, IConfig $config) { + $this->contactsManager = $contactsManager; + $this->cloudIdManager = $cloudIdManager; + $this->config = $config; + + $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; + } + + public function search($search, $limit, $offset, ISearchResult $searchResult) { + $result = ['wide' => [], 'exact' => []]; + $resultType = new SearchResultType('remotes'); + + // Search in contacts + //@todo Pagination missing + $addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN']); + foreach ($addressBookContacts as $contact) { + if (isset($contact['isLocalSystemBook'])) { + continue; + } + if (isset($contact['CLOUD'])) { + $cloudIds = $contact['CLOUD']; + if (!is_array($cloudIds)) { + $cloudIds = [$cloudIds]; + } + $lowerSearch = strtolower($search); + foreach ($cloudIds as $cloudId) { + try { + list(, $serverUrl) = $this->splitUserRemote($cloudId); + } catch (\InvalidArgumentException $e) { + continue; + } + + if (strtolower($contact['FN']) === $lowerSearch || strtolower($cloudId) === $lowerSearch) { + if (strtolower($cloudId) === $lowerSearch) { + $searchResult->markExactIdMatch($resultType); + } + $result['exact'][] = [ + 'label' => $contact['FN'] . " ($cloudId)", + 'value' => [ + 'shareType' => Share::SHARE_TYPE_REMOTE, + 'shareWith' => $cloudId, + 'server' => $serverUrl, + ], + ]; + } else { + $result['wide'][] = [ + 'label' => $contact['FN'] . " ($cloudId)", + 'value' => [ + 'shareType' => Share::SHARE_TYPE_REMOTE, + 'shareWith' => $cloudId, + 'server' => $serverUrl, + ], + ]; + } + } + } + } + + if (!$this->shareeEnumeration) { + $result['wide'] = []; + } + + if (!$searchResult->hasExactIdMatch($resultType) && $this->cloudIdManager->isValidCloudId($search) && $offset === 0) { + $result['exact'][] = [ + 'label' => $search, + 'value' => [ + 'shareType' => Share::SHARE_TYPE_REMOTE, + 'shareWith' => $search, + ], + ]; + } + + $searchResult->addResultSet($resultType, $result['wide'], $result['exact']); + + return true; + } + + /** + * split user and remote from federated cloud id + * + * @param string $address federated share address + * @return array [user, remoteURL] + * @throws \InvalidArgumentException + */ + public function splitUserRemote($address) { + try { + $cloudId = $this->cloudIdManager->resolveCloudId($address); + return [$cloudId->getUser(), $cloudId->getRemote()]; + } catch (\InvalidArgumentException $e) { + throw new \InvalidArgumentException('Invalid Federated Cloud ID', 0, $e); + } + } +} diff --git a/lib/private/Collaboration/Collaborators/Search.php b/lib/private/Collaboration/Collaborators/Search.php new file mode 100644 index 00000000000..e9b15dd1201 --- /dev/null +++ b/lib/private/Collaboration/Collaborators/Search.php @@ -0,0 +1,89 @@ +<?php +/** + * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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\Collaboration\Collaborators; + +use OCP\Collaboration\Collaborators\ISearch; +use OCP\Collaboration\Collaborators\ISearchPlugin; +use OCP\Collaboration\Collaborators\ISearchResult; +use OCP\Collaboration\Collaborators\SearchResultType; +use OCP\IContainer; +use OCP\Share; + +class Search implements ISearch { + /** @var IContainer */ + private $c; + + protected $pluginList = []; + + public function __construct(IContainer $c) { + $this->c = $c; + } + + public function search($search, array $shareTypes, $lookup, $limit, $offset) { + $hasMoreResults = false; + + /** @var ISearchResult $searchResult */ + $searchResult = $this->c->resolve(SearchResult::class); + + foreach ($shareTypes as $type) { + if(!isset($this->pluginList[$type])) { + continue; + } + foreach ($this->pluginList[$type] as $plugin) { + /** @var ISearchPlugin $searchPlugin */ + $searchPlugin = $this->c->resolve($plugin); + $hasMoreResults |= $searchPlugin->search($search, $limit, $offset, $searchResult); + } + } + + // Get from lookup server, not a separate share type + if ($lookup) { + $searchPlugin = $this->c->resolve(LookupPlugin::class); + $hasMoreResults |= $searchPlugin->search($search, $limit, $offset, $searchResult); + } + + // sanitizing, could go into the plugins as well + + // if we have a exact match, either for the federated cloud id or for the + // email address we only return the exact match. It is highly unlikely + // that the exact same email address and federated cloud id exists + $emailType = new SearchResultType('emails'); + $remoteType = new SearchResultType('remotes'); + if($searchResult->hasExactIdMatch($emailType) && !$searchResult->hasExactIdMatch($remoteType)) { + $searchResult->unsetResult($remoteType); + } elseif (!$searchResult->hasExactIdMatch($emailType) && $searchResult->hasExactIdMatch($remoteType)) { + $searchResult->unsetResult($emailType); + } + + return [$searchResult->asArray(), (bool)$hasMoreResults]; + } + + public function registerPlugin(array $pluginInfo) { + $shareType = constant(Share::class . '::' . $pluginInfo['shareType']); + if($shareType === null) { + throw new \InvalidArgumentException('Provided ShareType is invalid'); + } + $this->pluginList[$shareType][] = $pluginInfo['class']; + } +} diff --git a/lib/private/Collaboration/Collaborators/SearchResult.php b/lib/private/Collaboration/Collaborators/SearchResult.php new file mode 100644 index 00000000000..7b32b388203 --- /dev/null +++ b/lib/private/Collaboration/Collaborators/SearchResult.php @@ -0,0 +1,86 @@ +<?php +/** + * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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\Collaboration\Collaborators; + + +use OCP\Collaboration\Collaborators\ISearchResult; +use OCP\Collaboration\Collaborators\SearchResultType; + +class SearchResult implements ISearchResult { + + protected $result = [ + 'exact' => [], + ]; + + protected $exactIdMatches = []; + + public function addResultSet(SearchResultType $type, array $matches, array $exactMatches = null) { + $type = $type->getLabel(); + if(!isset($this->result[$type])) { + $this->result[$type] = []; + $this->result['exact'][$type] = []; + } + + $this->result[$type] = array_merge($this->result[$type], $matches); + if(is_array($exactMatches)) { + $this->result['exact'][$type] = array_merge($this->result['exact'][$type], $exactMatches); + } + } + + public function markExactIdMatch(SearchResultType $type) { + $this->exactIdMatches[$type->getLabel()] = 1; + } + + public function hasExactIdMatch(SearchResultType$type) { + return isset($this->exactIdMatches[$type->getLabel()]); + } + + public function hasResult(SearchResultType $type, $collaboratorId) { + $type = $type->getLabel(); + if(!isset($this->result[$type])) { + return false; + } + + $resultArrays = [$this->result['exact'][$type], $this->result[$type]]; + foreach($resultArrays as $resultArray) { + if ($resultArray['value']['shareWith'] === $collaboratorId) { + return true; + } + } + + return false; + } + + public function asArray() { + return $this->result; + } + + public function unsetResult(SearchResultType $type) { + $type = $type->getLabel(); + $this->result[$type] = []; + if(isset($this->result['exact'][$type])) { + $this->result['exact'][$type] = []; + } + } +} diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php new file mode 100644 index 00000000000..86a55aa428f --- /dev/null +++ b/lib/private/Collaboration/Collaborators/UserPlugin.php @@ -0,0 +1,149 @@ +<?php +/** + * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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\Collaboration\Collaborators; + + +use OCP\Collaboration\Collaborators\ISearchPlugin; +use OCP\Collaboration\Collaborators\ISearchResult; +use OCP\Collaboration\Collaborators\SearchResultType; +use OCP\IConfig; +use OCP\IGroupManager; +use OCP\IUser; +use OCP\IUserManager; +use OCP\IUserSession; +use OCP\Share; + +class UserPlugin implements ISearchPlugin { + /* @var bool */ + protected $shareWithGroupOnly; + protected $shareeEnumeration; + + /** @var IConfig */ + private $config; + /** @var IGroupManager */ + private $groupManager; + /** @var IUserSession */ + private $userSession; + /** @var IUserManager */ + private $userManager; + + public function __construct(IConfig $config, IUserManager $userManager, IGroupManager $groupManager, IUserSession $userSession) { + $this->config = $config; + + $this->groupManager = $groupManager; + $this->userSession = $userSession; + $this->userManager = $userManager; + + $this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes'; + $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; + } + + public function search($search, $limit, $offset, ISearchResult $searchResult) { + $result = ['wide' => [], 'exact' => []]; + $users = []; + $hasMoreResults = false; + + $userGroups = []; + if ($this->shareWithGroupOnly) { + // Search in all the groups this user is part of + $userGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser()); + foreach ($userGroups as $userGroup) { + $usersTmp = $this->groupManager->displayNamesInGroup($userGroup, $search, $limit, $offset); + foreach ($usersTmp as $uid => $userDisplayName) { + $users[$uid] = $userDisplayName; + } + } + } else { + // Search in all users + $usersTmp = $this->userManager->searchDisplayName($search, $limit, $offset); + + foreach ($usersTmp as $user) { + $users[$user->getUID()] = $user->getDisplayName(); + } + } + + if (!$this->shareeEnumeration || sizeof($users) < $limit) { + $hasMoreResults = true; + } + + $foundUserById = false; + $lowerSearch = strtolower($search); + foreach ($users as $uid => $userDisplayName) { + if (strtolower($uid) === $lowerSearch || strtolower($userDisplayName) === $lowerSearch) { + if (strtolower($uid) === $lowerSearch) { + $foundUserById = true; + } + $result['exact'][] = [ + 'label' => $userDisplayName, + 'value' => [ + 'shareType' => Share::SHARE_TYPE_USER, + 'shareWith' => $uid, + ], + ]; + } else { + $result['wide'][] = [ + 'label' => $userDisplayName, + 'value' => [ + 'shareType' => Share::SHARE_TYPE_USER, + 'shareWith' => $uid, + ], + ]; + } + } + + if ($offset === 0 && !$foundUserById) { + // On page one we try if the search result has a direct hit on the + // user id and if so, we add that to the exact match list + $user = $this->userManager->get($search); + if ($user instanceof IUser) { + $addUser = true; + + if ($this->shareWithGroupOnly) { + // Only add, if we have a common group + $commonGroups = array_intersect($userGroups, $this->groupManager->getUserGroupIds($user)); + $addUser = !empty($commonGroups); + } + + if ($addUser) { + array_push($result['exact'], [ + 'label' => $user->getDisplayName(), + 'value' => [ + 'shareType' => Share::SHARE_TYPE_USER, + 'shareWith' => $user->getUID(), + ], + ]); + } + } + } + + if (!$this->shareeEnumeration) { + $result['wide'] = []; + } + + $type = new SearchResultType('users'); + $searchResult->addResultSet($type, $result['wide'], $result['exact']); + + return $hasMoreResults; + } +} diff --git a/lib/private/DB/ConnectionFactory.php b/lib/private/DB/ConnectionFactory.php index d90d7737d40..8848f6db3b4 100644 --- a/lib/private/DB/ConnectionFactory.php +++ b/lib/private/DB/ConnectionFactory.php @@ -137,6 +137,10 @@ class ConnectionFactory { } unset($additionalConnectionParams['host']); break; + + case 'pgsql': + $additionalConnectionParams['platform'] = new OCPostgreSqlPlatform(); + break; case 'sqlite3': $journalMode = $additionalConnectionParams['sqlite.journal_mode']; $additionalConnectionParams['platform'] = new OCSqlitePlatform(); diff --git a/lib/private/DB/OCPostgreSqlPlatform.php b/lib/private/DB/OCPostgreSqlPlatform.php new file mode 100644 index 00000000000..524a62c2beb --- /dev/null +++ b/lib/private/DB/OCPostgreSqlPlatform.php @@ -0,0 +1,94 @@ +<?php +/** + * @author Victor Dubiniuk <dubiniuk@owncloud.com> + * + * @copyright Copyright (c) 2017, ownCloud GmbH + * @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\DB; + +use Doctrine\DBAL\Platforms\PostgreSqlPlatform; +use Doctrine\DBAL\Schema\ColumnDiff; +use Doctrine\DBAL\Schema\TableDiff; +use Doctrine\DBAL\Types\Type; + +class OCPostgreSqlPlatform extends PostgreSqlPlatform { + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff){ + $queries = parent::getAlterTableSQL($diff); + foreach ($queries as $index => $sql){ + // BIGSERIAL could not be used in statements altering column type + // That's why we replace it with BIGINT + // see https://github.com/owncloud/core/pull/28364#issuecomment-315006853 + if (preg_match('|(ALTER TABLE\s+\S+\s+ALTER\s+\S+\s+TYPE\s+)(BIGSERIAL)|i', $sql, $matches)) { + $alterTable = $matches[1]; + $queries[$index] = $alterTable . 'BIGINT'; + } + + // Changing integer to bigint kills next autoincrement value + // see https://github.com/owncloud/core/pull/28364#issuecomment-315006853 + if (preg_match('|ALTER TABLE\s+(\S+)\s+ALTER\s+(\S+)\s+DROP DEFAULT|i', $sql, $matches)) { + $queryColumnName = $matches[2]; + $columnDiff = $this->findColumnDiffByName($diff, $queryColumnName); + if ($columnDiff && $this->shouldSkipDropDefault($columnDiff)) { + unset($queries[$index]); + continue; + } + } + } + + return $queries; + } + + /** + * We should NOT drop next sequence value if + * - type was changed from INTEGER to BIGINT + * - column keeps an autoincrement + * - default value is kept NULL + * + * @param ColumnDiff $columnDiff + * @return bool + */ + private function shouldSkipDropDefault(ColumnDiff $columnDiff) { + $column = $columnDiff->column; + $fromColumn = $columnDiff->fromColumn; + return $fromColumn->getType()->getName() === Type::INTEGER + && $column->getType()->getName() === Type::BIGINT + && $fromColumn->getDefault() === null + && $column->getDefault() === null + && $fromColumn->getAutoincrement() + && $column->getAutoincrement(); + } + + /** + * @param TableDiff $diff + * @param string $name + * @return ColumnDiff | false + */ + private function findColumnDiffByName(TableDiff $diff, $name) { + foreach ($diff->changedColumns as $columnDiff) { + $oldColumnName = $columnDiff->getOldColumnName()->getQuotedName($this); + if ($oldColumnName === $name) { + return $columnDiff; + } + } + return false; + } +} diff --git a/lib/private/Installer.php b/lib/private/Installer.php index 4d7e5016653..d5082a7fad2 100644 --- a/lib/private/Installer.php +++ b/lib/private/Installer.php @@ -288,7 +288,14 @@ class Installer { $archive = new TAR($tempFile); if($archive) { - $archive->extract($extractDir); + if (!$archive->extract($extractDir)) { + throw new \Exception( + sprintf( + 'Could not extract app %s', + $appId + ) + ); + } $allFiles = scandir($extractDir); $folders = array_diff($allFiles, ['.', '..']); $folders = array_values($folders); diff --git a/lib/private/Log.php b/lib/private/Log.php index d93b29414e6..39577d2387a 100644 --- a/lib/private/Log.php +++ b/lib/private/Log.php @@ -331,6 +331,9 @@ class Log implements ILogger { 'Line' => $exception->getLine(), ); $data['Trace'] = preg_replace('!(' . implode('|', $this->methodsWithSensitiveParameters) . ')\(.*\)!', '$1(*** sensitive parameters replaced ***)', $data['Trace']); + if ($exception instanceof HintException) { + $data['Hint'] = $exception->getHint(); + } $msg = isset($context['message']) ? $context['message'] : 'Exception'; $msg .= ': ' . json_encode($data); $this->log($level, $msg, $context); diff --git a/lib/private/NavigationManager.php b/lib/private/NavigationManager.php index 5e484bea737..3cf4459ddfc 100644 --- a/lib/private/NavigationManager.php +++ b/lib/private/NavigationManager.php @@ -91,6 +91,9 @@ class NavigationManager implements INavigationManager { if(!isset($entry['icon'])) { $entry['icon'] = ''; } + if(!isset($entry['classes'])) { + $entry['classes'] = ''; + } if(!isset($entry['type'])) { $entry['type'] = 'link'; } diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php index 5a264c2bbd5..71e9fdb1a20 100644 --- a/lib/private/Preview/Generator.php +++ b/lib/private/Preview/Generator.php @@ -110,6 +110,12 @@ class Generator { $maxPreview = $this->getMaxPreview($previewFolder, $file, $mimeType); list($maxWidth, $maxHeight) = $this->getPreviewSize($maxPreview); + // If both width and heigth are -1 we just want the max preview + if ($width === -1 && $height === -1) { + $width = $maxWidth; + $height = $maxHeight; + } + // Calculate the preview size list($width, $height) = $this->calculateSize($width, $height, $crop, $mode, $maxWidth, $maxHeight); diff --git a/lib/private/Repair/NC13/RepairInvalidPaths.php b/lib/private/Repair/NC13/RepairInvalidPaths.php index 8e6a4ca0e37..a8ccb9a579f 100644 --- a/lib/private/Repair/NC13/RepairInvalidPaths.php +++ b/lib/private/Repair/NC13/RepairInvalidPaths.php @@ -172,10 +172,18 @@ class RepairInvalidPaths implements IRepairStep { return $count; } - public function run(IOutput $output) { + private function shouldRun() { $versionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0'); - // was added to 12.0.0.30 and 13.0.0.1 - if (version_compare($versionFromBeforeUpdate, '12.0.0.30', '<') || version_compare($versionFromBeforeUpdate, '13.0.0.0', '==')) { + + // was added to 11.0.5.2, 12.0.0.30 and 13.0.0.1 + $shouldRun = version_compare($versionFromBeforeUpdate, '11.0.5.2', '<'); + $shouldRun |= version_compare($versionFromBeforeUpdate, '12.0.0.0', '>=') && version_compare($versionFromBeforeUpdate, '12.0.0.30', '<'); + $shouldRun |= version_compare($versionFromBeforeUpdate, '13.0.0.0', '=='); + return $shouldRun; + } + + public function run(IOutput $output) { + if ($this->shouldRun()) { $count = $this->repair(); $output->info('Repaired ' . $count . ' paths'); diff --git a/lib/private/Server.php b/lib/private/Server.php index a20d9ccfc01..29aee06d896 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -52,6 +52,10 @@ use OC\AppFramework\Http\Request; use OC\AppFramework\Utility\SimpleContainer; use OC\AppFramework\Utility\TimeFactory; use OC\Authentication\LoginCredentials\Store; +use OC\Collaboration\Collaborators\GroupPlugin; +use OC\Collaboration\Collaborators\MailPlugin; +use OC\Collaboration\Collaborators\RemotePlugin; +use OC\Collaboration\Collaborators\UserPlugin; use OC\Command\CronBus; use OC\Contacts\ContactsMenu\ActionFactory; use OC\Diagnostics\EventLogger; @@ -115,6 +119,7 @@ use OCP\Contacts\ContactsMenu\IActionFactory; use OCP\Lock\ILockingProvider; use OCP\RichObjectStrings\IValidator; use OCP\Security\IContentSecurityPolicyManager; +use OCP\Share; use OCP\Share\IShareHelper; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -993,6 +998,19 @@ class Server extends ServerContainer implements IServerContainer { }); $this->registerAlias('ShareManager', \OCP\Share\IManager::class); + $this->registerService(\OCP\Collaboration\Collaborators\ISearch::class, function(Server $c) { + $instance = new Collaboration\Collaborators\Search($c); + + // register default plugins + $instance->registerPlugin(['shareType' => 'SHARE_TYPE_USER', 'class' => UserPlugin::class]); + $instance->registerPlugin(['shareType' => 'SHARE_TYPE_GROUP', 'class' => GroupPlugin::class]); + $instance->registerPlugin(['shareType' => 'SHARE_TYPE_EMAIL', 'class' => MailPlugin::class]); + $instance->registerPlugin(['shareType' => 'SHARE_TYPE_REMOTE', 'class' => RemotePlugin::class]); + + return $instance; + }); + $this->registerAlias('CollaboratorSearch', \OCP\Collaboration\Collaborators\ISearch::class); + $this->registerService('SettingsManager', function (Server $c) { $manager = new \OC\Settings\Manager( $c->getLogger(), @@ -1777,6 +1795,13 @@ class Server extends ServerContainer implements IServerContainer { } /** + * @return \OCP\Collaboration\Collaborators\ISearch + */ + public function getCollaboratorSearch() { + return $this->query('CollaboratorSearch'); + } + + /** * Returns the LDAP Provider * * @return \OCP\LDAP\ILDAPProvider diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php index 3c5ff5670da..8de72ce314e 100644 --- a/lib/private/Settings/Manager.php +++ b/lib/private/Settings/Manager.php @@ -127,18 +127,26 @@ class Manager implements IManager { * @inheritdoc */ public function setupSettings(array $settings) { - if (isset($settings[IManager::KEY_ADMIN_SECTION])) { - $this->setupSectionEntry($settings[IManager::KEY_ADMIN_SECTION], 'admin'); + if (!empty($settings[IManager::KEY_ADMIN_SECTION])) { + foreach ($settings[IManager::KEY_ADMIN_SECTION] as $className) { + $this->setupSectionEntry($className, 'admin'); + } } - if (isset($settings[IManager::KEY_ADMIN_SETTINGS])) { - $this->setupSettingsEntry($settings[IManager::KEY_ADMIN_SETTINGS], 'admin'); + if (!empty($settings[IManager::KEY_ADMIN_SETTINGS])) { + foreach ($settings[IManager::KEY_ADMIN_SETTINGS] as $className) { + $this->setupSettingsEntry($className, 'admin'); + } } - if (isset($settings[IManager::KEY_PERSONAL_SECTION])) { - $this->setupSectionEntry($settings[IManager::KEY_PERSONAL_SECTION], 'personal'); + if (!empty($settings[IManager::KEY_PERSONAL_SECTION])) { + foreach ($settings[IManager::KEY_PERSONAL_SECTION] as $className) { + $this->setupSectionEntry($className, 'personal'); + } } - if (isset($settings[IManager::KEY_PERSONAL_SETTINGS])) { - $this->setupSettingsEntry($settings[IManager::KEY_PERSONAL_SETTINGS], 'personal'); + if (!empty($settings[IManager::KEY_PERSONAL_SETTINGS])) { + foreach ($settings[IManager::KEY_PERSONAL_SETTINGS] as $className) { + $this->setupSettingsEntry($className, 'personal'); + } } } @@ -153,18 +161,26 @@ class Manager implements IManager { public function onAppDisabled($appId) { $appInfo = \OC_App::getAppInfo($appId); // hello static legacy - if (isset($appInfo['settings'][IManager::KEY_ADMIN_SECTION])) { - $this->mapper->remove(Mapper::TABLE_ADMIN_SECTIONS, trim($appInfo['settings'][IManager::KEY_ADMIN_SECTION], '\\')); + if (!empty($appInfo['settings'][IManager::KEY_ADMIN_SECTION])) { + foreach ($appInfo['settings'][IManager::KEY_ADMIN_SECTION] as $className) { + $this->mapper->remove(Mapper::TABLE_ADMIN_SECTIONS, trim($className, '\\')); + } } - if (isset($appInfo['settings'][IManager::KEY_ADMIN_SETTINGS])) { - $this->mapper->remove(Mapper::TABLE_ADMIN_SETTINGS, trim($appInfo['settings'][IManager::KEY_ADMIN_SETTINGS], '\\')); + if (!empty($appInfo['settings'][IManager::KEY_ADMIN_SETTINGS])) { + foreach ($appInfo['settings'][IManager::KEY_ADMIN_SETTINGS] as $className) { + $this->mapper->remove(Mapper::TABLE_ADMIN_SETTINGS, trim($className, '\\')); + } } - if (isset($appInfo['settings'][IManager::KEY_PERSONAL_SECTION])) { - $this->mapper->remove(Mapper::TABLE_PERSONAL_SECTIONS, trim($appInfo['settings'][IManager::KEY_PERSONAL_SECTION], '\\')); + if (!empty($appInfo['settings'][IManager::KEY_PERSONAL_SECTION])) { + foreach ($appInfo['settings'][IManager::KEY_PERSONAL_SECTION] as $className) { + $this->mapper->remove(Mapper::TABLE_PERSONAL_SECTIONS, trim($className, '\\')); + } } - if (isset($appInfo['settings'][IManager::KEY_PERSONAL_SETTINGS])) { - $this->mapper->remove(Mapper::TABLE_PERSONAL_SETTINGS, trim($appInfo['settings'][IManager::KEY_PERSONAL_SETTINGS], '\\')); + if (!empty($appInfo['settings'][IManager::KEY_PERSONAL_SETTINGS])) { + foreach ($appInfo['settings'][IManager::KEY_PERSONAL_SETTINGS] as $className) { + $this->mapper->remove(Mapper::TABLE_PERSONAL_SETTINGS, trim($className, '\\')); + } } } diff --git a/lib/private/Settings/Personal/PersonalInfo.php b/lib/private/Settings/Personal/PersonalInfo.php index e92541c0010..389257cf892 100644 --- a/lib/private/Settings/Personal/PersonalInfo.php +++ b/lib/private/Settings/Personal/PersonalInfo.php @@ -116,7 +116,7 @@ class PersonalInfo implements ISettings { $parameters = [ 'total_space' => $totalSpace, 'usage' => \OC_Helper::humanFileSize($storageInfo['used']), - 'usage_relative' => $storageInfo['relative'], + 'usage_relative' => round($storageInfo['relative']), 'quota' => $storageInfo['quota'], 'avatarChangeSupported' => $user->canChangeAvatar(), 'lookupServerUploadEnabled' => $lookupServerUploadEnabled, diff --git a/lib/private/Setup.php b/lib/private/Setup.php index 521a8f75f8e..5228d52b05f 100644 --- a/lib/private/Setup.php +++ b/lib/private/Setup.php @@ -42,6 +42,8 @@ namespace OC; use bantu\IniGetWrapper\IniGetWrapper; use Exception; use OC\App\AppStore\Bundles\BundleFetcher; +use OC\Authentication\Token\DefaultTokenCleanupJob; +use OC\Authentication\Token\DefaultTokenProvider; use OCP\Defaults; use OCP\IL10N; use OCP\ILogger; @@ -84,7 +86,7 @@ class Setup { $this->random = $random; } - static $dbSetupClasses = [ + static protected $dbSetupClasses = [ 'mysql' => \OC\Setup\MySQL::class, 'pgsql' => \OC\Setup\PostgreSQL::class, 'oci' => \OC\Setup\OCI::class, @@ -127,33 +129,33 @@ class Setup { * @throws Exception */ public function getSupportedDatabases($allowAllDatabases = false) { - $availableDatabases = array( - 'sqlite' => array( + $availableDatabases = [ + 'sqlite' => [ 'type' => 'pdo', 'call' => 'sqlite', - 'name' => 'SQLite' - ), - 'mysql' => array( + 'name' => 'SQLite', + ], + 'mysql' => [ 'type' => 'pdo', 'call' => 'mysql', - 'name' => 'MySQL/MariaDB' - ), - 'pgsql' => array( + 'name' => 'MySQL/MariaDB', + ], + 'pgsql' => [ 'type' => 'pdo', 'call' => 'pgsql', - 'name' => 'PostgreSQL' - ), - 'oci' => array( + 'name' => 'PostgreSQL', + ], + 'oci' => [ 'type' => 'function', 'call' => 'oci_connect', - 'name' => 'Oracle' - ) - ); + 'name' => 'Oracle', + ], + ]; if ($allowAllDatabases) { $configuredDatabases = array_keys($availableDatabases); } else { $configuredDatabases = $this->config->getValue('supportedDatabases', - array('sqlite', 'mysql', 'pgsql')); + ['sqlite', 'mysql', 'pgsql']); } if(!is_array($configuredDatabases)) { throw new Exception('Supported databases are not properly configured.'); @@ -170,7 +172,7 @@ class Setup { if ($type === 'function') { $working = $this->is_callable($call); } elseif($type === 'pdo') { - $working = in_array($call, $this->getAvailableDbDriversForPdo(), TRUE); + $working = in_array($call, $this->getAvailableDbDriversForPdo(), true); } if($working) { $supportedDatabases[$database] = $availableDatabases[$database]['name']; @@ -193,7 +195,7 @@ class Setup { $dataDir = $this->config->getValue('datadirectory', \OC::$SERVERROOT.'/data'); - $errors = array(); + $errors = []; // Create data directory to test whether the .htaccess works // Notice that this is not necessarily the same data directory as the one @@ -204,40 +206,40 @@ class Setup { $htAccessWorking = true; if (is_dir($dataDir) && is_writable($dataDir)) { // Protect data directory here, so we can test if the protection is working - \OC\Setup::protectDataDirectory(); + self::protectDataDirectory(); try { $util = new \OC_Util(); $htAccessWorking = $util->isHtaccessWorking(\OC::$server->getConfig()); } catch (\OC\HintException $e) { - $errors[] = array( + $errors[] = [ 'error' => $e->getMessage(), - 'hint' => $e->getHint() - ); + 'hint' => $e->getHint(), + ]; $htAccessWorking = false; } } if (\OC_Util::runningOnMac()) { - $errors[] = array( + $errors[] = [ 'error' => $this->l10n->t( 'Mac OS X is not supported and %s will not work properly on this platform. ' . 'Use it at your own risk! ', [$this->defaults->getName()] ), - 'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.') - ); + 'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.'), + ]; } if($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) { - $errors[] = array( + $errors[] = [ 'error' => $this->l10n->t( 'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' . 'This will lead to problems with files over 4 GB and is highly discouraged.', [$this->defaults->getName()] ), - 'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.') - ); + 'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.'), + ]; } return array( @@ -286,14 +288,15 @@ class Setup { $error = array_merge($error, $dbSetup->validate($options)); // validate the data directory - if ( - (!is_dir($dataDir) and !mkdir($dataDir)) or - !is_writable($dataDir) - ) { + if ((!is_dir($dataDir) && !mkdir($dataDir)) || !is_writable($dataDir)) { $error[] = $l->t("Can't create or write into the data directory %s", array($dataDir)); } - if(count($error) != 0) { + if (!$this->validateDatabaseHost($options['dbhost'])) { + $error[] = $l->t('Given database host is invalid and must not contain the port: %s', [$options['dbhost']]); + } + + if (!empty($error)) { return $error; } @@ -308,8 +311,8 @@ class Setup { } //use sqlite3 when available, otherwise sqlite2 will be used. - if($dbType=='sqlite' and class_exists('SQLite3')) { - $dbType='sqlite3'; + if ($dbType === 'sqlite' && class_exists('SQLite3')) { + $dbType = 'sqlite3'; } //generate a random salt that is used to salt the local user passwords @@ -334,17 +337,17 @@ class Setup { // apply necessary migrations $dbSetup->runMigrations(); } catch (\OC\DatabaseSetupException $e) { - $error[] = array( + $error[] = [ 'error' => $e->getMessage(), - 'hint' => $e->getHint() - ); - return($error); + 'hint' => $e->getHint(), + ]; + return $error; } catch (Exception $e) { - $error[] = array( + $error[] = [ 'error' => 'Error while trying to create admin user: ' . $e->getMessage(), - 'hint' => '' - ); - return($error); + 'hint' => '', + ]; + return $error; } //create the user and group @@ -358,7 +361,7 @@ class Setup { $error[] = $exception->getMessage(); } - if(count($error) == 0) { + if (empty($error)) { $config = \OC::$server->getConfig(); $config->setAppValue('core', 'installedat', microtime(true)); $config->setAppValue('core', 'lastupdatedat', microtime(true)); @@ -389,8 +392,8 @@ class Setup { file_put_contents($config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data').'/.ocdata', ''); // Update .htaccess files - Setup::updateHtaccess(); - Setup::protectDataDirectory(); + self::updateHtaccess(); + self::protectDataDirectory(); self::installBackgroundJobs(); @@ -401,7 +404,7 @@ class Setup { // The token provider requires a working db, so it's not injected on setup /* @var $userSession User\Session */ $userSession = \OC::$server->getUserSession(); - $defaultTokenProvider = \OC::$server->query('OC\Authentication\Token\DefaultTokenProvider'); + $defaultTokenProvider = \OC::$server->query(DefaultTokenProvider::class); $userSession->setTokenProvider($defaultTokenProvider); $userSession->login($username, $password); $userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password); @@ -410,8 +413,20 @@ class Setup { return $error; } + /** + * @param string $host + * @return bool + */ + protected function validateDatabaseHost($host) { + if (strpos($host, ':') === false) { + return true; + } + + return filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false; + } + public static function installBackgroundJobs() { - \OC::$server->getJobList()->add('\OC\Authentication\Token\DefaultTokenCleanupJob'); + \OC::$server->getJobList()->add(DefaultTokenCleanupJob::class); } /** diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index b4c4c7292fd..b2e192b8309 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -745,7 +745,7 @@ class Manager implements IManager { $initiatorEmail = $initiatorUser->getEMailAddress(); if($initiatorEmail !== null) { $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]); - $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan()); + $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')); } else { $emailTemplate->addFooter(); } diff --git a/lib/private/Template/CSSResourceLocator.php b/lib/private/Template/CSSResourceLocator.php index c8a8c04ab47..1028f31a5ea 100644 --- a/lib/private/Template/CSSResourceLocator.php +++ b/lib/private/Template/CSSResourceLocator.php @@ -119,7 +119,7 @@ class CSSResourceLocator extends ResourceLocator { if (!$webRoot) { $webRoot = $this->findWebRoot($root); - if (!$webRoot) { + if ($webRoot === null) { $webRoot = ''; $this->logger->error('ResourceLocator can not find a web root (root: {root}, file: {file}, webRoot: {webRoot}, throw: {throw})', [ 'app' => 'lib', diff --git a/lib/private/Template/ResourceLocator.php b/lib/private/Template/ResourceLocator.php index 2127161f28c..468fe7e60a6 100755 --- a/lib/private/Template/ResourceLocator.php +++ b/lib/private/Template/ResourceLocator.php @@ -139,7 +139,7 @@ abstract class ResourceLocator { $tmpRoot = dirname($tmpRoot); } - if (!$webRoot) { + if ($webRoot === null) { $realpath = realpath($root); if ($realpath && ($realpath !== $root)) { @@ -171,7 +171,7 @@ abstract class ResourceLocator { if (!$webRoot) { $webRoot = $this->findWebRoot($root); - if (!$webRoot) { + if ($webRoot === null) { $webRoot = ''; $this->logger->error('ResourceLocator can not find a web root (root: {root}, file: {file}, webRoot: {webRoot}, throw: {throw})', [ 'app' => 'lib', diff --git a/lib/private/Template/SCSSCacher.php b/lib/private/Template/SCSSCacher.php index 8ecbb9588a3..664e4d69f73 100644 --- a/lib/private/Template/SCSSCacher.php +++ b/lib/private/Template/SCSSCacher.php @@ -183,6 +183,8 @@ class SCSSCacher { $path, \OC::$SERVERROOT . '/core/css/', ]); + // Continue after throw + $scss->setIgnoreErrors(true); if($this->config->getSystemValue('debug')) { // Debug mode $scss->setFormatter(Expanded::class); diff --git a/lib/private/legacy/api.php b/lib/private/legacy/api.php index f65275bf1da..7fe84b73c43 100644 --- a/lib/private/legacy/api.php +++ b/lib/private/legacy/api.php @@ -129,7 +129,7 @@ class OC_API { if(!self::isAuthorised($action)) { $responses[] = array( 'app' => $action['app'], - 'response' => new OC_OCS_Result(null, API::RESPOND_UNAUTHORISED, 'Unauthorised'), + 'response' => new \OC\OCS\Result(null, API::RESPOND_UNAUTHORISED, 'Unauthorised'), 'shipped' => $appManager->isShipped($action['app']), ); continue; @@ -137,7 +137,7 @@ class OC_API { if(!is_callable($action['action'])) { $responses[] = array( 'app' => $action['app'], - 'response' => new OC_OCS_Result(null, API::RESPOND_NOT_FOUND, 'Api method not found'), + 'response' => new \OC\OCS\Result(null, API::RESPOND_NOT_FOUND, 'Api method not found'), 'shipped' => $appManager->isShipped($action['app']), ); continue; @@ -161,7 +161,7 @@ class OC_API { /** * merge the returned result objects into one response * @param array $responses - * @return OC_OCS_Result + * @return \OC\OCS\Result */ public static function mergeResponses($responses) { // Sort into shipped and third-party @@ -205,7 +205,7 @@ class OC_API { $code = $picked['response']->getStatusCode(); $meta = $picked['response']->getMeta(); $headers = $picked['response']->getHeaders(); - $response = new OC_OCS_Result($data, $code, $meta['message'], $headers); + $response = new \OC\OCS\Result($data, $code, $meta['message'], $headers); return $response; } elseif(!empty($shipped['succeeded'])) { $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']); @@ -219,7 +219,7 @@ class OC_API { $code = $picked['response']->getStatusCode(); $meta = $picked['response']->getMeta(); $headers = $picked['response']->getHeaders(); - $response = new OC_OCS_Result($data, $code, $meta['message'], $headers); + $response = new \OC\OCS\Result($data, $code, $meta['message'], $headers); return $response; } else { $responses = $thirdparty['succeeded']; @@ -251,7 +251,7 @@ class OC_API { } } - return new OC_OCS_Result($data, $statusCode, $statusMessage, $header); + return new \OC\OCS\Result($data, $statusCode, $statusMessage, $header); } /** @@ -351,7 +351,7 @@ class OC_API { /** * respond to a call - * @param OC_OCS_Result $result + * @param \OC\OCS\Result $result * @param string $format the format xml|json */ public static function respond($result, $format='xml') { diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php index 24c7a344e00..627107a63a8 100644 --- a/lib/private/legacy/app.php +++ b/lib/private/legacy/app.php @@ -174,6 +174,20 @@ class OC_App { \OC::$server->getActivityManager()->registerProvider($provider); } } + if (!empty($info['collaboration']['plugins'])) { + // deal with one or many plugin entries + $plugins = isset($info['collaboration']['plugins']['plugin']['@value']) ? + [$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin']; + foreach ($plugins as $plugin) { + if($plugin['@attributes']['type'] === 'collaborator-search') { + $pluginInfo = [ + 'shareType' => $plugin['@attributes']['share-type'], + 'class' => $plugin['@value'], + ]; + \OC::$server->getCollaboratorSearch()->registerPlugin($pluginInfo); + } + } + } } /** @@ -754,6 +768,8 @@ class OC_App { } } + $apps = array_unique($apps); + return $apps; } diff --git a/lib/private/legacy/ocs/result.php b/lib/private/legacy/ocs/result.php deleted file mode 100644 index fd90e56c602..00000000000 --- a/lib/private/legacy/ocs/result.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @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/> - * - */ - -/** - * @deprecated Since 9.1.0 use \OC\OCS\Result - */ -class OC_OCS_Result extends \OC\OCS\Result { -} diff --git a/lib/public/AppFramework/Http/OCSResponse.php b/lib/public/AppFramework/Http/OCSResponse.php index 8614e76805f..ee1207f1217 100644 --- a/lib/public/AppFramework/Http/OCSResponse.php +++ b/lib/public/AppFramework/Http/OCSResponse.php @@ -83,7 +83,7 @@ class OCSResponse extends Response { * @suppress PhanDeprecatedClass */ public function render() { - $r = new \OC_OCS_Result($this->data, $this->statuscode, $this->message); + $r = new \OC\OCS\Result($this->data, $this->statuscode, $this->message); $r->setTotalItems($this->itemscount); $r->setItemsPerPage($this->itemsperpage); diff --git a/lib/public/Collaboration/Collaborators/ISearch.php b/lib/public/Collaboration/Collaborators/ISearch.php new file mode 100644 index 00000000000..281893908ee --- /dev/null +++ b/lib/public/Collaboration/Collaborators/ISearch.php @@ -0,0 +1,50 @@ +<?php +/** + * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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 OCP\Collaboration\Collaborators; + +/** + * Interface ISearch + * + * @package OCP\Collaboration\Collaborators + * @since 13.0.0 + */ +interface ISearch { + /** + * @param string $search + * @param array $shareTypes + * @param bool $lookup + * @param int $limit + * @param int $offset + * @return array with two elements, 1st ISearchResult as array, 2nd a bool indicating whether more result are available + * @since 13.0.0 + */ + public function search($search, array $shareTypes, $lookup, $limit, $offset); + + /** + * @param array $pluginInfo with keys 'shareType' containing the name of a corresponding constant in \OCP\Share and + * 'class' with the class name of the plugin + * @since 13.0.0 + */ + public function registerPlugin(array $pluginInfo); +} diff --git a/lib/public/Collaboration/Collaborators/ISearchPlugin.php b/lib/public/Collaboration/Collaborators/ISearchPlugin.php new file mode 100644 index 00000000000..bc6fa53799b --- /dev/null +++ b/lib/public/Collaboration/Collaborators/ISearchPlugin.php @@ -0,0 +1,42 @@ +<?php +/** + * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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 OCP\Collaboration\Collaborators; + +/** + * Interface ISearchPlugin + * + * @package OCP\Collaboration\Collaborators + * @since 13.0.0 + */ +interface ISearchPlugin { + /** + * @param string $search + * @param int $limit + * @param int $offset + * @param ISearchResult $searchResult + * @return bool whether the plugin has more results + * @since 13.0.0 + */ + public function search($search, $limit, $offset, ISearchResult $searchResult); +} diff --git a/lib/public/Collaboration/Collaborators/ISearchResult.php b/lib/public/Collaboration/Collaborators/ISearchResult.php new file mode 100644 index 00000000000..abea5df8598 --- /dev/null +++ b/lib/public/Collaboration/Collaborators/ISearchResult.php @@ -0,0 +1,73 @@ +<?php +/** + * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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 OCP\Collaboration\Collaborators; + +/** + * Interface ISearchResult + * + * @package OCP\Collaboration\Collaborators + * @since 13.0.0 + */ +interface ISearchResult { + /** + * @param SearchResultType $type + * @param array $matches + * @param array|null $exactMatches + * @since 13.0.0 + */ + public function addResultSet(SearchResultType $type, array $matches, array $exactMatches = null); + + /** + * @param SearchResultType $type + * @param string $collaboratorId + * @return bool + * @since 13.0.0 + */ + public function hasResult(SearchResultType $type, $collaboratorId); + + /** + * @param SearchResultType $type + * @since 13.0.0 + */ + public function unsetResult(SearchResultType $type); + + /** + * @param SearchResultType $type + * @since 13.0.0 + */ + public function markExactIdMatch(SearchResultType $type); + + /** + * @param SearchResultType $type + * @return bool + * @since 13.0.0 + */ + public function hasExactIdMatch(SearchResultType $type); + + /** + * @return array + * @since 13.0.0 + */ + public function asArray(); +} diff --git a/lib/public/Collaboration/Collaborators/SearchResultType.php b/lib/public/Collaboration/Collaborators/SearchResultType.php new file mode 100644 index 00000000000..e4ad888d6e4 --- /dev/null +++ b/lib/public/Collaboration/Collaborators/SearchResultType.php @@ -0,0 +1,73 @@ +<?php +/** + * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @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 OCP\Collaboration\Collaborators; + +/** + * Class SearchResultType + * + * @package OCP\Collaboration\Collaborators + * @since 13.0.0 + */ +class SearchResultType { + /** @var string */ + protected $label; + + /** + * SearchResultType constructor. + * + * @param string $label + * @since 13.0.0 + */ + public function __construct($label) { + $this->label = $this->getValidatedType($label); + } + + /** + * @return string + * @since 13.0.0 + */ + public function getLabel() { + return $this->label; + } + + /** + * @param $type + * @return string + * @throws \InvalidArgumentException + * @since 13.0.0 + */ + protected function getValidatedType($type) { + $type = trim(strval($type)); + + if($type === '') { + throw new \InvalidArgumentException('Type must not be empty'); + } + + if($type === 'exact') { + throw new \InvalidArgumentException('Provided type is a reserved word'); + } + + return $type; + } +} diff --git a/lib/public/ICacheFactory.php b/lib/public/ICacheFactory.php index 717fbc5e627..cc4d8fa3ec3 100644 --- a/lib/public/ICacheFactory.php +++ b/lib/public/ICacheFactory.php @@ -31,13 +31,14 @@ namespace OCP; */ interface ICacheFactory{ /** - * Get a memory cache instance + * Get a distributed memory cache instance * * All entries added trough the cache instance will be namespaced by $prefix to prevent collisions between apps * * @param string $prefix * @return \OCP\ICache * @since 7.0.0 + * @deprecated 13.0.0 Use either createLocking, createDistributed or createLocal */ public function create($prefix = ''); @@ -48,4 +49,31 @@ interface ICacheFactory{ * @since 7.0.0 */ public function isAvailable(); + + /** + * create a cache instance for storing locks + * + * @param string $prefix + * @return \OCP\IMemcache + * @since 13.0.0 + */ + public function createLocking($prefix = ''); + + /** + * create a distributed cache instance + * + * @param string $prefix + * @return \OCP\ICache + * @since 13.0.0 + */ + public function createDistributed($prefix = ''); + + /** + * create a local cache instance + * + * @param string $prefix + * @return \OCP\ICache + * @since 13.0.0 + */ + public function createLocal($prefix = ''); } diff --git a/lib/public/Migration/BigIntMigration.php b/lib/public/Migration/BigIntMigration.php new file mode 100644 index 00000000000..91722671860 --- /dev/null +++ b/lib/public/Migration/BigIntMigration.php @@ -0,0 +1,66 @@ +<?php +/** + * @copyright Copyright (c) 2017 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 OCP\Migration; + +use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Types\Type; + +/** + * @since 13.0.0 + */ +abstract class BigIntMigration extends SimpleMigrationStep { + + /** + * @return array Returns an array with the following structure + * ['table1' => ['column1', 'column2'], ...] + * @since 13.0.0 + */ + abstract protected function getColumnsByTable(); + + /** + * @param IOutput $output + * @param \Closure $schemaClosure The `\Closure` returns a `Schema` + * @param array $options + * @return null|Schema + * @since 13.0.0 + */ + public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { + /** @var Schema $schema */ + $schema = $schemaClosure(); + + $tables = $this->getColumnsByTable(); + + foreach ($tables as $tableName => $columns) { + $table = $schema->getTable($tableName); + + foreach ($columns as $columnName) { + $column = $table->getColumn($columnName); + if ($column->getType()->getName() !== Type::BIGINT) { + $column->setType(Type::getType(Type::BIGINT)); + $column->setOptions(['length' => 20]); + } + } + } + + return $schema; + } +} |