summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/autoloader.php18
-rw-r--r--lib/base.php74
-rw-r--r--lib/composer/composer/autoload_classmap.php118
-rw-r--r--lib/composer/composer/autoload_static.php118
-rw-r--r--lib/l10n/ar.js142
-rw-r--r--lib/l10n/ar.json140
-rw-r--r--lib/l10n/ast.js177
-rw-r--r--lib/l10n/ast.json175
-rw-r--r--lib/l10n/az.js32
-rw-r--r--lib/l10n/az.json30
-rw-r--r--lib/l10n/bg.js149
-rw-r--r--lib/l10n/bg.json147
-rw-r--r--lib/l10n/bn_BD.js26
-rw-r--r--lib/l10n/bn_BD.json24
-rw-r--r--lib/l10n/bs.js16
-rw-r--r--lib/l10n/bs.json14
-rw-r--r--lib/l10n/ca.js193
-rw-r--r--lib/l10n/ca.json191
-rw-r--r--lib/l10n/cs.js48
-rw-r--r--lib/l10n/cs.json48
-rw-r--r--lib/l10n/cy_GB.js23
-rw-r--r--lib/l10n/cy_GB.json21
-rw-r--r--lib/l10n/da.js111
-rw-r--r--lib/l10n/da.json109
-rw-r--r--lib/l10n/de.js27
-rw-r--r--lib/l10n/de.json27
-rw-r--r--lib/l10n/de_DE.js27
-rw-r--r--lib/l10n/de_DE.json27
-rw-r--r--lib/l10n/el.js22
-rw-r--r--lib/l10n/el.json22
-rw-r--r--lib/l10n/en_GB.js33
-rw-r--r--lib/l10n/en_GB.json33
-rw-r--r--lib/l10n/eo.js141
-rw-r--r--lib/l10n/eo.json139
-rw-r--r--lib/l10n/es.js65
-rw-r--r--lib/l10n/es.json65
-rw-r--r--lib/l10n/es_419.js12
-rw-r--r--lib/l10n/es_419.json12
-rw-r--r--lib/l10n/es_AR.js10
-rw-r--r--lib/l10n/es_AR.json10
-rw-r--r--lib/l10n/es_CL.js34
-rw-r--r--lib/l10n/es_CL.json34
-rw-r--r--lib/l10n/es_CO.js34
-rw-r--r--lib/l10n/es_CO.json34
-rw-r--r--lib/l10n/es_CR.js34
-rw-r--r--lib/l10n/es_CR.json34
-rw-r--r--lib/l10n/es_DO.js34
-rw-r--r--lib/l10n/es_DO.json34
-rw-r--r--lib/l10n/es_EC.js34
-rw-r--r--lib/l10n/es_EC.json34
-rw-r--r--lib/l10n/es_GT.js34
-rw-r--r--lib/l10n/es_GT.json34
-rw-r--r--lib/l10n/es_HN.js12
-rw-r--r--lib/l10n/es_HN.json12
-rw-r--r--lib/l10n/es_MX.js35
-rw-r--r--lib/l10n/es_MX.json35
-rw-r--r--lib/l10n/es_NI.js12
-rw-r--r--lib/l10n/es_NI.json12
-rw-r--r--lib/l10n/es_PA.js12
-rw-r--r--lib/l10n/es_PA.json12
-rw-r--r--lib/l10n/es_PE.js12
-rw-r--r--lib/l10n/es_PE.json12
-rw-r--r--lib/l10n/es_PR.js12
-rw-r--r--lib/l10n/es_PR.json12
-rw-r--r--lib/l10n/es_PY.js12
-rw-r--r--lib/l10n/es_PY.json12
-rw-r--r--lib/l10n/es_SV.js34
-rw-r--r--lib/l10n/es_SV.json34
-rw-r--r--lib/l10n/es_UY.js12
-rw-r--r--lib/l10n/es_UY.json12
-rw-r--r--lib/l10n/et_EE.js8
-rw-r--r--lib/l10n/et_EE.json8
-rw-r--r--lib/l10n/eu.js154
-rw-r--r--lib/l10n/eu.json152
-rw-r--r--lib/l10n/fa.js58
-rw-r--r--lib/l10n/fa.json56
-rw-r--r--lib/l10n/fi.js30
-rw-r--r--lib/l10n/fi.json30
-rw-r--r--lib/l10n/fr.js23
-rw-r--r--lib/l10n/fr.json23
-rw-r--r--lib/l10n/gl.js7
-rw-r--r--lib/l10n/gl.json5
-rw-r--r--lib/l10n/he.js254
-rw-r--r--lib/l10n/he.json252
-rw-r--r--lib/l10n/hr.js82
-rw-r--r--lib/l10n/hr.json80
-rw-r--r--lib/l10n/hu.js31
-rw-r--r--lib/l10n/hu.json31
-rw-r--r--lib/l10n/hy.js9
-rw-r--r--lib/l10n/hy.json7
-rw-r--r--lib/l10n/id.js130
-rw-r--r--lib/l10n/id.json128
-rw-r--r--lib/l10n/is.js12
-rw-r--r--lib/l10n/is.json12
-rw-r--r--lib/l10n/it.js27
-rw-r--r--lib/l10n/it.json27
-rw-r--r--lib/l10n/ja.js60
-rw-r--r--lib/l10n/ja.json60
-rw-r--r--lib/l10n/ka_GE.js39
-rw-r--r--lib/l10n/ka_GE.json39
-rw-r--r--lib/l10n/km.js31
-rw-r--r--lib/l10n/km.json29
-rw-r--r--lib/l10n/kn.js13
-rw-r--r--lib/l10n/kn.json11
-rw-r--r--lib/l10n/ko.js12
-rw-r--r--lib/l10n/ko.json12
-rw-r--r--lib/l10n/lb.js29
-rw-r--r--lib/l10n/lb.json27
-rw-r--r--lib/l10n/lt_LT.js34
-rw-r--r--lib/l10n/lt_LT.json34
-rw-r--r--lib/l10n/lv.js129
-rw-r--r--lib/l10n/lv.json127
-rw-r--r--lib/l10n/mk.js32
-rw-r--r--lib/l10n/mk.json30
-rw-r--r--lib/l10n/mn.js20
-rw-r--r--lib/l10n/mn.json18
-rw-r--r--lib/l10n/ms_MY.js9
-rw-r--r--lib/l10n/ms_MY.json7
-rw-r--r--lib/l10n/nb.js32
-rw-r--r--lib/l10n/nb.json32
-rw-r--r--lib/l10n/nl.js31
-rw-r--r--lib/l10n/nl.json31
-rw-r--r--lib/l10n/nn_NO.js19
-rw-r--r--lib/l10n/nn_NO.json17
-rw-r--r--lib/l10n/pl.js17
-rw-r--r--lib/l10n/pl.json17
-rw-r--r--lib/l10n/pt_BR.js27
-rw-r--r--lib/l10n/pt_BR.json27
-rw-r--r--lib/l10n/pt_PT.js246
-rw-r--r--lib/l10n/pt_PT.json244
-rw-r--r--lib/l10n/ro.js144
-rw-r--r--lib/l10n/ro.json142
-rw-r--r--lib/l10n/ru.js59
-rw-r--r--lib/l10n/ru.json59
-rw-r--r--lib/l10n/si_LK.js16
-rw-r--r--lib/l10n/si_LK.json14
-rw-r--r--lib/l10n/sk.js55
-rw-r--r--lib/l10n/sk.json55
-rw-r--r--lib/l10n/sl.js135
-rw-r--r--lib/l10n/sl.json133
-rw-r--r--lib/l10n/sq.js12
-rw-r--r--lib/l10n/sq.json12
-rw-r--r--lib/l10n/sr.js27
-rw-r--r--lib/l10n/sr.json27
-rw-r--r--lib/l10n/sv.js12
-rw-r--r--lib/l10n/sv.json12
-rw-r--r--lib/l10n/ta_LK.js17
-rw-r--r--lib/l10n/ta_LK.json15
-rw-r--r--lib/l10n/th.js119
-rw-r--r--lib/l10n/th.json117
-rw-r--r--lib/l10n/tr.js35
-rw-r--r--lib/l10n/tr.json35
-rw-r--r--lib/l10n/ug.js13
-rw-r--r--lib/l10n/ug.json11
-rw-r--r--lib/l10n/uk.js118
-rw-r--r--lib/l10n/uk.json116
-rw-r--r--lib/l10n/ur_PK.js15
-rw-r--r--lib/l10n/ur_PK.json13
-rw-r--r--lib/l10n/uz.js7
-rw-r--r--lib/l10n/uz.json5
-rw-r--r--lib/l10n/vi.js25
-rw-r--r--lib/l10n/vi.json23
-rw-r--r--lib/l10n/zh_CN.js19
-rw-r--r--lib/l10n/zh_CN.json19
-rw-r--r--lib/l10n/zh_HK.js16
-rw-r--r--lib/l10n/zh_HK.json14
-rw-r--r--lib/l10n/zh_TW.js34
-rw-r--r--lib/l10n/zh_TW.json34
-rw-r--r--lib/private/AllConfig.php4
-rw-r--r--lib/private/App/AppManager.php29
-rw-r--r--lib/private/App/AppStore/Fetcher/AppFetcher.php38
-rw-r--r--lib/private/App/AppStore/Fetcher/Fetcher.php5
-rw-r--r--lib/private/App/CodeChecker/DeprecationCheck.php11
-rw-r--r--lib/private/App/CodeChecker/InfoChecker.php149
-rw-r--r--lib/private/App/CompareVersion.php97
-rw-r--r--lib/private/App/DependencyAnalyzer.php10
-rw-r--r--lib/private/App/Platform.php2
-rw-r--r--lib/private/AppConfig.php8
-rw-r--r--lib/private/AppFramework/App.php7
-rw-r--r--lib/private/AppFramework/DependencyInjection/DIContainer.php31
-rw-r--r--lib/private/AppFramework/Http/Dispatcher.php25
-rw-r--r--lib/private/AppFramework/Http/Request.php124
-rw-r--r--lib/private/AppFramework/Middleware/MiddlewareDispatcher.php21
-rw-r--r--lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php7
-rw-r--r--lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php112
-rw-r--r--lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php1
-rw-r--r--lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php3
-rw-r--r--lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php1
-rw-r--r--lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php54
-rw-r--r--lib/private/AppFramework/OCS/BaseResponse.php58
-rw-r--r--lib/private/AppFramework/Utility/ControllerMethodReflector.php54
-rw-r--r--lib/private/AppFramework/Utility/SimpleContainer.php7
-rw-r--r--lib/private/AppHelper.php48
-rw-r--r--lib/private/Archive/TAR.php8
-rw-r--r--lib/private/Archive/ZIP.php5
-rw-r--r--lib/private/Authentication/Exceptions/ExpiredTokenException.php41
-rw-r--r--lib/private/Authentication/Token/DefaultToken.php123
-rw-r--r--lib/private/Authentication/Token/DefaultTokenMapper.php50
-rw-r--r--lib/private/Authentication/Token/DefaultTokenProvider.php98
-rw-r--r--lib/private/Authentication/Token/IProvider.php46
-rw-r--r--lib/private/Authentication/Token/IToken.php51
-rw-r--r--lib/private/Authentication/Token/Manager.php230
-rw-r--r--lib/private/Authentication/Token/PublicKeyToken.php217
-rw-r--r--lib/private/Authentication/Token/PublicKeyTokenMapper.php172
-rw-r--r--lib/private/Authentication/Token/PublicKeyTokenProvider.php320
-rw-r--r--lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php86
-rw-r--r--lib/private/Authentication/TwoFactorAuth/Manager.php163
-rw-r--r--lib/private/Authentication/TwoFactorAuth/ProviderLoader.php89
-rw-r--r--lib/private/Authentication/TwoFactorAuth/ProviderSet.php72
-rw-r--r--lib/private/Authentication/TwoFactorAuth/Registry.php55
-rw-r--r--lib/private/Avatar.php314
-rw-r--r--lib/private/BackgroundJob/JobList.php50
-rw-r--r--lib/private/Cache/File.php5
-rw-r--r--lib/private/Calendar/Resource/Manager.php83
-rw-r--r--lib/private/Calendar/Room/Manager.php83
-rw-r--r--lib/private/CapabilitiesManager.php2
-rw-r--r--lib/private/Collaboration/Collaborators/GroupPlugin.php2
-rw-r--r--lib/private/Collaboration/Collaborators/MailPlugin.php48
-rw-r--r--lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php78
-rw-r--r--lib/private/Collaboration/Collaborators/RemotePlugin.php2
-rw-r--r--lib/private/Collaboration/Collaborators/UserPlugin.php2
-rw-r--r--lib/private/Color.php33
-rw-r--r--lib/private/Comments/Comment.php2
-rw-r--r--lib/private/Comments/Manager.php117
-rw-r--r--lib/private/Config.php2
-rw-r--r--lib/private/Console/Application.php35
-rw-r--r--lib/private/Contacts/ContactsMenu/ContactsStore.php13
-rw-r--r--lib/private/DB/Connection.php4
-rw-r--r--lib/private/DB/ConnectionFactory.php34
-rw-r--r--lib/private/DB/MigrationService.php29
-rw-r--r--lib/private/DB/MissingIndexInformation.php39
-rw-r--r--lib/private/DB/MySqlTools.php27
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php28
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php6
-rw-r--r--lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php4
-rw-r--r--lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php16
-rw-r--r--lib/private/DB/QueryBuilder/QueryBuilder.php78
-rw-r--r--lib/private/DB/ReconnectWrapper.php52
-rw-r--r--lib/private/DB/SchemaWrapper.php1
-rw-r--r--lib/private/DateTimeZone.php5
-rw-r--r--lib/private/Encryption/Manager.php9
-rw-r--r--lib/private/Encryption/Util.php8
-rw-r--r--lib/private/Federation/CloudFederationFactory.php63
-rw-r--r--lib/private/Federation/CloudFederationNotification.php67
-rw-r--r--lib/private/Federation/CloudFederationProviderManager.php243
-rw-r--r--lib/private/Federation/CloudFederationShare.php356
-rw-r--r--lib/private/Files/AppData/AppData.php16
-rw-r--r--lib/private/Files/AppData/Factory.php3
-rw-r--r--lib/private/Files/Cache/Scanner.php26
-rw-r--r--lib/private/Files/Cache/Wrapper/CacheJail.php11
-rw-r--r--lib/private/Files/Config/MountProviderCollection.php23
-rw-r--r--lib/private/Files/Config/UserMountCache.php3
-rw-r--r--lib/private/Files/Filesystem.php7
-rw-r--r--lib/private/Files/Mount/Manager.php71
-rw-r--r--lib/private/Files/Mount/MountPoint.php5
-rw-r--r--lib/private/Files/Mount/ObjectHomeMountProvider.php8
-rw-r--r--lib/private/Files/Node/File.php8
-rw-r--r--lib/private/Files/Node/Folder.php23
-rw-r--r--lib/private/Files/Node/HookConnector.php7
-rw-r--r--lib/private/Files/Node/Node.php6
-rw-r--r--lib/private/Files/ObjectStore/Azure.php118
-rw-r--r--lib/private/Files/ObjectStore/ObjectStoreStorage.php26
-rw-r--r--lib/private/Files/ObjectStore/S3ConnectionTrait.php16
-rw-r--r--lib/private/Files/ObjectStore/S3ObjectTrait.php48
-rw-r--r--lib/private/Files/ObjectStore/Swift.php239
-rw-r--r--lib/private/Files/ObjectStore/SwiftFactory.php216
-rw-r--r--lib/private/Files/SimpleFS/SimpleFile.php61
-rw-r--r--lib/private/Files/Storage/Common.php8
-rw-r--r--lib/private/Files/Storage/DAV.php11
-rw-r--r--lib/private/Files/Storage/Flysystem.php2
-rw-r--r--lib/private/Files/Storage/Local.php9
-rw-r--r--lib/private/Files/Storage/Wrapper/Encryption.php29
-rw-r--r--lib/private/Files/Storage/Wrapper/Quota.php23
-rw-r--r--lib/private/Files/Stream/Encryption.php6
-rw-r--r--lib/private/Files/Utils/Scanner.php13
-rw-r--r--lib/private/Files/View.php19
-rw-r--r--lib/private/Group/Database.php152
-rw-r--r--lib/private/Group/Group.php53
-rw-r--r--lib/private/Group/Manager.php13
-rw-r--r--lib/private/Group/MetaData.php18
-rw-r--r--lib/private/HTTPHelper.php120
-rw-r--r--lib/private/Http/Client/Client.php63
-rw-r--r--lib/private/Http/Client/ClientService.php3
-rw-r--r--lib/private/Http/Client/Response.php10
-rw-r--r--lib/private/Installer.php38
-rw-r--r--lib/private/IntegrityCheck/Checker.php47
-rw-r--r--lib/private/IntegrityCheck/Helpers/AppLocator.php5
-rw-r--r--lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php5
-rw-r--r--lib/private/IntegrityCheck/Helpers/FileAccessHelper.php13
-rw-r--r--lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php3
-rw-r--r--lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php5
-rw-r--r--lib/private/L10N/Factory.php188
-rw-r--r--lib/private/L10N/L10N.php86
-rw-r--r--lib/private/L10N/LanguageIterator.php137
-rwxr-xr-x[-rw-r--r--]lib/private/LargeFileHelper.php20
-rw-r--r--lib/private/Lock/DBLockingProvider.php44
-rw-r--r--lib/private/Lock/MemcacheLockingProvider.php29
-rw-r--r--lib/private/Log.php240
-rw-r--r--lib/private/Log/Errorlog.php11
-rw-r--r--lib/private/Log/ExceptionSerializer.php145
-rw-r--r--lib/private/Log/File.php73
-rw-r--r--lib/private/Log/LogFactory.php81
-rw-r--r--lib/private/Log/Rotate.php25
-rw-r--r--lib/private/Log/Syslog.php37
-rw-r--r--lib/private/Log/Systemdlog.php78
-rw-r--r--lib/private/Mail/Attachment.php9
-rw-r--r--lib/private/Mail/EMailTemplate.php77
-rw-r--r--lib/private/Mail/Mailer.php77
-rw-r--r--lib/private/Mail/Message.php67
-rw-r--r--lib/private/Memcache/Factory.php4
-rw-r--r--lib/private/NaturalSort.php4
-rw-r--r--lib/private/NavigationManager.php57
-rw-r--r--lib/private/OCS/DiscoveryService.php15
-rw-r--r--lib/private/Preview/BackgroundCleanupJob.php91
-rw-r--r--lib/private/Preview/Bitmap.php5
-rw-r--r--lib/private/Preview/Generator.php6
-rw-r--r--lib/private/Preview/Office.php22
-rw-r--r--lib/private/Preview/SVG.php4
-rw-r--r--lib/private/Preview/Watcher.php48
-rw-r--r--lib/private/Preview/WatcherConnector.php11
-rw-r--r--lib/private/Repair.php12
-rw-r--r--lib/private/Repair/AddCleanupUpdaterBackupsJob.php48
-rw-r--r--lib/private/Repair/Collation.php5
-rw-r--r--lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php48
-rw-r--r--lib/private/Repair/NC14/RepairPendingCronJobs.php77
-rw-r--r--lib/private/Repair/RepairMimeTypes.php34
-rw-r--r--lib/private/Security/Bruteforce/Throttler.php2
-rw-r--r--lib/private/Security/CSP/ContentSecurityPolicy.php47
-rw-r--r--lib/private/Security/CSP/ContentSecurityPolicyManager.php11
-rw-r--r--lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php5
-rw-r--r--lib/private/Security/CSRF/CsrfToken.php11
-rw-r--r--lib/private/Security/CSRF/CsrfTokenGenerator.php3
-rw-r--r--lib/private/Security/CSRF/CsrfTokenManager.php9
-rw-r--r--lib/private/Security/CSRF/TokenStorage/SessionStorage.php7
-rw-r--r--lib/private/Security/Hasher.php45
-rw-r--r--lib/private/Security/IdentityProof/Key.php7
-rw-r--r--lib/private/Security/IdentityProof/Manager.php11
-rw-r--r--lib/private/Security/IdentityProof/Signer.php5
-rw-r--r--lib/private/Server.php163
-rw-r--r--lib/private/Session/CryptoSessionData.php20
-rw-r--r--lib/private/Session/Internal.php52
-rw-r--r--lib/private/Session/Memory.php19
-rw-r--r--lib/private/Session/Session.php5
-rw-r--r--lib/private/Settings/Admin/Mail.php (renamed from lib/private/Settings/Admin/Additional.php)10
-rw-r--r--lib/private/Settings/Admin/Overview.php (renamed from lib/private/Settings/Admin/TipsTricks.php)22
-rw-r--r--lib/private/Settings/Admin/Server.php56
-rw-r--r--lib/private/Settings/Admin/Sharing.php70
-rw-r--r--lib/private/Settings/Manager.php38
-rw-r--r--lib/private/Settings/Personal/PersonalInfo.php104
-rw-r--r--lib/private/Settings/Personal/Security.php19
-rw-r--r--lib/private/Settings/Personal/ServerDevNotice.php (renamed from lib/private/Settings/Admin/ServerDevNotice.php)8
-rw-r--r--lib/private/Setup.php15
-rw-r--r--lib/private/Setup/MySQL.php9
-rw-r--r--lib/private/Share/Constants.php1
-rw-r--r--lib/private/Share/Share.php123
-rw-r--r--lib/private/Share20/DefaultShareProvider.php38
-rw-r--r--lib/private/Share20/Manager.php40
-rw-r--r--lib/private/Share20/ProviderFactory.php11
-rw-r--r--lib/private/Share20/Share.php40
-rw-r--r--lib/private/Streamer.php43
-rw-r--r--lib/private/SubAdmin.php19
-rw-r--r--lib/private/SystemTag/ManagerFactory.php5
-rw-r--r--lib/private/SystemTag/SystemTag.php11
-rw-r--r--lib/private/SystemTag/SystemTagManager.php63
-rw-r--r--lib/private/SystemTag/SystemTagObjectMapper.php31
-rw-r--r--lib/private/Tags.php104
-rw-r--r--lib/private/Template/Base.php5
-rw-r--r--lib/private/Template/IconsCacher.php147
-rw-r--r--lib/private/Template/JSCombiner.php22
-rw-r--r--lib/private/Template/JSConfigHelper.php12
-rw-r--r--lib/private/Template/SCSSCacher.php151
-rw-r--r--lib/private/TemplateLayout.php29
-rw-r--r--lib/private/URLGenerator.php6
-rw-r--r--lib/private/Updater.php42
-rw-r--r--lib/private/Updater/ChangesCheck.php166
-rw-r--r--lib/private/Updater/ChangesMapper.php57
-rw-r--r--lib/private/Updater/ChangesResult.php61
-rw-r--r--lib/private/Updater/VersionCheck.php2
-rw-r--r--lib/private/User/Database.php245
-rw-r--r--lib/private/User/Manager.php77
-rw-r--r--lib/private/User/Session.php6
-rw-r--r--lib/private/User/User.php5
-rw-r--r--lib/private/legacy/api.php281
-rw-r--r--lib/private/legacy/app.php255
-rw-r--r--lib/private/legacy/db.php4
-rw-r--r--lib/private/legacy/defaults.php9
-rw-r--r--lib/private/legacy/eventsource.php4
-rw-r--r--lib/private/legacy/files.php67
-rw-r--r--lib/private/legacy/group/backend.php56
-rw-r--r--lib/private/legacy/json.php45
-rw-r--r--lib/private/legacy/response.php165
-rw-r--r--lib/private/legacy/template.php65
-rw-r--r--lib/private/legacy/template/functions.php2
-rw-r--r--lib/private/legacy/user.php31
-rw-r--r--lib/private/legacy/util.php60
-rw-r--r--lib/public/App/IAppManager.php9
-rw-r--r--lib/public/AppFramework/App.php16
-rw-r--r--lib/public/AppFramework/AuthPublicShareController.php192
-rw-r--r--lib/public/AppFramework/Db/Mapper.php15
-rw-r--r--lib/public/AppFramework/Db/QBMapper.php272
-rw-r--r--lib/public/AppFramework/Http/ContentSecurityPolicy.php7
-rw-r--r--lib/public/AppFramework/Http/Response.php20
-rw-r--r--lib/public/AppFramework/Http/StrictContentSecurityPolicy.php85
-rw-r--r--lib/public/AppFramework/Http/StrictEvalContentSecurityPolicy.php51
-rw-r--r--lib/public/AppFramework/Http/StrictInlineContentSecurityPolicy.php51
-rw-r--r--lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php77
-rw-r--r--lib/public/AppFramework/Http/Template/IMenuAction.php64
-rw-r--r--lib/public/AppFramework/Http/Template/LinkMenuAction.php66
-rw-r--r--lib/public/AppFramework/Http/Template/PublicTemplateResponse.php158
-rw-r--r--lib/public/AppFramework/Http/Template/SimpleMenuAction.php126
-rw-r--r--lib/public/AppFramework/Http/TemplateResponse.php2
-rw-r--r--lib/public/AppFramework/PublicShareController.php138
-rw-r--r--lib/public/AppFramework/Utility/IControllerMethodReflector.php9
-rw-r--r--lib/public/Authentication/TwoFactorAuth/IProvider.php16
-rw-r--r--lib/public/Authentication/TwoFactorAuth/IProvidesCustomCSP.php3
-rw-r--r--lib/public/Authentication/TwoFactorAuth/IRegistry.php65
-rw-r--r--lib/public/Authentication/TwoFactorAuth/TwoFactorException.php1
-rw-r--r--lib/public/BackgroundJob.php7
-rw-r--r--lib/public/Calendar/BackendTemporarilyUnavailableException.php32
-rw-r--r--lib/public/Calendar/Resource/IBackend.php70
-rw-r--r--lib/public/Calendar/Resource/IManager.php71
-rw-r--r--lib/public/Calendar/Resource/IResource.php80
-rw-r--r--lib/public/Calendar/Room/IBackend.php70
-rw-r--r--lib/public/Calendar/Room/IManager.php71
-rw-r--r--lib/public/Calendar/Room/IRoom.php80
-rw-r--r--lib/public/Comments/ICommentsManager.php18
-rw-r--r--lib/public/Contacts.php185
-rw-r--r--lib/public/DB.php147
-rw-r--r--lib/public/DB/QueryBuilder/IExpressionBuilder.php8
-rw-r--r--lib/public/DB/QueryBuilder/IFunctionBuilder.php33
-rw-r--r--lib/public/DB/QueryBuilder/IQueryBuilder.php38
-rw-r--r--lib/public/Federation/Exceptions/ActionNotSupportedException.php48
-rw-r--r--lib/public/Federation/Exceptions/AuthenticationFailedException.php48
-rw-r--r--lib/public/Federation/Exceptions/BadRequestException.php77
-rw-r--r--lib/public/Federation/Exceptions/ProviderAlreadyExistsException.php50
-rw-r--r--lib/public/Federation/Exceptions/ProviderCouldNotAddShareException.php51
-rw-r--r--lib/public/Federation/Exceptions/ProviderDoesNotExistsException.php49
-rw-r--r--lib/public/Federation/ICloudFederationFactory.php62
-rw-r--r--lib/public/Federation/ICloudFederationNotification.php53
-rw-r--r--lib/public/Federation/ICloudFederationProvider.php89
-rw-r--r--lib/public/Federation/ICloudFederationProviderManager.php107
-rw-r--r--lib/public/Federation/ICloudFederationShare.php250
-rw-r--r--lib/public/Files.php32
-rw-r--r--lib/public/Files/Config/IMountProviderCollection.php8
-rw-r--r--lib/public/Files/File.php4
-rw-r--r--lib/public/Files/Folder.php3
-rw-r--r--lib/public/Files/GenericFileException.php33
-rw-r--r--lib/public/Files/Mount/IMountManager.php17
-rw-r--r--lib/public/Files/SimpleFS/ISimpleFile.php23
-rw-r--r--lib/public/Files/SimpleFS/ISimpleRoot.php6
-rw-r--r--lib/public/Group/Backend/ABackend.php67
-rw-r--r--lib/public/Group/Backend/IAddToGroupBackend.php36
-rw-r--r--lib/public/Group/Backend/ICountDisabledInGroup.php36
-rw-r--r--lib/public/Group/Backend/ICountUsersBackend.php36
-rw-r--r--lib/public/Group/Backend/ICreateGroupBackend.php36
-rw-r--r--lib/public/Group/Backend/IDeleteGroupBackend.php36
-rw-r--r--lib/public/Group/Backend/IGroupDetailsBackend.php36
-rw-r--r--lib/public/Group/Backend/IIsAdminBackend.php36
-rw-r--r--lib/public/Group/Backend/IRemoveFromGroupBackend.php36
-rw-r--r--lib/public/IAvatar.php9
-rw-r--r--lib/public/ICacheFactory.php8
-rw-r--r--lib/public/IDBConnection.php4
-rw-r--r--lib/public/IGroup.php20
-rw-r--r--lib/public/IHelper.php50
-rw-r--r--lib/public/IL10N.php20
-rw-r--r--lib/public/ILogger.php44
-rw-r--r--lib/public/INavigationManager.php9
-rw-r--r--lib/public/IRequest.php51
-rw-r--r--lib/public/IServerContainer.php65
-rw-r--r--lib/public/ISession.php18
-rw-r--r--lib/public/IUser.php2
-rw-r--r--lib/public/IUserManager.php3
-rw-r--r--lib/public/JSON.php209
-rw-r--r--lib/public/L10N/IFactory.php47
-rw-r--r--lib/public/L10N/ILanguageIterator.php74
-rw-r--r--lib/public/Lock/LockedException.php10
-rw-r--r--lib/public/Log/IFileBased.php43
-rw-r--r--lib/public/Log/ILogFactory.php49
-rw-r--r--lib/public/Log/IWriter.php37
-rw-r--r--lib/public/Log/RotationTrait.php71
-rw-r--r--lib/public/Mail/IAttachment.php13
-rw-r--r--lib/public/Mail/IEMailTemplate.php37
-rw-r--r--lib/public/Mail/IMailer.php13
-rw-r--r--lib/public/Mail/IMessage.php29
-rw-r--r--lib/public/Migration/IMigrationStep.php15
-rw-r--r--lib/public/Migration/SimpleMigrationStep.php19
-rw-r--r--lib/public/OCS/IDiscoveryService.php3
-rw-r--r--lib/public/Response.php137
-rw-r--r--lib/public/Share.php10
-rw-r--r--lib/public/Share/IManager.php37
-rw-r--r--lib/public/Share/IShare.php34
-rw-r--r--lib/public/Share/IShareProvider.php15
-rw-r--r--lib/public/SystemTag/ISystemTag.php9
-rw-r--r--lib/public/SystemTag/ISystemTagManager.php39
-rw-r--r--lib/public/SystemTag/ISystemTagManagerFactory.php5
-rw-r--r--lib/public/SystemTag/ISystemTagObjectMapper.php19
-rw-r--r--lib/public/SystemTag/ManagerEvent.php10
-rw-r--r--lib/public/SystemTag/MapperEvent.php11
-rw-r--r--lib/public/SystemTag/SystemTagsEntityEvent.php7
-rw-r--r--lib/public/SystemTag/TagAlreadyExistsException.php1
-rw-r--r--lib/public/SystemTag/TagNotFoundException.php5
-rw-r--r--lib/public/User.php51
-rw-r--r--lib/public/User/Backend/ABackend.php72
-rw-r--r--lib/public/User/Backend/ICheckPasswordBackend.php39
-rw-r--r--lib/public/User/Backend/ICountUsersBackend.php38
-rw-r--r--lib/public/User/Backend/ICreateUserBackend.php40
-rw-r--r--lib/public/User/Backend/IGetDisplayNameBackend.php39
-rw-r--r--lib/public/User/Backend/IGetHomeBackend.php39
-rw-r--r--lib/public/User/Backend/IProvideAvatarBackend.php39
-rw-r--r--lib/public/User/Backend/ISetDisplayNameBackend.php40
-rw-r--r--lib/public/User/Backend/ISetPasswordBackend.php40
-rw-r--r--lib/public/UserInterface.php1
-rw-r--r--lib/public/Util.php161
513 files changed, 20302 insertions, 5343 deletions
diff --git a/lib/autoloader.php b/lib/autoloader.php
index efab84b44f9..4377a84f307 100644
--- a/lib/autoloader.php
+++ b/lib/autoloader.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -33,6 +34,7 @@
namespace OC;
use \OCP\AutoloadNotAllowedException;
+use OCP\ILogger;
class Autoloader {
/** @var bool */
@@ -63,7 +65,7 @@ class Autoloader {
*
* @param string $root
*/
- public function addValidRoot($root) {
+ public function addValidRoot(string $root) {
$root = stream_resolve_include_path($root);
$this->validRoots[$root] = true;
}
@@ -86,12 +88,12 @@ class Autoloader {
* get the possible paths for a class
*
* @param string $class
- * @return array|bool an array of possible paths or false if the class is not part of ownCloud
+ * @return array an array of possible paths
*/
- public function findClass($class) {
+ public function findClass(string $class): array {
$class = trim($class, '\\');
- $paths = array();
+ $paths = [];
if ($this->useGlobalClassPath && array_key_exists($class, \OC::$CLASSPATH)) {
$paths[] = \OC::$CLASSPATH[$class];
/**
@@ -99,7 +101,7 @@ class Autoloader {
* Remove "apps/" from inclusion path for smooth migration to multi app dir
*/
if (strpos(\OC::$CLASSPATH[$class], 'apps/') === 0) {
- \OCP\Util::writeLog('core', 'include path for class "' . $class . '" starts with "apps/"', \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', 'include path for class "' . $class . '" starts with "apps/"', ILogger::DEBUG);
$paths[] = str_replace('apps/', '', \OC::$CLASSPATH[$class]);
}
} elseif (strpos($class, 'OC_') === 0) {
@@ -124,8 +126,9 @@ class Autoloader {
/**
* @param string $fullPath
* @return bool
+ * @throws AutoloadNotAllowedException
*/
- protected function isValidPath($fullPath) {
+ protected function isValidPath(string $fullPath): bool {
foreach ($this->validRoots as $root => $true) {
if (substr($fullPath, 0, strlen($root) + 1) === $root . '/') {
return true;
@@ -139,8 +142,9 @@ class Autoloader {
*
* @param string $class
* @return bool
+ * @throws AutoloadNotAllowedException
*/
- public function load($class) {
+ public function load(string $class): bool {
$pathsToRequire = null;
if ($this->memoryCache) {
$pathsToRequire = $this->memoryCache->get($class);
diff --git a/lib/base.php b/lib/base.php
index 05da2814d4c..628756cd217 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -54,6 +54,7 @@
*
*/
+use OCP\ILogger;
use OCP\Share;
use OC\Encryption\HookManager;
use OC\Files\Filesystem;
@@ -248,14 +249,19 @@ class OC {
if (self::$CLI) {
echo $l->t('Cannot write into "config" directory!')."\n";
echo $l->t('This can usually be fixed by giving the webserver write access to the config directory')."\n";
- echo "\n";
echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-dir_permissions') ])."\n";
+ echo "\n";
+ echo $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it.')."\n";
+ echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-config') ])."\n";
exit;
} else {
OC_Template::printErrorPage(
$l->t('Cannot write into "config" directory!'),
$l->t('This can usually be fixed by giving the webserver write access to the config directory. See %s',
- [ $urlGenerator->linkToDocs('admin-dir_permissions') ])
+ [ $urlGenerator->linkToDocs('admin-dir_permissions') ]) . '. '
+ . $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it. See %s',
+ [ $urlGenerator->linkToDocs('admin-config') ] ),
+ 503
);
}
}
@@ -281,8 +287,7 @@ class OC {
// Allow ajax update script to execute without being stopped
if (\OC::$server->getSystemConfig()->getValue('maintenance', false) && OC::$SUBURI != '/core/ajax/update.php') {
// send http status 503
- header('HTTP/1.1 503 Service Temporarily Unavailable');
- header('Status: 503 Service Temporarily Unavailable');
+ http_response_code(503);
header('Retry-After: 120');
// render error page
@@ -338,8 +343,7 @@ class OC {
if ($disableWebUpdater || ($tooBig && !$ignoreTooBigWarning)) {
// send http status 503
- header('HTTP/1.1 503 Service Temporarily Unavailable');
- header('Status: 503 Service Temporarily Unavailable');
+ http_response_code(503);
header('Retry-After: 120');
// render error page
@@ -373,6 +377,7 @@ class OC {
// get third party apps
$ocVersion = \OCP\Util::getVersion();
+ $ocVersion = implode('.', $ocVersion);
$incompatibleApps = $appManager->getIncompatibleApps($ocVersion);
$incompatibleShippedApps = [];
foreach ($incompatibleApps as $appInfo) {
@@ -425,10 +430,9 @@ class OC {
// if session can't be started break with http 500 error
} catch (Exception $e) {
- \OCP\Util::logException('base', $e);
+ \OC::$server->getLogger()->logException($e, ['app' => 'base']);
//show the user a detailed error page
- OC_Response::setStatus(OC_Response::STATUS_INTERNAL_SERVER_ERROR);
- OC_Template::printExceptionErrorPage($e);
+ OC_Template::printExceptionErrorPage($e, 500);
die();
}
@@ -521,10 +525,18 @@ class OC {
// specifications. For those, have an automated opt-out. Since the protection
// for remote.php is applied in base.php as starting point we need to opt out
// here.
- $incompatibleUserAgents = [
- // OS X Finder
- '/^WebDAVFS/',
- ];
+ $incompatibleUserAgents = \OC::$server->getConfig()->getSystemValue('csrf.optout');
+
+ // Fallback, if csrf.optout is unset
+ if (!is_array($incompatibleUserAgents)) {
+ $incompatibleUserAgents = [
+ // OS X Finder
+ '/^WebDAVFS/',
+ // Windows webdav drive
+ '/^Microsoft-WebDAV-MiniRedir/',
+ ];
+ }
+
if($request->isUserAgent($incompatibleUserAgents)) {
return;
}
@@ -586,9 +598,7 @@ class OC {
} catch (\RuntimeException $e) {
if (!self::$CLI) {
- $claimedProtocol = strtoupper($_SERVER['SERVER_PROTOCOL']);
- $protocol = in_array($claimedProtocol, ['HTTP/1.0', 'HTTP/1.1', 'HTTP/2']) ? $claimedProtocol : 'HTTP/1.1';
- header($protocol . ' ' . OC_Response::STATUS_SERVICE_UNAVAILABLE);
+ http_response_code(503);
}
// we can't use the template error page here, because this needs the
// DI container which isn't available yet
@@ -675,7 +685,7 @@ class OC {
}
exit(1);
} else {
- OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
+ http_response_code(503);
OC_Util::addStyle('guest');
OC_Template::printGuestPage('', 'error', array('errors' => $errors));
exit;
@@ -736,11 +746,10 @@ class OC {
// Check whether the sample configuration has been copied
if($systemConfig->getValue('copied_sample_config', false)) {
$l = \OC::$server->getL10N('lib');
- header('HTTP/1.1 503 Service Temporarily Unavailable');
- header('Status: 503 Service Temporarily Unavailable');
OC_Template::printErrorPage(
$l->t('Sample configuration detected'),
- $l->t('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')
+ $l->t('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'),
+ 503
);
return;
}
@@ -765,18 +774,16 @@ class OC {
}
if(substr($request->getRequestUri(), -11) === '/status.php') {
- OC_Response::setStatus(\OC_Response::STATUS_BAD_REQUEST);
- header('Status: 400 Bad Request');
+ http_response_code(400);
header('Content-Type: application/json');
echo '{"error": "Trusted domain error.", "code": 15}';
exit();
}
if (!$isScssRequest) {
- OC_Response::setStatus(\OC_Response::STATUS_BAD_REQUEST);
- header('Status: 400 Bad Request');
+ http_response_code(400);
- \OC::$server->getLogger()->warning(
+ \OC::$server->getLogger()->info(
'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
[
'app' => 'core',
@@ -786,7 +793,7 @@ class OC {
);
$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
- $tmpl->assign('domain', $host);
+ $tmpl->assign('docUrl', \OC::$server->getURLGenerator()->linkToDocs('admin-trusted-domains'));
$tmpl->printPage();
exit();
@@ -826,7 +833,7 @@ class OC {
// so log the exception
\OC::$server->getLogger()->logException($e, [
'message' => 'Exception when running cache gc.',
- 'level' => \OCP\Util::WARN,
+ 'level' => ILogger::WARN,
'app' => 'core',
]);
}
@@ -888,6 +895,8 @@ class OC {
self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader'));
} catch (\Exception $ex) {
}
+
+ self::$composerAutoloader->setApcuPrefix($instanceId . '-mainComposer');
}
}
@@ -943,12 +952,12 @@ class OC {
&& $request->getMethod() === 'POST'
&& ((array)$request->getParam('appid')) !== ''
) {
- \OCP\JSON::callCheck();
- \OCP\JSON::checkAdminUser();
+ \OC_JSON::callCheck();
+ \OC_JSON::checkAdminUser();
$appIds = (array)$request->getParam('appid');
foreach($appIds as $appId) {
$appId = \OC_App::cleanAppId($appId);
- \OC_App::disable($appId);
+ \OC::$server->getAppManager()->disableApp($appId);
}
\OC_JSON::success();
exit();
@@ -982,7 +991,7 @@ class OC {
} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
//header('HTTP/1.0 404 Not Found');
} catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
- OC_Response::setStatus(405);
+ http_response_code(405);
return;
}
}
@@ -992,8 +1001,7 @@ class OC {
// not allowed any more to prevent people
// mounting this root directly.
// Users need to mount remote.php/webdav instead.
- header('HTTP/1.1 405 Method Not Allowed');
- header('Status: 405 Method Not Allowed');
+ http_response_code(405);
return;
}
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 3eb532be0c6..234aa418f56 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -18,11 +18,13 @@ return array(
'OCP\\App' => $baseDir . '/lib/public/App.php',
'OCP\\AppFramework\\ApiController' => $baseDir . '/lib/public/AppFramework/ApiController.php',
'OCP\\AppFramework\\App' => $baseDir . '/lib/public/AppFramework/App.php',
+ 'OCP\\AppFramework\\AuthPublicShareController' => $baseDir . '/lib/public/AppFramework/AuthPublicShareController.php',
'OCP\\AppFramework\\Controller' => $baseDir . '/lib/public/AppFramework/Controller.php',
'OCP\\AppFramework\\Db\\DoesNotExistException' => $baseDir . '/lib/public/AppFramework/Db/DoesNotExistException.php',
'OCP\\AppFramework\\Db\\Entity' => $baseDir . '/lib/public/AppFramework/Db/Entity.php',
'OCP\\AppFramework\\Db\\Mapper' => $baseDir . '/lib/public/AppFramework/Db/Mapper.php',
'OCP\\AppFramework\\Db\\MultipleObjectsReturnedException' => $baseDir . '/lib/public/AppFramework/Db/MultipleObjectsReturnedException.php',
+ 'OCP\\AppFramework\\Db\\QBMapper' => $baseDir . '/lib/public/AppFramework/Db/QBMapper.php',
'OCP\\AppFramework\\Http' => $baseDir . '/lib/public/AppFramework/Http.php',
'OCP\\AppFramework\\Http\\ContentSecurityPolicy' => $baseDir . '/lib/public/AppFramework/Http/ContentSecurityPolicy.php',
'OCP\\AppFramework\\Http\\DataDisplayResponse' => $baseDir . '/lib/public/AppFramework/Http/DataDisplayResponse.php',
@@ -39,7 +41,15 @@ return array(
'OCP\\AppFramework\\Http\\RedirectResponse' => $baseDir . '/lib/public/AppFramework/Http/RedirectResponse.php',
'OCP\\AppFramework\\Http\\Response' => $baseDir . '/lib/public/AppFramework/Http/Response.php',
'OCP\\AppFramework\\Http\\StreamResponse' => $baseDir . '/lib/public/AppFramework/Http/StreamResponse.php',
+ 'OCP\\AppFramework\\Http\\StrictContentSecurityPolicy' => $baseDir . '/lib/public/AppFramework/Http/StrictContentSecurityPolicy.php',
+ 'OCP\\AppFramework\\Http\\StrictEvalContentSecurityPolicy' => $baseDir . '/lib/public/AppFramework/Http/StrictEvalContentSecurityPolicy.php',
+ 'OCP\\AppFramework\\Http\\StrictInlineContentSecurityPolicy' => $baseDir . '/lib/public/AppFramework/Http/StrictInlineContentSecurityPolicy.php',
'OCP\\AppFramework\\Http\\TemplateResponse' => $baseDir . '/lib/public/AppFramework/Http/TemplateResponse.php',
+ 'OCP\\AppFramework\\Http\\Template\\ExternalShareMenuAction' => $baseDir . '/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php',
+ 'OCP\\AppFramework\\Http\\Template\\IMenuAction' => $baseDir . '/lib/public/AppFramework/Http/Template/IMenuAction.php',
+ 'OCP\\AppFramework\\Http\\Template\\LinkMenuAction' => $baseDir . '/lib/public/AppFramework/Http/Template/LinkMenuAction.php',
+ 'OCP\\AppFramework\\Http\\Template\\PublicTemplateResponse' => $baseDir . '/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php',
+ 'OCP\\AppFramework\\Http\\Template\\SimpleMenuAction' => $baseDir . '/lib/public/AppFramework/Http/Template/SimpleMenuAction.php',
'OCP\\AppFramework\\IAppContainer' => $baseDir . '/lib/public/AppFramework/IAppContainer.php',
'OCP\\AppFramework\\Middleware' => $baseDir . '/lib/public/AppFramework/Middleware.php',
'OCP\\AppFramework\\OCSController' => $baseDir . '/lib/public/AppFramework/OCSController.php',
@@ -47,6 +57,7 @@ return array(
'OCP\\AppFramework\\OCS\\OCSException' => $baseDir . '/lib/public/AppFramework/OCS/OCSException.php',
'OCP\\AppFramework\\OCS\\OCSForbiddenException' => $baseDir . '/lib/public/AppFramework/OCS/OCSForbiddenException.php',
'OCP\\AppFramework\\OCS\\OCSNotFoundException' => $baseDir . '/lib/public/AppFramework/OCS/OCSNotFoundException.php',
+ 'OCP\\AppFramework\\PublicShareController' => $baseDir . '/lib/public/AppFramework/PublicShareController.php',
'OCP\\AppFramework\\QueryException' => $baseDir . '/lib/public/AppFramework/QueryException.php',
'OCP\\AppFramework\\Utility\\IControllerMethodReflector' => $baseDir . '/lib/public/AppFramework/Utility/IControllerMethodReflector.php',
'OCP\\AppFramework\\Utility\\ITimeFactory' => $baseDir . '/lib/public/AppFramework/Utility/ITimeFactory.php',
@@ -60,13 +71,21 @@ return array(
'OCP\\Authentication\\LoginCredentials\\IStore' => $baseDir . '/lib/public/Authentication/LoginCredentials/IStore.php',
'OCP\\Authentication\\TwoFactorAuth\\IProvider' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/IProvider.php',
'OCP\\Authentication\\TwoFactorAuth\\IProvidesCustomCSP' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/IProvidesCustomCSP.php',
+ 'OCP\\Authentication\\TwoFactorAuth\\IRegistry' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/IRegistry.php',
'OCP\\Authentication\\TwoFactorAuth\\TwoFactorException' => $baseDir . '/lib/public/Authentication/TwoFactorAuth/TwoFactorException.php',
'OCP\\AutoloadNotAllowedException' => $baseDir . '/lib/public/AutoloadNotAllowedException.php',
'OCP\\BackgroundJob' => $baseDir . '/lib/public/BackgroundJob.php',
'OCP\\BackgroundJob\\IJob' => $baseDir . '/lib/public/BackgroundJob/IJob.php',
'OCP\\BackgroundJob\\IJobList' => $baseDir . '/lib/public/BackgroundJob/IJobList.php',
+ 'OCP\\Calendar\\BackendTemporarilyUnavailableException' => $baseDir . '/lib/public/Calendar/BackendTemporarilyUnavailableException.php',
'OCP\\Calendar\\ICalendar' => $baseDir . '/lib/public/Calendar/ICalendar.php',
'OCP\\Calendar\\IManager' => $baseDir . '/lib/public/Calendar/IManager.php',
+ 'OCP\\Calendar\\Resource\\IBackend' => $baseDir . '/lib/public/Calendar/Resource/IBackend.php',
+ 'OCP\\Calendar\\Resource\\IManager' => $baseDir . '/lib/public/Calendar/Resource/IManager.php',
+ 'OCP\\Calendar\\Resource\\IResource' => $baseDir . '/lib/public/Calendar/Resource/IResource.php',
+ 'OCP\\Calendar\\Room\\IBackend' => $baseDir . '/lib/public/Calendar/Room/IBackend.php',
+ 'OCP\\Calendar\\Room\\IManager' => $baseDir . '/lib/public/Calendar/Room/IManager.php',
+ 'OCP\\Calendar\\Room\\IRoom' => $baseDir . '/lib/public/Calendar/Room/IRoom.php',
'OCP\\Capabilities\\ICapability' => $baseDir . '/lib/public/Capabilities/ICapability.php',
'OCP\\Capabilities\\IPublicCapability' => $baseDir . '/lib/public/Capabilities/IPublicCapability.php',
'OCP\\Collaboration\\AutoComplete\\IManager' => $baseDir . '/lib/public/Collaboration/AutoComplete/IManager.php',
@@ -88,7 +107,6 @@ return array(
'OCP\\Comments\\NotFoundException' => $baseDir . '/lib/public/Comments/NotFoundException.php',
'OCP\\Console\\ConsoleEvent' => $baseDir . '/lib/public/Console/ConsoleEvent.php',
'OCP\\Constants' => $baseDir . '/lib/public/Constants.php',
- 'OCP\\Contacts' => $baseDir . '/lib/public/Contacts.php',
'OCP\\Contacts\\ContactsMenu\\IAction' => $baseDir . '/lib/public/Contacts/ContactsMenu/IAction.php',
'OCP\\Contacts\\ContactsMenu\\IActionFactory' => $baseDir . '/lib/public/Contacts/ContactsMenu/IActionFactory.php',
'OCP\\Contacts\\ContactsMenu\\IContactsStore' => $baseDir . '/lib/public/Contacts/ContactsMenu/IContactsStore.php',
@@ -96,7 +114,6 @@ return array(
'OCP\\Contacts\\ContactsMenu\\ILinkAction' => $baseDir . '/lib/public/Contacts/ContactsMenu/ILinkAction.php',
'OCP\\Contacts\\ContactsMenu\\IProvider' => $baseDir . '/lib/public/Contacts/ContactsMenu/IProvider.php',
'OCP\\Contacts\\IManager' => $baseDir . '/lib/public/Contacts/IManager.php',
- 'OCP\\DB' => $baseDir . '/lib/public/DB.php',
'OCP\\DB\\ISchemaWrapper' => $baseDir . '/lib/public/DB/ISchemaWrapper.php',
'OCP\\DB\\QueryBuilder\\ICompositeExpression' => $baseDir . '/lib/public/DB/QueryBuilder/ICompositeExpression.php',
'OCP\\DB\\QueryBuilder\\IExpressionBuilder' => $baseDir . '/lib/public/DB/QueryBuilder/IExpressionBuilder.php',
@@ -115,6 +132,17 @@ return array(
'OCP\\Encryption\\IFile' => $baseDir . '/lib/public/Encryption/IFile.php',
'OCP\\Encryption\\IManager' => $baseDir . '/lib/public/Encryption/IManager.php',
'OCP\\Encryption\\Keys\\IStorage' => $baseDir . '/lib/public/Encryption/Keys/IStorage.php',
+ 'OCP\\Federation\\Exceptions\\ActionNotSupportedException' => $baseDir . '/lib/public/Federation/Exceptions/ActionNotSupportedException.php',
+ 'OCP\\Federation\\Exceptions\\AuthenticationFailedException' => $baseDir . '/lib/public/Federation/Exceptions/AuthenticationFailedException.php',
+ 'OCP\\Federation\\Exceptions\\BadRequestException' => $baseDir . '/lib/public/Federation/Exceptions/BadRequestException.php',
+ 'OCP\\Federation\\Exceptions\\ProviderAlreadyExistsException' => $baseDir . '/lib/public/Federation/Exceptions/ProviderAlreadyExistsException.php',
+ 'OCP\\Federation\\Exceptions\\ProviderCouldNotAddShareException' => $baseDir . '/lib/public/Federation/Exceptions/ProviderCouldNotAddShareException.php',
+ 'OCP\\Federation\\Exceptions\\ProviderDoesNotExistsException' => $baseDir . '/lib/public/Federation/Exceptions/ProviderDoesNotExistsException.php',
+ 'OCP\\Federation\\ICloudFederationFactory' => $baseDir . '/lib/public/Federation/ICloudFederationFactory.php',
+ 'OCP\\Federation\\ICloudFederationNotification' => $baseDir . '/lib/public/Federation/ICloudFederationNotification.php',
+ 'OCP\\Federation\\ICloudFederationProvider' => $baseDir . '/lib/public/Federation/ICloudFederationProvider.php',
+ 'OCP\\Federation\\ICloudFederationProviderManager' => $baseDir . '/lib/public/Federation/ICloudFederationProviderManager.php',
+ 'OCP\\Federation\\ICloudFederationShare' => $baseDir . '/lib/public/Federation/ICloudFederationShare.php',
'OCP\\Federation\\ICloudId' => $baseDir . '/lib/public/Federation/ICloudId.php',
'OCP\\Federation\\ICloudIdManager' => $baseDir . '/lib/public/Federation/ICloudIdManager.php',
'OCP\\Files' => $baseDir . '/lib/public/Files.php',
@@ -138,6 +166,7 @@ return array(
'OCP\\Files\\FileNameTooLongException' => $baseDir . '/lib/public/Files/FileNameTooLongException.php',
'OCP\\Files\\Folder' => $baseDir . '/lib/public/Files/Folder.php',
'OCP\\Files\\ForbiddenException' => $baseDir . '/lib/public/Files/ForbiddenException.php',
+ 'OCP\\Files\\GenericFileException' => $baseDir . '/lib/public/Files/GenericFileException.php',
'OCP\\Files\\IAppData' => $baseDir . '/lib/public/Files/IAppData.php',
'OCP\\Files\\IHomeStorage' => $baseDir . '/lib/public/Files/IHomeStorage.php',
'OCP\\Files\\IMimeTypeDetector' => $baseDir . '/lib/public/Files/IMimeTypeDetector.php',
@@ -181,6 +210,15 @@ return array(
'OCP\\Files\\UnseekableException' => $baseDir . '/lib/public/Files/UnseekableException.php',
'OCP\\GlobalScale\\IConfig' => $baseDir . '/lib/public/GlobalScale/IConfig.php',
'OCP\\GroupInterface' => $baseDir . '/lib/public/GroupInterface.php',
+ 'OCP\\Group\\Backend\\ABackend' => $baseDir . '/lib/public/Group/Backend/ABackend.php',
+ 'OCP\\Group\\Backend\\IAddToGroupBackend' => $baseDir . '/lib/public/Group/Backend/IAddToGroupBackend.php',
+ 'OCP\\Group\\Backend\\ICountDisabledInGroup' => $baseDir . '/lib/public/Group/Backend/ICountDisabledInGroup.php',
+ 'OCP\\Group\\Backend\\ICountUsersBackend' => $baseDir . '/lib/public/Group/Backend/ICountUsersBackend.php',
+ 'OCP\\Group\\Backend\\ICreateGroupBackend' => $baseDir . '/lib/public/Group/Backend/ICreateGroupBackend.php',
+ 'OCP\\Group\\Backend\\IDeleteGroupBackend' => $baseDir . '/lib/public/Group/Backend/IDeleteGroupBackend.php',
+ 'OCP\\Group\\Backend\\IGroupDetailsBackend' => $baseDir . '/lib/public/Group/Backend/IGroupDetailsBackend.php',
+ 'OCP\\Group\\Backend\\IIsAdminBackend' => $baseDir . '/lib/public/Group/Backend/IIsAdminBackend.php',
+ 'OCP\\Group\\Backend\\IRemoveFromGroupBackend' => $baseDir . '/lib/public/Group/Backend/IRemoveFromGroupBackend.php',
'OCP\\Http\\Client\\IClient' => $baseDir . '/lib/public/Http/Client/IClient.php',
'OCP\\Http\\Client\\IClientService' => $baseDir . '/lib/public/Http/Client/IClientService.php',
'OCP\\Http\\Client\\IResponse' => $baseDir . '/lib/public/Http/Client/IResponse.php',
@@ -200,7 +238,6 @@ return array(
'OCP\\IEventSource' => $baseDir . '/lib/public/IEventSource.php',
'OCP\\IGroup' => $baseDir . '/lib/public/IGroup.php',
'OCP\\IGroupManager' => $baseDir . '/lib/public/IGroupManager.php',
- 'OCP\\IHelper' => $baseDir . '/lib/public/IHelper.php',
'OCP\\IImage' => $baseDir . '/lib/public/IImage.php',
'OCP\\IL10N' => $baseDir . '/lib/public/IL10N.php',
'OCP\\ILogger' => $baseDir . '/lib/public/ILogger.php',
@@ -221,14 +258,18 @@ return array(
'OCP\\IUserManager' => $baseDir . '/lib/public/IUserManager.php',
'OCP\\IUserSession' => $baseDir . '/lib/public/IUserSession.php',
'OCP\\Image' => $baseDir . '/lib/public/Image.php',
- 'OCP\\JSON' => $baseDir . '/lib/public/JSON.php',
'OCP\\L10N\\IFactory' => $baseDir . '/lib/public/L10N/IFactory.php',
+ 'OCP\\L10N\\ILanguageIterator' => $baseDir . '/lib/public/L10N/ILanguageIterator.php',
'OCP\\LDAP\\IDeletionFlagSupport' => $baseDir . '/lib/public/LDAP/IDeletionFlagSupport.php',
'OCP\\LDAP\\ILDAPProvider' => $baseDir . '/lib/public/LDAP/ILDAPProvider.php',
'OCP\\LDAP\\ILDAPProviderFactory' => $baseDir . '/lib/public/LDAP/ILDAPProviderFactory.php',
'OCP\\Lock\\ILockingProvider' => $baseDir . '/lib/public/Lock/ILockingProvider.php',
'OCP\\Lock\\LockedException' => $baseDir . '/lib/public/Lock/LockedException.php',
'OCP\\Lockdown\\ILockdownManager' => $baseDir . '/lib/public/Lockdown/ILockdownManager.php',
+ 'OCP\\Log\\IFileBased' => $baseDir . '/lib/public/Log/IFileBased.php',
+ 'OCP\\Log\\ILogFactory' => $baseDir . '/lib/public/Log/ILogFactory.php',
+ 'OCP\\Log\\IWriter' => $baseDir . '/lib/public/Log/IWriter.php',
+ 'OCP\\Log\\RotationTrait' => $baseDir . '/lib/public/Log/RotationTrait.php',
'OCP\\Mail\\IAttachment' => $baseDir . '/lib/public/Mail/IAttachment.php',
'OCP\\Mail\\IEMailTemplate' => $baseDir . '/lib/public/Mail/IEMailTemplate.php',
'OCP\\Mail\\IMailer' => $baseDir . '/lib/public/Mail/IMailer.php',
@@ -254,7 +295,6 @@ return array(
'OCP\\Remote\\IInstance' => $baseDir . '/lib/public/Remote/IInstance.php',
'OCP\\Remote\\IInstanceFactory' => $baseDir . '/lib/public/Remote/IInstanceFactory.php',
'OCP\\Remote\\IUser' => $baseDir . '/lib/public/Remote/IUser.php',
- 'OCP\\Response' => $baseDir . '/lib/public/Response.php',
'OCP\\RichObjectStrings\\Definitions' => $baseDir . '/lib/public/RichObjectStrings/Definitions.php',
'OCP\\RichObjectStrings\\IValidator' => $baseDir . '/lib/public/RichObjectStrings/IValidator.php',
'OCP\\RichObjectStrings\\InvalidObjectExeption' => $baseDir . '/lib/public/RichObjectStrings/InvalidObjectExeption.php',
@@ -302,6 +342,15 @@ return array(
'OCP\\Template' => $baseDir . '/lib/public/Template.php',
'OCP\\User' => $baseDir . '/lib/public/User.php',
'OCP\\UserInterface' => $baseDir . '/lib/public/UserInterface.php',
+ 'OCP\\User\\Backend\\ABackend' => $baseDir . '/lib/public/User/Backend/ABackend.php',
+ 'OCP\\User\\Backend\\ICheckPasswordBackend' => $baseDir . '/lib/public/User/Backend/ICheckPasswordBackend.php',
+ 'OCP\\User\\Backend\\ICountUsersBackend' => $baseDir . '/lib/public/User/Backend/ICountUsersBackend.php',
+ 'OCP\\User\\Backend\\ICreateUserBackend' => $baseDir . '/lib/public/User/Backend/ICreateUserBackend.php',
+ 'OCP\\User\\Backend\\IGetDisplayNameBackend' => $baseDir . '/lib/public/User/Backend/IGetDisplayNameBackend.php',
+ 'OCP\\User\\Backend\\IGetHomeBackend' => $baseDir . '/lib/public/User/Backend/IGetHomeBackend.php',
+ 'OCP\\User\\Backend\\IProvideAvatarBackend' => $baseDir . '/lib/public/User/Backend/IProvideAvatarBackend.php',
+ 'OCP\\User\\Backend\\ISetDisplayNameBackend' => $baseDir . '/lib/public/User/Backend/ISetDisplayNameBackend.php',
+ 'OCP\\User\\Backend\\ISetPasswordBackend' => $baseDir . '/lib/public/User/Backend/ISetPasswordBackend.php',
'OCP\\Util' => $baseDir . '/lib/public/Util.php',
'OCP\\WorkflowEngine\\ICheck' => $baseDir . '/lib/public/WorkflowEngine/ICheck.php',
'OCP\\WorkflowEngine\\IManager' => $baseDir . '/lib/public/WorkflowEngine/IManager.php',
@@ -323,6 +372,8 @@ return array(
'OC\\AppFramework\\Http\\Request' => $baseDir . '/lib/private/AppFramework/Http/Request.php',
'OC\\AppFramework\\Middleware\\MiddlewareDispatcher' => $baseDir . '/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php',
'OC\\AppFramework\\Middleware\\OCSMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/OCSMiddleware.php',
+ 'OC\\AppFramework\\Middleware\\PublicShare\\Exceptions\\NeedAuthenticationException' => $baseDir . '/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php',
+ 'OC\\AppFramework\\Middleware\\PublicShare\\PublicShareMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php',
'OC\\AppFramework\\Middleware\\Security\\BruteForceMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php',
'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',
@@ -346,7 +397,6 @@ return array(
'OC\\AppFramework\\Utility\\ControllerMethodReflector' => $baseDir . '/lib/private/AppFramework/Utility/ControllerMethodReflector.php',
'OC\\AppFramework\\Utility\\SimpleContainer' => $baseDir . '/lib/private/AppFramework/Utility/SimpleContainer.php',
'OC\\AppFramework\\Utility\\TimeFactory' => $baseDir . '/lib/private/AppFramework/Utility/TimeFactory.php',
- 'OC\\AppHelper' => $baseDir . '/lib/private/AppHelper.php',
'OC\\App\\AppManager' => $baseDir . '/lib/private/App/AppManager.php',
'OC\\App\\AppStore\\Bundles\\Bundle' => $baseDir . '/lib/private/App/AppStore/Bundles/Bundle.php',
'OC\\App\\AppStore\\Bundles\\BundleFetcher' => $baseDir . '/lib/private/App/AppStore/Bundles/BundleFetcher.php',
@@ -372,6 +422,7 @@ return array(
'OC\\App\\CodeChecker\\NodeVisitor' => $baseDir . '/lib/private/App/CodeChecker/NodeVisitor.php',
'OC\\App\\CodeChecker\\PrivateCheck' => $baseDir . '/lib/private/App/CodeChecker/PrivateCheck.php',
'OC\\App\\CodeChecker\\StrongComparisonCheck' => $baseDir . '/lib/private/App/CodeChecker/StrongComparisonCheck.php',
+ 'OC\\App\\CompareVersion' => $baseDir . '/lib/private/App/CompareVersion.php',
'OC\\App\\DependencyAnalyzer' => $baseDir . '/lib/private/App/DependencyAnalyzer.php',
'OC\\App\\InfoParser' => $baseDir . '/lib/private/App/InfoParser.php',
'OC\\App\\Platform' => $baseDir . '/lib/private/App/Platform.php',
@@ -391,9 +442,18 @@ return array(
'OC\\Authentication\\Token\\DefaultTokenCleanupJob' => $baseDir . '/lib/private/Authentication/Token/DefaultTokenCleanupJob.php',
'OC\\Authentication\\Token\\DefaultTokenMapper' => $baseDir . '/lib/private/Authentication/Token/DefaultTokenMapper.php',
'OC\\Authentication\\Token\\DefaultTokenProvider' => $baseDir . '/lib/private/Authentication/Token/DefaultTokenProvider.php',
+ 'OC\\Authentication\\Token\\ExpiredTokenException' => $baseDir . '/lib/private/Authentication/Exceptions/ExpiredTokenException.php',
'OC\\Authentication\\Token\\IProvider' => $baseDir . '/lib/private/Authentication/Token/IProvider.php',
'OC\\Authentication\\Token\\IToken' => $baseDir . '/lib/private/Authentication/Token/IToken.php',
+ 'OC\\Authentication\\Token\\Manager' => $baseDir . '/lib/private/Authentication/Token/Manager.php',
+ 'OC\\Authentication\\Token\\PublicKeyToken' => $baseDir . '/lib/private/Authentication/Token/PublicKeyToken.php',
+ 'OC\\Authentication\\Token\\PublicKeyTokenMapper' => $baseDir . '/lib/private/Authentication/Token/PublicKeyTokenMapper.php',
+ 'OC\\Authentication\\Token\\PublicKeyTokenProvider' => $baseDir . '/lib/private/Authentication/Token/PublicKeyTokenProvider.php',
+ 'OC\\Authentication\\TwoFactorAuth\\Db\\ProviderUserAssignmentDao' => $baseDir . '/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php',
'OC\\Authentication\\TwoFactorAuth\\Manager' => $baseDir . '/lib/private/Authentication/TwoFactorAuth/Manager.php',
+ 'OC\\Authentication\\TwoFactorAuth\\ProviderLoader' => $baseDir . '/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php',
+ 'OC\\Authentication\\TwoFactorAuth\\ProviderSet' => $baseDir . '/lib/private/Authentication/TwoFactorAuth/ProviderSet.php',
+ 'OC\\Authentication\\TwoFactorAuth\\Registry' => $baseDir . '/lib/private/Authentication/TwoFactorAuth/Registry.php',
'OC\\Avatar' => $baseDir . '/lib/private/Avatar.php',
'OC\\AvatarManager' => $baseDir . '/lib/private/AvatarManager.php',
'OC\\BackgroundJob\\Job' => $baseDir . '/lib/private/BackgroundJob/Job.php',
@@ -405,15 +465,19 @@ return array(
'OC\\Cache\\CappedMemoryCache' => $baseDir . '/lib/private/Cache/CappedMemoryCache.php',
'OC\\Cache\\File' => $baseDir . '/lib/private/Cache/File.php',
'OC\\Calendar\\Manager' => $baseDir . '/lib/private/Calendar/Manager.php',
+ 'OC\\Calendar\\Resource\\Manager' => $baseDir . '/lib/private/Calendar/Resource/Manager.php',
+ 'OC\\Calendar\\Room\\Manager' => $baseDir . '/lib/private/Calendar/Room/Manager.php',
'OC\\CapabilitiesManager' => $baseDir . '/lib/private/CapabilitiesManager.php',
'OC\\Collaboration\\AutoComplete\\Manager' => $baseDir . '/lib/private/Collaboration/AutoComplete/Manager.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\\RemoteGroupPlugin' => $baseDir . '/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.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\\Color' => $baseDir . '/lib/private/Color.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',
@@ -436,6 +500,7 @@ return array(
'OC\\Contacts\\ContactsMenu\\Manager' => $baseDir . '/lib/private/Contacts/ContactsMenu/Manager.php',
'OC\\Contacts\\ContactsMenu\\Providers\\EMailProvider' => $baseDir . '/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php',
'OC\\Core\\Application' => $baseDir . '/core/Application.php',
+ 'OC\\Core\\BackgroundJobs\\BackgroundCleanupUpdaterBackupsJob' => $baseDir . '/core/BackgroundJobs/BackgroundCleanupUpdaterBackupsJob.php',
'OC\\Core\\Command\\App\\CheckCode' => $baseDir . '/core/Command/App/CheckCode.php',
'OC\\Core\\Command\\App\\Disable' => $baseDir . '/core/Command/App/Disable.php',
'OC\\Core\\Command\\App\\Enable' => $baseDir . '/core/Command/App/Enable.php',
@@ -502,6 +567,7 @@ return array(
'OC\\Core\\Command\\TwoFactorAuth\\Base' => $baseDir . '/core/Command/TwoFactorAuth/Base.php',
'OC\\Core\\Command\\TwoFactorAuth\\Disable' => $baseDir . '/core/Command/TwoFactorAuth/Disable.php',
'OC\\Core\\Command\\TwoFactorAuth\\Enable' => $baseDir . '/core/Command/TwoFactorAuth/Enable.php',
+ 'OC\\Core\\Command\\TwoFactorAuth\\State' => $baseDir . '/core/Command/TwoFactorAuth/State.php',
'OC\\Core\\Command\\Upgrade' => $baseDir . '/core/Command/Upgrade.php',
'OC\\Core\\Command\\User\\Add' => $baseDir . '/core/Command/User/Add.php',
'OC\\Core\\Command\\User\\Delete' => $baseDir . '/core/Command/User/Delete.php',
@@ -515,19 +581,24 @@ return array(
'OC\\Core\\Command\\User\\Setting' => $baseDir . '/core/Command/User/Setting.php',
'OC\\Core\\Controller\\AutoCompleteController' => $baseDir . '/core/Controller/AutoCompleteController.php',
'OC\\Core\\Controller\\AvatarController' => $baseDir . '/core/Controller/AvatarController.php',
+ 'OC\\Core\\Controller\\CSRFTokenController' => $baseDir . '/core/Controller/CSRFTokenController.php',
'OC\\Core\\Controller\\ClientFlowLoginController' => $baseDir . '/core/Controller/ClientFlowLoginController.php',
'OC\\Core\\Controller\\ContactsMenuController' => $baseDir . '/core/Controller/ContactsMenuController.php',
'OC\\Core\\Controller\\CssController' => $baseDir . '/core/Controller/CssController.php',
'OC\\Core\\Controller\\JsController' => $baseDir . '/core/Controller/JsController.php',
'OC\\Core\\Controller\\LoginController' => $baseDir . '/core/Controller/LoginController.php',
'OC\\Core\\Controller\\LostController' => $baseDir . '/core/Controller/LostController.php',
+ 'OC\\Core\\Controller\\NavigationController' => $baseDir . '/core/Controller/NavigationController.php',
'OC\\Core\\Controller\\OCJSController' => $baseDir . '/core/Controller/OCJSController.php',
'OC\\Core\\Controller\\OCSController' => $baseDir . '/core/Controller/OCSController.php',
'OC\\Core\\Controller\\PreviewController' => $baseDir . '/core/Controller/PreviewController.php',
+ 'OC\\Core\\Controller\\SearchController' => $baseDir . '/core/Controller/SearchController.php',
'OC\\Core\\Controller\\SetupController' => $baseDir . '/core/Controller/SetupController.php',
+ 'OC\\Core\\Controller\\SvgController' => $baseDir . '/core/Controller/SvgController.php',
'OC\\Core\\Controller\\TwoFactorChallengeController' => $baseDir . '/core/Controller/TwoFactorChallengeController.php',
'OC\\Core\\Controller\\UserController' => $baseDir . '/core/Controller/UserController.php',
'OC\\Core\\Controller\\WalledGardenController' => $baseDir . '/core/Controller/WalledGardenController.php',
+ 'OC\\Core\\Controller\\WhatsNewController' => $baseDir . '/core/Controller/WhatsNewController.php',
'OC\\Core\\Middleware\\TwoFactorMiddleware' => $baseDir . '/core/Middleware/TwoFactorMiddleware.php',
'OC\\Core\\Migrations\\Version13000Date20170705121758' => $baseDir . '/core/Migrations/Version13000Date20170705121758.php',
'OC\\Core\\Migrations\\Version13000Date20170718121200' => $baseDir . '/core/Migrations/Version13000Date20170718121200.php',
@@ -535,6 +606,11 @@ return array(
'OC\\Core\\Migrations\\Version13000Date20170919121250' => $baseDir . '/core/Migrations/Version13000Date20170919121250.php',
'OC\\Core\\Migrations\\Version13000Date20170926101637' => $baseDir . '/core/Migrations/Version13000Date20170926101637.php',
'OC\\Core\\Migrations\\Version14000Date20180129121024' => $baseDir . '/core/Migrations/Version14000Date20180129121024.php',
+ 'OC\\Core\\Migrations\\Version14000Date20180404140050' => $baseDir . '/core/Migrations/Version14000Date20180404140050.php',
+ 'OC\\Core\\Migrations\\Version14000Date20180516101403' => $baseDir . '/core/Migrations/Version14000Date20180516101403.php',
+ 'OC\\Core\\Migrations\\Version14000Date20180518120534' => $baseDir . '/core/Migrations/Version14000Date20180518120534.php',
+ 'OC\\Core\\Migrations\\Version14000Date20180522074438' => $baseDir . '/core/Migrations/Version14000Date20180522074438.php',
+ 'OC\\Core\\Migrations\\Version14000Date20180626223656' => $baseDir . '/core/Migrations/Version14000Date20180626223656.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',
@@ -548,6 +624,7 @@ return array(
'OC\\DB\\MigrationException' => $baseDir . '/lib/private/DB/MigrationException.php',
'OC\\DB\\MigrationService' => $baseDir . '/lib/private/DB/MigrationService.php',
'OC\\DB\\Migrator' => $baseDir . '/lib/private/DB/Migrator.php',
+ 'OC\\DB\\MissingIndexInformation' => $baseDir . '/lib/private/DB/MissingIndexInformation.php',
'OC\\DB\\MySQLMigrator' => $baseDir . '/lib/private/DB/MySQLMigrator.php',
'OC\\DB\\MySqlTools' => $baseDir . '/lib/private/DB/MySqlTools.php',
'OC\\DB\\OCSqlitePlatform' => $baseDir . '/lib/private/DB/OCSqlitePlatform.php',
@@ -570,6 +647,7 @@ return array(
'OC\\DB\\QueryBuilder\\QueryBuilder' => $baseDir . '/lib/private/DB/QueryBuilder/QueryBuilder.php',
'OC\\DB\\QueryBuilder\\QueryFunction' => $baseDir . '/lib/private/DB/QueryBuilder/QueryFunction.php',
'OC\\DB\\QueryBuilder\\QuoteHelper' => $baseDir . '/lib/private/DB/QueryBuilder/QuoteHelper.php',
+ 'OC\\DB\\ReconnectWrapper' => $baseDir . '/lib/private/DB/ReconnectWrapper.php',
'OC\\DB\\SQLiteMigrator' => $baseDir . '/lib/private/DB/SQLiteMigrator.php',
'OC\\DB\\SQLiteSessionInit' => $baseDir . '/lib/private/DB/SQLiteSessionInit.php',
'OC\\DB\\SchemaWrapper' => $baseDir . '/lib/private/DB/SchemaWrapper.php',
@@ -597,6 +675,10 @@ return array(
'OC\\Encryption\\Manager' => $baseDir . '/lib/private/Encryption/Manager.php',
'OC\\Encryption\\Update' => $baseDir . '/lib/private/Encryption/Update.php',
'OC\\Encryption\\Util' => $baseDir . '/lib/private/Encryption/Util.php',
+ 'OC\\Federation\\CloudFederationFactory' => $baseDir . '/lib/private/Federation/CloudFederationFactory.php',
+ 'OC\\Federation\\CloudFederationNotification' => $baseDir . '/lib/private/Federation/CloudFederationNotification.php',
+ 'OC\\Federation\\CloudFederationProviderManager' => $baseDir . '/lib/private/Federation/CloudFederationProviderManager.php',
+ 'OC\\Federation\\CloudFederationShare' => $baseDir . '/lib/private/Federation/CloudFederationShare.php',
'OC\\Federation\\CloudId' => $baseDir . '/lib/private/Federation/CloudId.php',
'OC\\Federation\\CloudIdManager' => $baseDir . '/lib/private/Federation/CloudIdManager.php',
'OC\\Files\\AppData\\AppData' => $baseDir . '/lib/private/Files/AppData/AppData.php',
@@ -642,6 +724,7 @@ return array(
'OC\\Files\\Node\\Root' => $baseDir . '/lib/private/Files/Node/Root.php',
'OC\\Files\\Notify\\Change' => $baseDir . '/lib/private/Files/Notify/Change.php',
'OC\\Files\\Notify\\RenameChange' => $baseDir . '/lib/private/Files/Notify/RenameChange.php',
+ 'OC\\Files\\ObjectStore\\Azure' => $baseDir . '/lib/private/Files/ObjectStore/Azure.php',
'OC\\Files\\ObjectStore\\HomeObjectStoreStorage' => $baseDir . '/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php',
'OC\\Files\\ObjectStore\\Mapper' => $baseDir . '/lib/private/Files/ObjectStore/Mapper.php',
'OC\\Files\\ObjectStore\\NoopScanner' => $baseDir . '/lib/private/Files/ObjectStore/NoopScanner.php',
@@ -652,6 +735,7 @@ return array(
'OC\\Files\\ObjectStore\\S3Signature' => $baseDir . '/lib/private/Files/ObjectStore/S3Signature.php',
'OC\\Files\\ObjectStore\\StorageObjectStore' => $baseDir . '/lib/private/Files/ObjectStore/StorageObjectStore.php',
'OC\\Files\\ObjectStore\\Swift' => $baseDir . '/lib/private/Files/ObjectStore/Swift.php',
+ 'OC\\Files\\ObjectStore\\SwiftFactory' => $baseDir . '/lib/private/Files/ObjectStore/SwiftFactory.php',
'OC\\Files\\Search\\SearchBinaryOperator' => $baseDir . '/lib/private/Files/Search/SearchBinaryOperator.php',
'OC\\Files\\Search\\SearchComparison' => $baseDir . '/lib/private/Files/Search/SearchComparison.php',
'OC\\Files\\Search\\SearchOrder' => $baseDir . '/lib/private/Files/Search/SearchOrder.php',
@@ -691,7 +775,6 @@ return array(
'OC\\Group\\Group' => $baseDir . '/lib/private/Group/Group.php',
'OC\\Group\\Manager' => $baseDir . '/lib/private/Group/Manager.php',
'OC\\Group\\MetaData' => $baseDir . '/lib/private/Group/MetaData.php',
- 'OC\\HTTPHelper' => $baseDir . '/lib/private/HTTPHelper.php',
'OC\\HintException' => $baseDir . '/lib/private/HintException.php',
'OC\\Hooks\\BasicEmitter' => $baseDir . '/lib/private/Hooks/BasicEmitter.php',
'OC\\Hooks\\Emitter' => $baseDir . '/lib/private/Hooks/Emitter.php',
@@ -713,6 +796,7 @@ return array(
'OC\\L10N\\Factory' => $baseDir . '/lib/private/L10N/Factory.php',
'OC\\L10N\\L10N' => $baseDir . '/lib/private/L10N/L10N.php',
'OC\\L10N\\L10NString' => $baseDir . '/lib/private/L10N/L10NString.php',
+ 'OC\\L10N\\LanguageIterator' => $baseDir . '/lib/private/L10N/LanguageIterator.php',
'OC\\L10N\\LanguageNotFoundException' => $baseDir . '/lib/private/L10N/LanguageNotFoundException.php',
'OC\\LargeFileHelper' => $baseDir . '/lib/private/LargeFileHelper.php',
'OC\\Lock\\AbstractLockingProvider' => $baseDir . '/lib/private/Lock/AbstractLockingProvider.php',
@@ -725,9 +809,12 @@ return array(
'OC\\Log' => $baseDir . '/lib/private/Log.php',
'OC\\Log\\ErrorHandler' => $baseDir . '/lib/private/Log/ErrorHandler.php',
'OC\\Log\\Errorlog' => $baseDir . '/lib/private/Log/Errorlog.php',
+ 'OC\\Log\\ExceptionSerializer' => $baseDir . '/lib/private/Log/ExceptionSerializer.php',
'OC\\Log\\File' => $baseDir . '/lib/private/Log/File.php',
+ 'OC\\Log\\LogFactory' => $baseDir . '/lib/private/Log/LogFactory.php',
'OC\\Log\\Rotate' => $baseDir . '/lib/private/Log/Rotate.php',
'OC\\Log\\Syslog' => $baseDir . '/lib/private/Log/Syslog.php',
+ 'OC\\Log\\Systemdlog' => $baseDir . '/lib/private/Log/Systemdlog.php',
'OC\\Mail\\Attachment' => $baseDir . '/lib/private/Mail/Attachment.php',
'OC\\Mail\\EMailTemplate' => $baseDir . '/lib/private/Mail/EMailTemplate.php',
'OC\\Mail\\Mailer' => $baseDir . '/lib/private/Mail/Mailer.php',
@@ -761,6 +848,7 @@ return array(
'OC\\PreviewManager' => $baseDir . '/lib/private/PreviewManager.php',
'OC\\PreviewNotAvailableException' => $baseDir . '/lib/private/PreviewNotAvailableException.php',
'OC\\Preview\\BMP' => $baseDir . '/lib/private/Preview/BMP.php',
+ 'OC\\Preview\\BackgroundCleanupJob' => $baseDir . '/lib/private/Preview/BackgroundCleanupJob.php',
'OC\\Preview\\Bitmap' => $baseDir . '/lib/private/Preview/Bitmap.php',
'OC\\Preview\\Font' => $baseDir . '/lib/private/Preview/Font.php',
'OC\\Preview\\GIF' => $baseDir . '/lib/private/Preview/GIF.php',
@@ -801,6 +889,7 @@ return array(
'OC\\Remote\\User' => $baseDir . '/lib/private/Remote/User.php',
'OC\\Repair' => $baseDir . '/lib/private/Repair.php',
'OC\\RepairException' => $baseDir . '/lib/private/RepairException.php',
+ 'OC\\Repair\\AddCleanupUpdaterBackupsJob' => $baseDir . '/lib/private/Repair/AddCleanupUpdaterBackupsJob.php',
'OC\\Repair\\CleanTags' => $baseDir . '/lib/private/Repair/CleanTags.php',
'OC\\Repair\\ClearFrontendCaches' => $baseDir . '/lib/private/Repair/ClearFrontendCaches.php',
'OC\\Repair\\Collation' => $baseDir . '/lib/private/Repair/Collation.php',
@@ -808,6 +897,8 @@ return array(
'OC\\Repair\\NC11\\FixMountStorages' => $baseDir . '/lib/private/Repair/NC11/FixMountStorages.php',
'OC\\Repair\\NC13\\AddLogRotateJob' => $baseDir . '/lib/private/Repair/NC13/AddLogRotateJob.php',
'OC\\Repair\\NC13\\RepairInvalidPaths' => $baseDir . '/lib/private/Repair/NC13/RepairInvalidPaths.php',
+ 'OC\\Repair\\NC14\\AddPreviewBackgroundCleanupJob' => $baseDir . '/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php',
+ 'OC\\Repair\\NC14\\RepairPendingCronJobs' => $baseDir . '/lib/private/Repair/NC14/RepairPendingCronJobs.php',
'OC\\Repair\\OldGroupMembershipShares' => $baseDir . '/lib/private/Repair/OldGroupMembershipShares.php',
'OC\\Repair\\Owncloud\\DropAccountTermsTable' => $baseDir . '/lib/private/Repair/Owncloud/DropAccountTermsTable.php',
'OC\\Repair\\Owncloud\\SaveAccountsTableData' => $baseDir . '/lib/private/Repair/Owncloud/SaveAccountsTableData.php',
@@ -863,12 +954,11 @@ return array(
'OC\\Settings\\Activity\\SecurityProvider' => $baseDir . '/settings/Activity/SecurityProvider.php',
'OC\\Settings\\Activity\\SecuritySetting' => $baseDir . '/settings/Activity/SecuritySetting.php',
'OC\\Settings\\Activity\\Setting' => $baseDir . '/settings/Activity/Setting.php',
- 'OC\\Settings\\Admin\\Additional' => $baseDir . '/lib/private/Settings/Admin/Additional.php',
'OC\\Settings\\Admin\\Encryption' => $baseDir . '/lib/private/Settings/Admin/Encryption.php',
+ 'OC\\Settings\\Admin\\Mail' => $baseDir . '/lib/private/Settings/Admin/Mail.php',
+ 'OC\\Settings\\Admin\\Overview' => $baseDir . '/lib/private/Settings/Admin/Overview.php',
'OC\\Settings\\Admin\\Server' => $baseDir . '/lib/private/Settings/Admin/Server.php',
- 'OC\\Settings\\Admin\\ServerDevNotice' => $baseDir . '/lib/private/Settings/Admin/ServerDevNotice.php',
'OC\\Settings\\Admin\\Sharing' => $baseDir . '/lib/private/Settings/Admin/Sharing.php',
- 'OC\\Settings\\Admin\\TipsTricks' => $baseDir . '/lib/private/Settings/Admin/TipsTricks.php',
'OC\\Settings\\Application' => $baseDir . '/settings/Application.php',
'OC\\Settings\\BackgroundJobs\\VerifyUserData' => $baseDir . '/settings/BackgroundJobs/VerifyUserData.php',
'OC\\Settings\\Controller\\AdminSettingsController' => $baseDir . '/settings/Controller/AdminSettingsController.php',
@@ -878,12 +968,9 @@ return array(
'OC\\Settings\\Controller\\ChangePasswordController' => $baseDir . '/settings/Controller/ChangePasswordController.php',
'OC\\Settings\\Controller\\CheckSetupController' => $baseDir . '/settings/Controller/CheckSetupController.php',
'OC\\Settings\\Controller\\CommonSettingsTrait' => $baseDir . '/settings/Controller/CommonSettingsTrait.php',
- 'OC\\Settings\\Controller\\EncryptionController' => $baseDir . '/settings/Controller/EncryptionController.php',
- 'OC\\Settings\\Controller\\GroupsController' => $baseDir . '/settings/Controller/GroupsController.php',
'OC\\Settings\\Controller\\LogSettingsController' => $baseDir . '/settings/Controller/LogSettingsController.php',
'OC\\Settings\\Controller\\MailSettingsController' => $baseDir . '/settings/Controller/MailSettingsController.php',
'OC\\Settings\\Controller\\PersonalSettingsController' => $baseDir . '/settings/Controller/PersonalSettingsController.php',
- 'OC\\Settings\\Controller\\SecuritySettingsController' => $baseDir . '/settings/Controller/SecuritySettingsController.php',
'OC\\Settings\\Controller\\UsersController' => $baseDir . '/settings/Controller/UsersController.php',
'OC\\Settings\\Hooks' => $baseDir . '/settings/Hooks.php',
'OC\\Settings\\Mailer\\NewUserMailHelper' => $baseDir . '/settings/Mailer/NewUserMailHelper.php',
@@ -892,6 +979,7 @@ return array(
'OC\\Settings\\Personal\\Additional' => $baseDir . '/lib/private/Settings/Personal/Additional.php',
'OC\\Settings\\Personal\\PersonalInfo' => $baseDir . '/lib/private/Settings/Personal/PersonalInfo.php',
'OC\\Settings\\Personal\\Security' => $baseDir . '/lib/private/Settings/Personal/Security.php',
+ 'OC\\Settings\\Personal\\ServerDevNotice' => $baseDir . '/lib/private/Settings/Personal/ServerDevNotice.php',
'OC\\Settings\\Section' => $baseDir . '/lib/private/Settings/Section.php',
'OC\\Setup' => $baseDir . '/lib/private/Setup.php',
'OC\\Setup\\AbstractDatabase' => $baseDir . '/lib/private/Setup/AbstractDatabase.php',
@@ -929,6 +1017,7 @@ return array(
'OC\\TemplateLayout' => $baseDir . '/lib/private/TemplateLayout.php',
'OC\\Template\\Base' => $baseDir . '/lib/private/Template/Base.php',
'OC\\Template\\CSSResourceLocator' => $baseDir . '/lib/private/Template/CSSResourceLocator.php',
+ 'OC\\Template\\IconsCacher' => $baseDir . '/lib/private/Template/IconsCacher.php',
'OC\\Template\\JSCombiner' => $baseDir . '/lib/private/Template/JSCombiner.php',
'OC\\Template\\JSConfigHelper' => $baseDir . '/lib/private/Template/JSConfigHelper.php',
'OC\\Template\\JSResourceLocator' => $baseDir . '/lib/private/Template/JSResourceLocator.php',
@@ -938,6 +1027,9 @@ return array(
'OC\\Template\\TemplateFileLocator' => $baseDir . '/lib/private/Template/TemplateFileLocator.php',
'OC\\URLGenerator' => $baseDir . '/lib/private/URLGenerator.php',
'OC\\Updater' => $baseDir . '/lib/private/Updater.php',
+ 'OC\\Updater\\ChangesCheck' => $baseDir . '/lib/private/Updater/ChangesCheck.php',
+ 'OC\\Updater\\ChangesMapper' => $baseDir . '/lib/private/Updater/ChangesMapper.php',
+ 'OC\\Updater\\ChangesResult' => $baseDir . '/lib/private/Updater/ChangesResult.php',
'OC\\Updater\\VersionCheck' => $baseDir . '/lib/private/Updater/VersionCheck.php',
'OC\\User\\Backend' => $baseDir . '/lib/private/User/Backend.php',
'OC\\User\\Database' => $baseDir . '/lib/private/User/Database.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 2483b5689b3..c54120586f9 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -48,11 +48,13 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\App' => __DIR__ . '/../../..' . '/lib/public/App.php',
'OCP\\AppFramework\\ApiController' => __DIR__ . '/../../..' . '/lib/public/AppFramework/ApiController.php',
'OCP\\AppFramework\\App' => __DIR__ . '/../../..' . '/lib/public/AppFramework/App.php',
+ 'OCP\\AppFramework\\AuthPublicShareController' => __DIR__ . '/../../..' . '/lib/public/AppFramework/AuthPublicShareController.php',
'OCP\\AppFramework\\Controller' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Controller.php',
'OCP\\AppFramework\\Db\\DoesNotExistException' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/DoesNotExistException.php',
'OCP\\AppFramework\\Db\\Entity' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/Entity.php',
'OCP\\AppFramework\\Db\\Mapper' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/Mapper.php',
'OCP\\AppFramework\\Db\\MultipleObjectsReturnedException' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/MultipleObjectsReturnedException.php',
+ 'OCP\\AppFramework\\Db\\QBMapper' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/QBMapper.php',
'OCP\\AppFramework\\Http' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http.php',
'OCP\\AppFramework\\Http\\ContentSecurityPolicy' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/ContentSecurityPolicy.php',
'OCP\\AppFramework\\Http\\DataDisplayResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/DataDisplayResponse.php',
@@ -69,7 +71,15 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\AppFramework\\Http\\RedirectResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/RedirectResponse.php',
'OCP\\AppFramework\\Http\\Response' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Response.php',
'OCP\\AppFramework\\Http\\StreamResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/StreamResponse.php',
+ 'OCP\\AppFramework\\Http\\StrictContentSecurityPolicy' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/StrictContentSecurityPolicy.php',
+ 'OCP\\AppFramework\\Http\\StrictEvalContentSecurityPolicy' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/StrictEvalContentSecurityPolicy.php',
+ 'OCP\\AppFramework\\Http\\StrictInlineContentSecurityPolicy' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/StrictInlineContentSecurityPolicy.php',
'OCP\\AppFramework\\Http\\TemplateResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/TemplateResponse.php',
+ 'OCP\\AppFramework\\Http\\Template\\ExternalShareMenuAction' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php',
+ 'OCP\\AppFramework\\Http\\Template\\IMenuAction' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Template/IMenuAction.php',
+ 'OCP\\AppFramework\\Http\\Template\\LinkMenuAction' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Template/LinkMenuAction.php',
+ 'OCP\\AppFramework\\Http\\Template\\PublicTemplateResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php',
+ 'OCP\\AppFramework\\Http\\Template\\SimpleMenuAction' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Template/SimpleMenuAction.php',
'OCP\\AppFramework\\IAppContainer' => __DIR__ . '/../../..' . '/lib/public/AppFramework/IAppContainer.php',
'OCP\\AppFramework\\Middleware' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Middleware.php',
'OCP\\AppFramework\\OCSController' => __DIR__ . '/../../..' . '/lib/public/AppFramework/OCSController.php',
@@ -77,6 +87,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\AppFramework\\OCS\\OCSException' => __DIR__ . '/../../..' . '/lib/public/AppFramework/OCS/OCSException.php',
'OCP\\AppFramework\\OCS\\OCSForbiddenException' => __DIR__ . '/../../..' . '/lib/public/AppFramework/OCS/OCSForbiddenException.php',
'OCP\\AppFramework\\OCS\\OCSNotFoundException' => __DIR__ . '/../../..' . '/lib/public/AppFramework/OCS/OCSNotFoundException.php',
+ 'OCP\\AppFramework\\PublicShareController' => __DIR__ . '/../../..' . '/lib/public/AppFramework/PublicShareController.php',
'OCP\\AppFramework\\QueryException' => __DIR__ . '/../../..' . '/lib/public/AppFramework/QueryException.php',
'OCP\\AppFramework\\Utility\\IControllerMethodReflector' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Utility/IControllerMethodReflector.php',
'OCP\\AppFramework\\Utility\\ITimeFactory' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Utility/ITimeFactory.php',
@@ -90,13 +101,21 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Authentication\\LoginCredentials\\IStore' => __DIR__ . '/../../..' . '/lib/public/Authentication/LoginCredentials/IStore.php',
'OCP\\Authentication\\TwoFactorAuth\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/IProvider.php',
'OCP\\Authentication\\TwoFactorAuth\\IProvidesCustomCSP' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/IProvidesCustomCSP.php',
+ 'OCP\\Authentication\\TwoFactorAuth\\IRegistry' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/IRegistry.php',
'OCP\\Authentication\\TwoFactorAuth\\TwoFactorException' => __DIR__ . '/../../..' . '/lib/public/Authentication/TwoFactorAuth/TwoFactorException.php',
'OCP\\AutoloadNotAllowedException' => __DIR__ . '/../../..' . '/lib/public/AutoloadNotAllowedException.php',
'OCP\\BackgroundJob' => __DIR__ . '/../../..' . '/lib/public/BackgroundJob.php',
'OCP\\BackgroundJob\\IJob' => __DIR__ . '/../../..' . '/lib/public/BackgroundJob/IJob.php',
'OCP\\BackgroundJob\\IJobList' => __DIR__ . '/../../..' . '/lib/public/BackgroundJob/IJobList.php',
+ 'OCP\\Calendar\\BackendTemporarilyUnavailableException' => __DIR__ . '/../../..' . '/lib/public/Calendar/BackendTemporarilyUnavailableException.php',
'OCP\\Calendar\\ICalendar' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendar.php',
'OCP\\Calendar\\IManager' => __DIR__ . '/../../..' . '/lib/public/Calendar/IManager.php',
+ 'OCP\\Calendar\\Resource\\IBackend' => __DIR__ . '/../../..' . '/lib/public/Calendar/Resource/IBackend.php',
+ 'OCP\\Calendar\\Resource\\IManager' => __DIR__ . '/../../..' . '/lib/public/Calendar/Resource/IManager.php',
+ 'OCP\\Calendar\\Resource\\IResource' => __DIR__ . '/../../..' . '/lib/public/Calendar/Resource/IResource.php',
+ 'OCP\\Calendar\\Room\\IBackend' => __DIR__ . '/../../..' . '/lib/public/Calendar/Room/IBackend.php',
+ 'OCP\\Calendar\\Room\\IManager' => __DIR__ . '/../../..' . '/lib/public/Calendar/Room/IManager.php',
+ 'OCP\\Calendar\\Room\\IRoom' => __DIR__ . '/../../..' . '/lib/public/Calendar/Room/IRoom.php',
'OCP\\Capabilities\\ICapability' => __DIR__ . '/../../..' . '/lib/public/Capabilities/ICapability.php',
'OCP\\Capabilities\\IPublicCapability' => __DIR__ . '/../../..' . '/lib/public/Capabilities/IPublicCapability.php',
'OCP\\Collaboration\\AutoComplete\\IManager' => __DIR__ . '/../../..' . '/lib/public/Collaboration/AutoComplete/IManager.php',
@@ -118,7 +137,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Comments\\NotFoundException' => __DIR__ . '/../../..' . '/lib/public/Comments/NotFoundException.php',
'OCP\\Console\\ConsoleEvent' => __DIR__ . '/../../..' . '/lib/public/Console/ConsoleEvent.php',
'OCP\\Constants' => __DIR__ . '/../../..' . '/lib/public/Constants.php',
- 'OCP\\Contacts' => __DIR__ . '/../../..' . '/lib/public/Contacts.php',
'OCP\\Contacts\\ContactsMenu\\IAction' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IAction.php',
'OCP\\Contacts\\ContactsMenu\\IActionFactory' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IActionFactory.php',
'OCP\\Contacts\\ContactsMenu\\IContactsStore' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IContactsStore.php',
@@ -126,7 +144,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Contacts\\ContactsMenu\\ILinkAction' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/ILinkAction.php',
'OCP\\Contacts\\ContactsMenu\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IProvider.php',
'OCP\\Contacts\\IManager' => __DIR__ . '/../../..' . '/lib/public/Contacts/IManager.php',
- 'OCP\\DB' => __DIR__ . '/../../..' . '/lib/public/DB.php',
'OCP\\DB\\ISchemaWrapper' => __DIR__ . '/../../..' . '/lib/public/DB/ISchemaWrapper.php',
'OCP\\DB\\QueryBuilder\\ICompositeExpression' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/ICompositeExpression.php',
'OCP\\DB\\QueryBuilder\\IExpressionBuilder' => __DIR__ . '/../../..' . '/lib/public/DB/QueryBuilder/IExpressionBuilder.php',
@@ -145,6 +162,17 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Encryption\\IFile' => __DIR__ . '/../../..' . '/lib/public/Encryption/IFile.php',
'OCP\\Encryption\\IManager' => __DIR__ . '/../../..' . '/lib/public/Encryption/IManager.php',
'OCP\\Encryption\\Keys\\IStorage' => __DIR__ . '/../../..' . '/lib/public/Encryption/Keys/IStorage.php',
+ 'OCP\\Federation\\Exceptions\\ActionNotSupportedException' => __DIR__ . '/../../..' . '/lib/public/Federation/Exceptions/ActionNotSupportedException.php',
+ 'OCP\\Federation\\Exceptions\\AuthenticationFailedException' => __DIR__ . '/../../..' . '/lib/public/Federation/Exceptions/AuthenticationFailedException.php',
+ 'OCP\\Federation\\Exceptions\\BadRequestException' => __DIR__ . '/../../..' . '/lib/public/Federation/Exceptions/BadRequestException.php',
+ 'OCP\\Federation\\Exceptions\\ProviderAlreadyExistsException' => __DIR__ . '/../../..' . '/lib/public/Federation/Exceptions/ProviderAlreadyExistsException.php',
+ 'OCP\\Federation\\Exceptions\\ProviderCouldNotAddShareException' => __DIR__ . '/../../..' . '/lib/public/Federation/Exceptions/ProviderCouldNotAddShareException.php',
+ 'OCP\\Federation\\Exceptions\\ProviderDoesNotExistsException' => __DIR__ . '/../../..' . '/lib/public/Federation/Exceptions/ProviderDoesNotExistsException.php',
+ 'OCP\\Federation\\ICloudFederationFactory' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudFederationFactory.php',
+ 'OCP\\Federation\\ICloudFederationNotification' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudFederationNotification.php',
+ 'OCP\\Federation\\ICloudFederationProvider' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudFederationProvider.php',
+ 'OCP\\Federation\\ICloudFederationProviderManager' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudFederationProviderManager.php',
+ 'OCP\\Federation\\ICloudFederationShare' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudFederationShare.php',
'OCP\\Federation\\ICloudId' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudId.php',
'OCP\\Federation\\ICloudIdManager' => __DIR__ . '/../../..' . '/lib/public/Federation/ICloudIdManager.php',
'OCP\\Files' => __DIR__ . '/../../..' . '/lib/public/Files.php',
@@ -168,6 +196,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Files\\FileNameTooLongException' => __DIR__ . '/../../..' . '/lib/public/Files/FileNameTooLongException.php',
'OCP\\Files\\Folder' => __DIR__ . '/../../..' . '/lib/public/Files/Folder.php',
'OCP\\Files\\ForbiddenException' => __DIR__ . '/../../..' . '/lib/public/Files/ForbiddenException.php',
+ 'OCP\\Files\\GenericFileException' => __DIR__ . '/../../..' . '/lib/public/Files/GenericFileException.php',
'OCP\\Files\\IAppData' => __DIR__ . '/../../..' . '/lib/public/Files/IAppData.php',
'OCP\\Files\\IHomeStorage' => __DIR__ . '/../../..' . '/lib/public/Files/IHomeStorage.php',
'OCP\\Files\\IMimeTypeDetector' => __DIR__ . '/../../..' . '/lib/public/Files/IMimeTypeDetector.php',
@@ -211,6 +240,15 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Files\\UnseekableException' => __DIR__ . '/../../..' . '/lib/public/Files/UnseekableException.php',
'OCP\\GlobalScale\\IConfig' => __DIR__ . '/../../..' . '/lib/public/GlobalScale/IConfig.php',
'OCP\\GroupInterface' => __DIR__ . '/../../..' . '/lib/public/GroupInterface.php',
+ 'OCP\\Group\\Backend\\ABackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/ABackend.php',
+ 'OCP\\Group\\Backend\\IAddToGroupBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IAddToGroupBackend.php',
+ 'OCP\\Group\\Backend\\ICountDisabledInGroup' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/ICountDisabledInGroup.php',
+ 'OCP\\Group\\Backend\\ICountUsersBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/ICountUsersBackend.php',
+ 'OCP\\Group\\Backend\\ICreateGroupBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/ICreateGroupBackend.php',
+ 'OCP\\Group\\Backend\\IDeleteGroupBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IDeleteGroupBackend.php',
+ 'OCP\\Group\\Backend\\IGroupDetailsBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IGroupDetailsBackend.php',
+ 'OCP\\Group\\Backend\\IIsAdminBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IIsAdminBackend.php',
+ 'OCP\\Group\\Backend\\IRemoveFromGroupBackend' => __DIR__ . '/../../..' . '/lib/public/Group/Backend/IRemoveFromGroupBackend.php',
'OCP\\Http\\Client\\IClient' => __DIR__ . '/../../..' . '/lib/public/Http/Client/IClient.php',
'OCP\\Http\\Client\\IClientService' => __DIR__ . '/../../..' . '/lib/public/Http/Client/IClientService.php',
'OCP\\Http\\Client\\IResponse' => __DIR__ . '/../../..' . '/lib/public/Http/Client/IResponse.php',
@@ -230,7 +268,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\IEventSource' => __DIR__ . '/../../..' . '/lib/public/IEventSource.php',
'OCP\\IGroup' => __DIR__ . '/../../..' . '/lib/public/IGroup.php',
'OCP\\IGroupManager' => __DIR__ . '/../../..' . '/lib/public/IGroupManager.php',
- 'OCP\\IHelper' => __DIR__ . '/../../..' . '/lib/public/IHelper.php',
'OCP\\IImage' => __DIR__ . '/../../..' . '/lib/public/IImage.php',
'OCP\\IL10N' => __DIR__ . '/../../..' . '/lib/public/IL10N.php',
'OCP\\ILogger' => __DIR__ . '/../../..' . '/lib/public/ILogger.php',
@@ -251,14 +288,18 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\IUserManager' => __DIR__ . '/../../..' . '/lib/public/IUserManager.php',
'OCP\\IUserSession' => __DIR__ . '/../../..' . '/lib/public/IUserSession.php',
'OCP\\Image' => __DIR__ . '/../../..' . '/lib/public/Image.php',
- 'OCP\\JSON' => __DIR__ . '/../../..' . '/lib/public/JSON.php',
'OCP\\L10N\\IFactory' => __DIR__ . '/../../..' . '/lib/public/L10N/IFactory.php',
+ 'OCP\\L10N\\ILanguageIterator' => __DIR__ . '/../../..' . '/lib/public/L10N/ILanguageIterator.php',
'OCP\\LDAP\\IDeletionFlagSupport' => __DIR__ . '/../../..' . '/lib/public/LDAP/IDeletionFlagSupport.php',
'OCP\\LDAP\\ILDAPProvider' => __DIR__ . '/../../..' . '/lib/public/LDAP/ILDAPProvider.php',
'OCP\\LDAP\\ILDAPProviderFactory' => __DIR__ . '/../../..' . '/lib/public/LDAP/ILDAPProviderFactory.php',
'OCP\\Lock\\ILockingProvider' => __DIR__ . '/../../..' . '/lib/public/Lock/ILockingProvider.php',
'OCP\\Lock\\LockedException' => __DIR__ . '/../../..' . '/lib/public/Lock/LockedException.php',
'OCP\\Lockdown\\ILockdownManager' => __DIR__ . '/../../..' . '/lib/public/Lockdown/ILockdownManager.php',
+ 'OCP\\Log\\IFileBased' => __DIR__ . '/../../..' . '/lib/public/Log/IFileBased.php',
+ 'OCP\\Log\\ILogFactory' => __DIR__ . '/../../..' . '/lib/public/Log/ILogFactory.php',
+ 'OCP\\Log\\IWriter' => __DIR__ . '/../../..' . '/lib/public/Log/IWriter.php',
+ 'OCP\\Log\\RotationTrait' => __DIR__ . '/../../..' . '/lib/public/Log/RotationTrait.php',
'OCP\\Mail\\IAttachment' => __DIR__ . '/../../..' . '/lib/public/Mail/IAttachment.php',
'OCP\\Mail\\IEMailTemplate' => __DIR__ . '/../../..' . '/lib/public/Mail/IEMailTemplate.php',
'OCP\\Mail\\IMailer' => __DIR__ . '/../../..' . '/lib/public/Mail/IMailer.php',
@@ -284,7 +325,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Remote\\IInstance' => __DIR__ . '/../../..' . '/lib/public/Remote/IInstance.php',
'OCP\\Remote\\IInstanceFactory' => __DIR__ . '/../../..' . '/lib/public/Remote/IInstanceFactory.php',
'OCP\\Remote\\IUser' => __DIR__ . '/../../..' . '/lib/public/Remote/IUser.php',
- 'OCP\\Response' => __DIR__ . '/../../..' . '/lib/public/Response.php',
'OCP\\RichObjectStrings\\Definitions' => __DIR__ . '/../../..' . '/lib/public/RichObjectStrings/Definitions.php',
'OCP\\RichObjectStrings\\IValidator' => __DIR__ . '/../../..' . '/lib/public/RichObjectStrings/IValidator.php',
'OCP\\RichObjectStrings\\InvalidObjectExeption' => __DIR__ . '/../../..' . '/lib/public/RichObjectStrings/InvalidObjectExeption.php',
@@ -332,6 +372,15 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Template' => __DIR__ . '/../../..' . '/lib/public/Template.php',
'OCP\\User' => __DIR__ . '/../../..' . '/lib/public/User.php',
'OCP\\UserInterface' => __DIR__ . '/../../..' . '/lib/public/UserInterface.php',
+ 'OCP\\User\\Backend\\ABackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ABackend.php',
+ 'OCP\\User\\Backend\\ICheckPasswordBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ICheckPasswordBackend.php',
+ 'OCP\\User\\Backend\\ICountUsersBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ICountUsersBackend.php',
+ 'OCP\\User\\Backend\\ICreateUserBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ICreateUserBackend.php',
+ 'OCP\\User\\Backend\\IGetDisplayNameBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetDisplayNameBackend.php',
+ 'OCP\\User\\Backend\\IGetHomeBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetHomeBackend.php',
+ 'OCP\\User\\Backend\\IProvideAvatarBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IProvideAvatarBackend.php',
+ 'OCP\\User\\Backend\\ISetDisplayNameBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ISetDisplayNameBackend.php',
+ 'OCP\\User\\Backend\\ISetPasswordBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ISetPasswordBackend.php',
'OCP\\Util' => __DIR__ . '/../../..' . '/lib/public/Util.php',
'OCP\\WorkflowEngine\\ICheck' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/ICheck.php',
'OCP\\WorkflowEngine\\IManager' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/IManager.php',
@@ -353,6 +402,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\AppFramework\\Http\\Request' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http/Request.php',
'OC\\AppFramework\\Middleware\\MiddlewareDispatcher' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php',
'OC\\AppFramework\\Middleware\\OCSMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/OCSMiddleware.php',
+ 'OC\\AppFramework\\Middleware\\PublicShare\\Exceptions\\NeedAuthenticationException' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php',
+ 'OC\\AppFramework\\Middleware\\PublicShare\\PublicShareMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php',
'OC\\AppFramework\\Middleware\\Security\\BruteForceMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php',
'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',
@@ -376,7 +427,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\AppFramework\\Utility\\ControllerMethodReflector' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Utility/ControllerMethodReflector.php',
'OC\\AppFramework\\Utility\\SimpleContainer' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Utility/SimpleContainer.php',
'OC\\AppFramework\\Utility\\TimeFactory' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Utility/TimeFactory.php',
- 'OC\\AppHelper' => __DIR__ . '/../../..' . '/lib/private/AppHelper.php',
'OC\\App\\AppManager' => __DIR__ . '/../../..' . '/lib/private/App/AppManager.php',
'OC\\App\\AppStore\\Bundles\\Bundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/Bundle.php',
'OC\\App\\AppStore\\Bundles\\BundleFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/BundleFetcher.php',
@@ -402,6 +452,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\App\\CodeChecker\\NodeVisitor' => __DIR__ . '/../../..' . '/lib/private/App/CodeChecker/NodeVisitor.php',
'OC\\App\\CodeChecker\\PrivateCheck' => __DIR__ . '/../../..' . '/lib/private/App/CodeChecker/PrivateCheck.php',
'OC\\App\\CodeChecker\\StrongComparisonCheck' => __DIR__ . '/../../..' . '/lib/private/App/CodeChecker/StrongComparisonCheck.php',
+ 'OC\\App\\CompareVersion' => __DIR__ . '/../../..' . '/lib/private/App/CompareVersion.php',
'OC\\App\\DependencyAnalyzer' => __DIR__ . '/../../..' . '/lib/private/App/DependencyAnalyzer.php',
'OC\\App\\InfoParser' => __DIR__ . '/../../..' . '/lib/private/App/InfoParser.php',
'OC\\App\\Platform' => __DIR__ . '/../../..' . '/lib/private/App/Platform.php',
@@ -421,9 +472,18 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Authentication\\Token\\DefaultTokenCleanupJob' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/DefaultTokenCleanupJob.php',
'OC\\Authentication\\Token\\DefaultTokenMapper' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/DefaultTokenMapper.php',
'OC\\Authentication\\Token\\DefaultTokenProvider' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/DefaultTokenProvider.php',
+ 'OC\\Authentication\\Token\\ExpiredTokenException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/ExpiredTokenException.php',
'OC\\Authentication\\Token\\IProvider' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/IProvider.php',
'OC\\Authentication\\Token\\IToken' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/IToken.php',
+ 'OC\\Authentication\\Token\\Manager' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/Manager.php',
+ 'OC\\Authentication\\Token\\PublicKeyToken' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/PublicKeyToken.php',
+ 'OC\\Authentication\\Token\\PublicKeyTokenMapper' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/PublicKeyTokenMapper.php',
+ 'OC\\Authentication\\Token\\PublicKeyTokenProvider' => __DIR__ . '/../../..' . '/lib/private/Authentication/Token/PublicKeyTokenProvider.php',
+ 'OC\\Authentication\\TwoFactorAuth\\Db\\ProviderUserAssignmentDao' => __DIR__ . '/../../..' . '/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php',
'OC\\Authentication\\TwoFactorAuth\\Manager' => __DIR__ . '/../../..' . '/lib/private/Authentication/TwoFactorAuth/Manager.php',
+ 'OC\\Authentication\\TwoFactorAuth\\ProviderLoader' => __DIR__ . '/../../..' . '/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php',
+ 'OC\\Authentication\\TwoFactorAuth\\ProviderSet' => __DIR__ . '/../../..' . '/lib/private/Authentication/TwoFactorAuth/ProviderSet.php',
+ 'OC\\Authentication\\TwoFactorAuth\\Registry' => __DIR__ . '/../../..' . '/lib/private/Authentication/TwoFactorAuth/Registry.php',
'OC\\Avatar' => __DIR__ . '/../../..' . '/lib/private/Avatar.php',
'OC\\AvatarManager' => __DIR__ . '/../../..' . '/lib/private/AvatarManager.php',
'OC\\BackgroundJob\\Job' => __DIR__ . '/../../..' . '/lib/private/BackgroundJob/Job.php',
@@ -435,15 +495,19 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Cache\\CappedMemoryCache' => __DIR__ . '/../../..' . '/lib/private/Cache/CappedMemoryCache.php',
'OC\\Cache\\File' => __DIR__ . '/../../..' . '/lib/private/Cache/File.php',
'OC\\Calendar\\Manager' => __DIR__ . '/../../..' . '/lib/private/Calendar/Manager.php',
+ 'OC\\Calendar\\Resource\\Manager' => __DIR__ . '/../../..' . '/lib/private/Calendar/Resource/Manager.php',
+ 'OC\\Calendar\\Room\\Manager' => __DIR__ . '/../../..' . '/lib/private/Calendar/Room/Manager.php',
'OC\\CapabilitiesManager' => __DIR__ . '/../../..' . '/lib/private/CapabilitiesManager.php',
'OC\\Collaboration\\AutoComplete\\Manager' => __DIR__ . '/../../..' . '/lib/private/Collaboration/AutoComplete/Manager.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\\RemoteGroupPlugin' => __DIR__ . '/../../..' . '/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.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\\Color' => __DIR__ . '/../../..' . '/lib/private/Color.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',
@@ -466,6 +530,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Contacts\\ContactsMenu\\Manager' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Manager.php',
'OC\\Contacts\\ContactsMenu\\Providers\\EMailProvider' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php',
'OC\\Core\\Application' => __DIR__ . '/../../..' . '/core/Application.php',
+ 'OC\\Core\\BackgroundJobs\\BackgroundCleanupUpdaterBackupsJob' => __DIR__ . '/../../..' . '/core/BackgroundJobs/BackgroundCleanupUpdaterBackupsJob.php',
'OC\\Core\\Command\\App\\CheckCode' => __DIR__ . '/../../..' . '/core/Command/App/CheckCode.php',
'OC\\Core\\Command\\App\\Disable' => __DIR__ . '/../../..' . '/core/Command/App/Disable.php',
'OC\\Core\\Command\\App\\Enable' => __DIR__ . '/../../..' . '/core/Command/App/Enable.php',
@@ -532,6 +597,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Command\\TwoFactorAuth\\Base' => __DIR__ . '/../../..' . '/core/Command/TwoFactorAuth/Base.php',
'OC\\Core\\Command\\TwoFactorAuth\\Disable' => __DIR__ . '/../../..' . '/core/Command/TwoFactorAuth/Disable.php',
'OC\\Core\\Command\\TwoFactorAuth\\Enable' => __DIR__ . '/../../..' . '/core/Command/TwoFactorAuth/Enable.php',
+ 'OC\\Core\\Command\\TwoFactorAuth\\State' => __DIR__ . '/../../..' . '/core/Command/TwoFactorAuth/State.php',
'OC\\Core\\Command\\Upgrade' => __DIR__ . '/../../..' . '/core/Command/Upgrade.php',
'OC\\Core\\Command\\User\\Add' => __DIR__ . '/../../..' . '/core/Command/User/Add.php',
'OC\\Core\\Command\\User\\Delete' => __DIR__ . '/../../..' . '/core/Command/User/Delete.php',
@@ -545,19 +611,24 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Command\\User\\Setting' => __DIR__ . '/../../..' . '/core/Command/User/Setting.php',
'OC\\Core\\Controller\\AutoCompleteController' => __DIR__ . '/../../..' . '/core/Controller/AutoCompleteController.php',
'OC\\Core\\Controller\\AvatarController' => __DIR__ . '/../../..' . '/core/Controller/AvatarController.php',
+ 'OC\\Core\\Controller\\CSRFTokenController' => __DIR__ . '/../../..' . '/core/Controller/CSRFTokenController.php',
'OC\\Core\\Controller\\ClientFlowLoginController' => __DIR__ . '/../../..' . '/core/Controller/ClientFlowLoginController.php',
'OC\\Core\\Controller\\ContactsMenuController' => __DIR__ . '/../../..' . '/core/Controller/ContactsMenuController.php',
'OC\\Core\\Controller\\CssController' => __DIR__ . '/../../..' . '/core/Controller/CssController.php',
'OC\\Core\\Controller\\JsController' => __DIR__ . '/../../..' . '/core/Controller/JsController.php',
'OC\\Core\\Controller\\LoginController' => __DIR__ . '/../../..' . '/core/Controller/LoginController.php',
'OC\\Core\\Controller\\LostController' => __DIR__ . '/../../..' . '/core/Controller/LostController.php',
+ 'OC\\Core\\Controller\\NavigationController' => __DIR__ . '/../../..' . '/core/Controller/NavigationController.php',
'OC\\Core\\Controller\\OCJSController' => __DIR__ . '/../../..' . '/core/Controller/OCJSController.php',
'OC\\Core\\Controller\\OCSController' => __DIR__ . '/../../..' . '/core/Controller/OCSController.php',
'OC\\Core\\Controller\\PreviewController' => __DIR__ . '/../../..' . '/core/Controller/PreviewController.php',
+ 'OC\\Core\\Controller\\SearchController' => __DIR__ . '/../../..' . '/core/Controller/SearchController.php',
'OC\\Core\\Controller\\SetupController' => __DIR__ . '/../../..' . '/core/Controller/SetupController.php',
+ 'OC\\Core\\Controller\\SvgController' => __DIR__ . '/../../..' . '/core/Controller/SvgController.php',
'OC\\Core\\Controller\\TwoFactorChallengeController' => __DIR__ . '/../../..' . '/core/Controller/TwoFactorChallengeController.php',
'OC\\Core\\Controller\\UserController' => __DIR__ . '/../../..' . '/core/Controller/UserController.php',
'OC\\Core\\Controller\\WalledGardenController' => __DIR__ . '/../../..' . '/core/Controller/WalledGardenController.php',
+ 'OC\\Core\\Controller\\WhatsNewController' => __DIR__ . '/../../..' . '/core/Controller/WhatsNewController.php',
'OC\\Core\\Middleware\\TwoFactorMiddleware' => __DIR__ . '/../../..' . '/core/Middleware/TwoFactorMiddleware.php',
'OC\\Core\\Migrations\\Version13000Date20170705121758' => __DIR__ . '/../../..' . '/core/Migrations/Version13000Date20170705121758.php',
'OC\\Core\\Migrations\\Version13000Date20170718121200' => __DIR__ . '/../../..' . '/core/Migrations/Version13000Date20170718121200.php',
@@ -565,6 +636,11 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Migrations\\Version13000Date20170919121250' => __DIR__ . '/../../..' . '/core/Migrations/Version13000Date20170919121250.php',
'OC\\Core\\Migrations\\Version13000Date20170926101637' => __DIR__ . '/../../..' . '/core/Migrations/Version13000Date20170926101637.php',
'OC\\Core\\Migrations\\Version14000Date20180129121024' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180129121024.php',
+ 'OC\\Core\\Migrations\\Version14000Date20180404140050' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180404140050.php',
+ 'OC\\Core\\Migrations\\Version14000Date20180516101403' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180516101403.php',
+ 'OC\\Core\\Migrations\\Version14000Date20180518120534' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180518120534.php',
+ 'OC\\Core\\Migrations\\Version14000Date20180522074438' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180522074438.php',
+ 'OC\\Core\\Migrations\\Version14000Date20180626223656' => __DIR__ . '/../../..' . '/core/Migrations/Version14000Date20180626223656.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',
@@ -578,6 +654,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\DB\\MigrationException' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationException.php',
'OC\\DB\\MigrationService' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationService.php',
'OC\\DB\\Migrator' => __DIR__ . '/../../..' . '/lib/private/DB/Migrator.php',
+ 'OC\\DB\\MissingIndexInformation' => __DIR__ . '/../../..' . '/lib/private/DB/MissingIndexInformation.php',
'OC\\DB\\MySQLMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/MySQLMigrator.php',
'OC\\DB\\MySqlTools' => __DIR__ . '/../../..' . '/lib/private/DB/MySqlTools.php',
'OC\\DB\\OCSqlitePlatform' => __DIR__ . '/../../..' . '/lib/private/DB/OCSqlitePlatform.php',
@@ -600,6 +677,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\DB\\QueryBuilder\\QueryBuilder' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/QueryBuilder.php',
'OC\\DB\\QueryBuilder\\QueryFunction' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/QueryFunction.php',
'OC\\DB\\QueryBuilder\\QuoteHelper' => __DIR__ . '/../../..' . '/lib/private/DB/QueryBuilder/QuoteHelper.php',
+ 'OC\\DB\\ReconnectWrapper' => __DIR__ . '/../../..' . '/lib/private/DB/ReconnectWrapper.php',
'OC\\DB\\SQLiteMigrator' => __DIR__ . '/../../..' . '/lib/private/DB/SQLiteMigrator.php',
'OC\\DB\\SQLiteSessionInit' => __DIR__ . '/../../..' . '/lib/private/DB/SQLiteSessionInit.php',
'OC\\DB\\SchemaWrapper' => __DIR__ . '/../../..' . '/lib/private/DB/SchemaWrapper.php',
@@ -627,6 +705,10 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Encryption\\Manager' => __DIR__ . '/../../..' . '/lib/private/Encryption/Manager.php',
'OC\\Encryption\\Update' => __DIR__ . '/../../..' . '/lib/private/Encryption/Update.php',
'OC\\Encryption\\Util' => __DIR__ . '/../../..' . '/lib/private/Encryption/Util.php',
+ 'OC\\Federation\\CloudFederationFactory' => __DIR__ . '/../../..' . '/lib/private/Federation/CloudFederationFactory.php',
+ 'OC\\Federation\\CloudFederationNotification' => __DIR__ . '/../../..' . '/lib/private/Federation/CloudFederationNotification.php',
+ 'OC\\Federation\\CloudFederationProviderManager' => __DIR__ . '/../../..' . '/lib/private/Federation/CloudFederationProviderManager.php',
+ 'OC\\Federation\\CloudFederationShare' => __DIR__ . '/../../..' . '/lib/private/Federation/CloudFederationShare.php',
'OC\\Federation\\CloudId' => __DIR__ . '/../../..' . '/lib/private/Federation/CloudId.php',
'OC\\Federation\\CloudIdManager' => __DIR__ . '/../../..' . '/lib/private/Federation/CloudIdManager.php',
'OC\\Files\\AppData\\AppData' => __DIR__ . '/../../..' . '/lib/private/Files/AppData/AppData.php',
@@ -672,6 +754,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Files\\Node\\Root' => __DIR__ . '/../../..' . '/lib/private/Files/Node/Root.php',
'OC\\Files\\Notify\\Change' => __DIR__ . '/../../..' . '/lib/private/Files/Notify/Change.php',
'OC\\Files\\Notify\\RenameChange' => __DIR__ . '/../../..' . '/lib/private/Files/Notify/RenameChange.php',
+ 'OC\\Files\\ObjectStore\\Azure' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/Azure.php',
'OC\\Files\\ObjectStore\\HomeObjectStoreStorage' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php',
'OC\\Files\\ObjectStore\\Mapper' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/Mapper.php',
'OC\\Files\\ObjectStore\\NoopScanner' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/NoopScanner.php',
@@ -682,6 +765,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Files\\ObjectStore\\S3Signature' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/S3Signature.php',
'OC\\Files\\ObjectStore\\StorageObjectStore' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/StorageObjectStore.php',
'OC\\Files\\ObjectStore\\Swift' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/Swift.php',
+ 'OC\\Files\\ObjectStore\\SwiftFactory' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/SwiftFactory.php',
'OC\\Files\\Search\\SearchBinaryOperator' => __DIR__ . '/../../..' . '/lib/private/Files/Search/SearchBinaryOperator.php',
'OC\\Files\\Search\\SearchComparison' => __DIR__ . '/../../..' . '/lib/private/Files/Search/SearchComparison.php',
'OC\\Files\\Search\\SearchOrder' => __DIR__ . '/../../..' . '/lib/private/Files/Search/SearchOrder.php',
@@ -721,7 +805,6 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Group\\Group' => __DIR__ . '/../../..' . '/lib/private/Group/Group.php',
'OC\\Group\\Manager' => __DIR__ . '/../../..' . '/lib/private/Group/Manager.php',
'OC\\Group\\MetaData' => __DIR__ . '/../../..' . '/lib/private/Group/MetaData.php',
- 'OC\\HTTPHelper' => __DIR__ . '/../../..' . '/lib/private/HTTPHelper.php',
'OC\\HintException' => __DIR__ . '/../../..' . '/lib/private/HintException.php',
'OC\\Hooks\\BasicEmitter' => __DIR__ . '/../../..' . '/lib/private/Hooks/BasicEmitter.php',
'OC\\Hooks\\Emitter' => __DIR__ . '/../../..' . '/lib/private/Hooks/Emitter.php',
@@ -743,6 +826,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\L10N\\Factory' => __DIR__ . '/../../..' . '/lib/private/L10N/Factory.php',
'OC\\L10N\\L10N' => __DIR__ . '/../../..' . '/lib/private/L10N/L10N.php',
'OC\\L10N\\L10NString' => __DIR__ . '/../../..' . '/lib/private/L10N/L10NString.php',
+ 'OC\\L10N\\LanguageIterator' => __DIR__ . '/../../..' . '/lib/private/L10N/LanguageIterator.php',
'OC\\L10N\\LanguageNotFoundException' => __DIR__ . '/../../..' . '/lib/private/L10N/LanguageNotFoundException.php',
'OC\\LargeFileHelper' => __DIR__ . '/../../..' . '/lib/private/LargeFileHelper.php',
'OC\\Lock\\AbstractLockingProvider' => __DIR__ . '/../../..' . '/lib/private/Lock/AbstractLockingProvider.php',
@@ -755,9 +839,12 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Log' => __DIR__ . '/../../..' . '/lib/private/Log.php',
'OC\\Log\\ErrorHandler' => __DIR__ . '/../../..' . '/lib/private/Log/ErrorHandler.php',
'OC\\Log\\Errorlog' => __DIR__ . '/../../..' . '/lib/private/Log/Errorlog.php',
+ 'OC\\Log\\ExceptionSerializer' => __DIR__ . '/../../..' . '/lib/private/Log/ExceptionSerializer.php',
'OC\\Log\\File' => __DIR__ . '/../../..' . '/lib/private/Log/File.php',
+ 'OC\\Log\\LogFactory' => __DIR__ . '/../../..' . '/lib/private/Log/LogFactory.php',
'OC\\Log\\Rotate' => __DIR__ . '/../../..' . '/lib/private/Log/Rotate.php',
'OC\\Log\\Syslog' => __DIR__ . '/../../..' . '/lib/private/Log/Syslog.php',
+ 'OC\\Log\\Systemdlog' => __DIR__ . '/../../..' . '/lib/private/Log/Systemdlog.php',
'OC\\Mail\\Attachment' => __DIR__ . '/../../..' . '/lib/private/Mail/Attachment.php',
'OC\\Mail\\EMailTemplate' => __DIR__ . '/../../..' . '/lib/private/Mail/EMailTemplate.php',
'OC\\Mail\\Mailer' => __DIR__ . '/../../..' . '/lib/private/Mail/Mailer.php',
@@ -791,6 +878,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\PreviewManager' => __DIR__ . '/../../..' . '/lib/private/PreviewManager.php',
'OC\\PreviewNotAvailableException' => __DIR__ . '/../../..' . '/lib/private/PreviewNotAvailableException.php',
'OC\\Preview\\BMP' => __DIR__ . '/../../..' . '/lib/private/Preview/BMP.php',
+ 'OC\\Preview\\BackgroundCleanupJob' => __DIR__ . '/../../..' . '/lib/private/Preview/BackgroundCleanupJob.php',
'OC\\Preview\\Bitmap' => __DIR__ . '/../../..' . '/lib/private/Preview/Bitmap.php',
'OC\\Preview\\Font' => __DIR__ . '/../../..' . '/lib/private/Preview/Font.php',
'OC\\Preview\\GIF' => __DIR__ . '/../../..' . '/lib/private/Preview/GIF.php',
@@ -831,6 +919,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Remote\\User' => __DIR__ . '/../../..' . '/lib/private/Remote/User.php',
'OC\\Repair' => __DIR__ . '/../../..' . '/lib/private/Repair.php',
'OC\\RepairException' => __DIR__ . '/../../..' . '/lib/private/RepairException.php',
+ 'OC\\Repair\\AddCleanupUpdaterBackupsJob' => __DIR__ . '/../../..' . '/lib/private/Repair/AddCleanupUpdaterBackupsJob.php',
'OC\\Repair\\CleanTags' => __DIR__ . '/../../..' . '/lib/private/Repair/CleanTags.php',
'OC\\Repair\\ClearFrontendCaches' => __DIR__ . '/../../..' . '/lib/private/Repair/ClearFrontendCaches.php',
'OC\\Repair\\Collation' => __DIR__ . '/../../..' . '/lib/private/Repair/Collation.php',
@@ -838,6 +927,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Repair\\NC11\\FixMountStorages' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/FixMountStorages.php',
'OC\\Repair\\NC13\\AddLogRotateJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC13/AddLogRotateJob.php',
'OC\\Repair\\NC13\\RepairInvalidPaths' => __DIR__ . '/../../..' . '/lib/private/Repair/NC13/RepairInvalidPaths.php',
+ 'OC\\Repair\\NC14\\AddPreviewBackgroundCleanupJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php',
+ 'OC\\Repair\\NC14\\RepairPendingCronJobs' => __DIR__ . '/../../..' . '/lib/private/Repair/NC14/RepairPendingCronJobs.php',
'OC\\Repair\\OldGroupMembershipShares' => __DIR__ . '/../../..' . '/lib/private/Repair/OldGroupMembershipShares.php',
'OC\\Repair\\Owncloud\\DropAccountTermsTable' => __DIR__ . '/../../..' . '/lib/private/Repair/Owncloud/DropAccountTermsTable.php',
'OC\\Repair\\Owncloud\\SaveAccountsTableData' => __DIR__ . '/../../..' . '/lib/private/Repair/Owncloud/SaveAccountsTableData.php',
@@ -893,12 +984,11 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Settings\\Activity\\SecurityProvider' => __DIR__ . '/../../..' . '/settings/Activity/SecurityProvider.php',
'OC\\Settings\\Activity\\SecuritySetting' => __DIR__ . '/../../..' . '/settings/Activity/SecuritySetting.php',
'OC\\Settings\\Activity\\Setting' => __DIR__ . '/../../..' . '/settings/Activity/Setting.php',
- 'OC\\Settings\\Admin\\Additional' => __DIR__ . '/../../..' . '/lib/private/Settings/Admin/Additional.php',
'OC\\Settings\\Admin\\Encryption' => __DIR__ . '/../../..' . '/lib/private/Settings/Admin/Encryption.php',
+ 'OC\\Settings\\Admin\\Mail' => __DIR__ . '/../../..' . '/lib/private/Settings/Admin/Mail.php',
+ 'OC\\Settings\\Admin\\Overview' => __DIR__ . '/../../..' . '/lib/private/Settings/Admin/Overview.php',
'OC\\Settings\\Admin\\Server' => __DIR__ . '/../../..' . '/lib/private/Settings/Admin/Server.php',
- 'OC\\Settings\\Admin\\ServerDevNotice' => __DIR__ . '/../../..' . '/lib/private/Settings/Admin/ServerDevNotice.php',
'OC\\Settings\\Admin\\Sharing' => __DIR__ . '/../../..' . '/lib/private/Settings/Admin/Sharing.php',
- 'OC\\Settings\\Admin\\TipsTricks' => __DIR__ . '/../../..' . '/lib/private/Settings/Admin/TipsTricks.php',
'OC\\Settings\\Application' => __DIR__ . '/../../..' . '/settings/Application.php',
'OC\\Settings\\BackgroundJobs\\VerifyUserData' => __DIR__ . '/../../..' . '/settings/BackgroundJobs/VerifyUserData.php',
'OC\\Settings\\Controller\\AdminSettingsController' => __DIR__ . '/../../..' . '/settings/Controller/AdminSettingsController.php',
@@ -908,12 +998,9 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Settings\\Controller\\ChangePasswordController' => __DIR__ . '/../../..' . '/settings/Controller/ChangePasswordController.php',
'OC\\Settings\\Controller\\CheckSetupController' => __DIR__ . '/../../..' . '/settings/Controller/CheckSetupController.php',
'OC\\Settings\\Controller\\CommonSettingsTrait' => __DIR__ . '/../../..' . '/settings/Controller/CommonSettingsTrait.php',
- 'OC\\Settings\\Controller\\EncryptionController' => __DIR__ . '/../../..' . '/settings/Controller/EncryptionController.php',
- 'OC\\Settings\\Controller\\GroupsController' => __DIR__ . '/../../..' . '/settings/Controller/GroupsController.php',
'OC\\Settings\\Controller\\LogSettingsController' => __DIR__ . '/../../..' . '/settings/Controller/LogSettingsController.php',
'OC\\Settings\\Controller\\MailSettingsController' => __DIR__ . '/../../..' . '/settings/Controller/MailSettingsController.php',
'OC\\Settings\\Controller\\PersonalSettingsController' => __DIR__ . '/../../..' . '/settings/Controller/PersonalSettingsController.php',
- 'OC\\Settings\\Controller\\SecuritySettingsController' => __DIR__ . '/../../..' . '/settings/Controller/SecuritySettingsController.php',
'OC\\Settings\\Controller\\UsersController' => __DIR__ . '/../../..' . '/settings/Controller/UsersController.php',
'OC\\Settings\\Hooks' => __DIR__ . '/../../..' . '/settings/Hooks.php',
'OC\\Settings\\Mailer\\NewUserMailHelper' => __DIR__ . '/../../..' . '/settings/Mailer/NewUserMailHelper.php',
@@ -922,6 +1009,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Settings\\Personal\\Additional' => __DIR__ . '/../../..' . '/lib/private/Settings/Personal/Additional.php',
'OC\\Settings\\Personal\\PersonalInfo' => __DIR__ . '/../../..' . '/lib/private/Settings/Personal/PersonalInfo.php',
'OC\\Settings\\Personal\\Security' => __DIR__ . '/../../..' . '/lib/private/Settings/Personal/Security.php',
+ 'OC\\Settings\\Personal\\ServerDevNotice' => __DIR__ . '/../../..' . '/lib/private/Settings/Personal/ServerDevNotice.php',
'OC\\Settings\\Section' => __DIR__ . '/../../..' . '/lib/private/Settings/Section.php',
'OC\\Setup' => __DIR__ . '/../../..' . '/lib/private/Setup.php',
'OC\\Setup\\AbstractDatabase' => __DIR__ . '/../../..' . '/lib/private/Setup/AbstractDatabase.php',
@@ -959,6 +1047,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\TemplateLayout' => __DIR__ . '/../../..' . '/lib/private/TemplateLayout.php',
'OC\\Template\\Base' => __DIR__ . '/../../..' . '/lib/private/Template/Base.php',
'OC\\Template\\CSSResourceLocator' => __DIR__ . '/../../..' . '/lib/private/Template/CSSResourceLocator.php',
+ 'OC\\Template\\IconsCacher' => __DIR__ . '/../../..' . '/lib/private/Template/IconsCacher.php',
'OC\\Template\\JSCombiner' => __DIR__ . '/../../..' . '/lib/private/Template/JSCombiner.php',
'OC\\Template\\JSConfigHelper' => __DIR__ . '/../../..' . '/lib/private/Template/JSConfigHelper.php',
'OC\\Template\\JSResourceLocator' => __DIR__ . '/../../..' . '/lib/private/Template/JSResourceLocator.php',
@@ -968,6 +1057,9 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Template\\TemplateFileLocator' => __DIR__ . '/../../..' . '/lib/private/Template/TemplateFileLocator.php',
'OC\\URLGenerator' => __DIR__ . '/../../..' . '/lib/private/URLGenerator.php',
'OC\\Updater' => __DIR__ . '/../../..' . '/lib/private/Updater.php',
+ 'OC\\Updater\\ChangesCheck' => __DIR__ . '/../../..' . '/lib/private/Updater/ChangesCheck.php',
+ 'OC\\Updater\\ChangesMapper' => __DIR__ . '/../../..' . '/lib/private/Updater/ChangesMapper.php',
+ 'OC\\Updater\\ChangesResult' => __DIR__ . '/../../..' . '/lib/private/Updater/ChangesResult.php',
'OC\\Updater\\VersionCheck' => __DIR__ . '/../../..' . '/lib/private/Updater/VersionCheck.php',
'OC\\User\\Backend' => __DIR__ . '/../../..' . '/lib/private/User/Backend.php',
'OC\\User\\Database' => __DIR__ . '/../../..' . '/lib/private/User/Database.php',
diff --git a/lib/l10n/ar.js b/lib/l10n/ar.js
new file mode 100644
index 00000000000..09a34082aa0
--- /dev/null
+++ b/lib/l10n/ar.js
@@ -0,0 +1,142 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "الكتابة في مجلد \"config\" غير ممكنة!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "يمكن حل هذا عادة بإعطاء خادم الوب صلاحية الكتابة في مجلد config",
+ "See %s" : "أنظر %s",
+ "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "يمكن إصلاح هذا الخطا بإعطاء مخدّم الموقع صلاحيات التعديل على مجلد الإعدادات. أنظر %s",
+ "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "لم يتم تبديل ملفات التطبيق %$1s بشكل صحيح. تأكد بأن إصدار التطبيق متوافق مع المخدّم.",
+ "Sample configuration detected" : "تم اكتشاف إعدادات عيّنة",
+ "%1$s and %2$s" : "%1$s و %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s، %2$s و %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s، %2$s، %3$s و %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s، %2$s، %3$s، %4$s و %5$s",
+ "Education Edition" : "الإصدار التعليمي",
+ "Enterprise bundle" : "حزمة المؤسسة",
+ "PHP %s or higher is required." : "إصدار PHP %s أو أحدث منه مطلوب.",
+ "PHP with a version lower than %s is required." : "PHP الإصدار %s أو أقل مطلوب.",
+ "%sbit or higher PHP required." : "مكتبات PHP ذات %s بت أو أعلى مطلوبة.",
+ "Following databases are supported: %s" : "قواعد البيانات التالية مدعومة: %s",
+ "The command line tool %s could not be found" : "لم يتم العثور على أداة سطر الأوامر %s",
+ "The library %s is not available." : "مكتبة %s غير متوفرة.",
+ "Unknown filetype" : "نوع الملف غير معروف",
+ "Invalid image" : "الصورة غير صالحة",
+ "Avatar image is not square" : "الصورة الرمزية ليست على شكل مربّع",
+ "today" : "اليوم",
+ "tomorrow" : "غدًا",
+ "yesterday" : "يوم أمس",
+ "_%n day ago_::_%n days ago_" : ["قبل ساعات","قبل يوم","قبل يومين","قبل %n يوماً","قبل %n يوماً","قبل %n يوماً"],
+ "next month" : "الشهر القادم",
+ "last month" : "الشهر الماضي",
+ "_%n month ago_::_%n months ago_" : ["قبل عدة أيام","قبل شهر","قبل شهرين","قبل %n شهراً","قبل %n شهراً","قبل %n شهراً"],
+ "next year" : "العام القادم",
+ "last year" : "السنةالماضية",
+ "in a few seconds" : "خلال بضع ثواني",
+ "seconds ago" : "منذ ثواني",
+ "File name is a reserved word" : "اسم الملف كلمة محجوزة",
+ "File name contains at least one invalid character" : "اسم الملف به ، على الأقل ، حرف غير صالح",
+ "File name is too long" : "اسم الملف طويل جداً",
+ "Empty filename is not allowed" : "لا يسمح بأسماء فارغة للملفات",
+ "__language_name__" : "اللغة العربية",
+ "Help" : "المساعدة",
+ "Apps" : "التطبيقات",
+ "Settings" : "الإعدادات",
+ "Log out" : "الخروج",
+ "Users" : "المستخدمين",
+ "Unknown user" : "المستخدم غير معروف",
+ "Basic settings" : "الإعدادات الأساسية",
+ "Sharing" : "المشاركة",
+ "Security" : "الأمان",
+ "Encryption" : "التعمية",
+ "Additional settings" : "الإعدادات المتقدمة",
+ "Personal info" : "المعلومات الشخصية",
+ "Unlimited" : "غير محدود",
+ "Verifying" : "التحقق",
+ "Verifying …" : "عملية التحقق جارية …",
+ "Verify" : "التحقق",
+ "%s enter the database username and name." : "%s أدخِل اسم قاعدة البيانات واسم مستخدمها.",
+ "%s enter the database username." : "%s ادخل اسم المستخدم الخاص بقاعدة البيانات.",
+ "%s enter the database name." : "%s ادخل اسم فاعدة البيانات",
+ "%s you may not use dots in the database name" : "%s لا يسمح لك باستخدام نقطه (.) في اسم قاعدة البيانات",
+ "Oracle connection could not be established" : "لم تنجح محاولة اتصال Oracle",
+ "Oracle username and/or password not valid" : "اسم المستخدم و/أو كلمة المرور لنظام Oracle غير صحيح",
+ "PostgreSQL username and/or password not valid" : "اسم المستخدم / أو كلمة المرور الخاصة بـPostgreSQL غير صحيحة",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "نظام ماك الإصدار X غير مدعوم و %s لن يعمل بشكل صحيح على هذه المنصة. استخدمه على مسؤوليتك!",
+ "For the best results, please consider using a GNU/Linux server instead." : "فضلاً ضع في الاعتبار استخدام نظام GNU/Linux بدل الأنظمة الأخرى للحصول على أفضل النتائج.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "فضلاً إحذف إعداد open_basedir من ملف php.ini لديك أو حوّل إلى PHP إصدار 64 بت.",
+ "Set an admin username." : "اعداد اسم مستخدم للمدير",
+ "Set an admin password." : "اعداد كلمة مرور للمدير",
+ "Can't create or write into the data directory %s" : "لا يمكن الإنشاء أو الكتابة في مجلد البيانات %s",
+ "Invalid Federated Cloud ID" : "معرّف سحابة الاتحاد غير صالح",
+ "Sharing %s failed, because the file does not exist" : "فشلت مشاركة %s فالملف غير موجود",
+ "You are not allowed to share %s" : "أنت غير مسموح لك أن تشارك %s",
+ "Sharing %s failed, because you can not share with yourself" : "فشلت مشاركة %s لأنك لايمكنك المشاركة مع نفسك",
+ "Sharing %s failed, because the user %s does not exist" : "فشلت مشاركة %s لأن المستخدم %s غير موجود",
+ "Share type %s is not valid for %s" : "مشاركة النوع %s غير صالحة لـ %s",
+ "%s shared »%s« with you" : "%s شارك »%s« معك",
+ "Click the button below to open it." : "أنقر على الزر أدناه لفتحه.",
+ "%s via %s" : "%s عبر %s",
+ "Could not find category \"%s\"" : "تعذر العثور على المجلد \"%s\"",
+ "Sunday" : "الأحد",
+ "Monday" : "الإثنين",
+ "Tuesday" : "الثلاثاء",
+ "Wednesday" : "الأربعاء",
+ "Thursday" : "الخميس",
+ "Friday" : "الجمعة",
+ "Saturday" : "السبت",
+ "Sun." : "أح.",
+ "Mon." : "إث.",
+ "Tue." : "ثلا.",
+ "Wed." : "أر.",
+ "Thu." : "خم.",
+ "Fri." : "جم.",
+ "Sat." : "سب.",
+ "Su" : "أح",
+ "Mo" : "إث",
+ "Tu" : "ثلا",
+ "We" : "أر",
+ "Th" : "خم",
+ "Fr" : "جم",
+ "Sa" : "سب",
+ "January" : "جانفي",
+ "February" : "فيفري",
+ "March" : "مارس",
+ "April" : "أفريل",
+ "May" : "ماي",
+ "June" : "جوان",
+ "July" : "جويلية",
+ "August" : "أوت",
+ "September" : "سبتمبر",
+ "October" : "أكتوبر",
+ "November" : "نوفمبر",
+ "December" : "ديسمبر",
+ "Jan." : "جان.",
+ "Feb." : "فيف.",
+ "Mar." : "مار.",
+ "Apr." : "أفر.",
+ "May." : "ماي",
+ "Jun." : "جوا.",
+ "Jul." : "جوي.",
+ "Aug." : "أوت",
+ "Sep." : "سبت.",
+ "Oct." : "أكت.",
+ "Nov." : "نوف.",
+ "Dec." : "ديس.",
+ "A valid username must be provided" : "يجب ادخال اسم مستخدم صحيح",
+ "Username contains whitespace at the beginning or at the end" : "إنّ إسم المستخدم يحتوي على مسافة بيضاء سواءا في البداية أو النهاية",
+ "A valid password must be provided" : "يجب ادخال كلمة مرور صحيحة",
+ "Could not create user" : "لا يمكن إنشاء المستخدم",
+ "User disabled" : "المستخدم معطّل",
+ "Login canceled by app" : "تم إلغاء الدخول مِن طرف التطبيق",
+ "a safe home for all your data" : "المكان الآمن لجميع بياناتك",
+ "File is currently busy, please try again later" : "إنّ الملف مشغول الآمن، يرجى إعادة المحاولة لاحقًا",
+ "Can't read file" : "لا يمكن قراءة الملف",
+ "Application is not enabled" : "التطبيق غير مفعّل",
+ "Authentication error" : "لم يتم التأكد من الشخصية بنجاح",
+ "Token expired. Please reload page." : "انتهت صلاحية الكلمة , يرجى اعادة تحميل الصفحة",
+ "Personal" : "الحساب الشخصي",
+ "Admin" : "المدير",
+ "Tips & tricks" : "نصائح و تلميحات",
+ "Sync clients" : "مزامنة العملاء"
+},
+"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;");
diff --git a/lib/l10n/ar.json b/lib/l10n/ar.json
new file mode 100644
index 00000000000..cfbf9675988
--- /dev/null
+++ b/lib/l10n/ar.json
@@ -0,0 +1,140 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "الكتابة في مجلد \"config\" غير ممكنة!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "يمكن حل هذا عادة بإعطاء خادم الوب صلاحية الكتابة في مجلد config",
+ "See %s" : "أنظر %s",
+ "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "يمكن إصلاح هذا الخطا بإعطاء مخدّم الموقع صلاحيات التعديل على مجلد الإعدادات. أنظر %s",
+ "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "لم يتم تبديل ملفات التطبيق %$1s بشكل صحيح. تأكد بأن إصدار التطبيق متوافق مع المخدّم.",
+ "Sample configuration detected" : "تم اكتشاف إعدادات عيّنة",
+ "%1$s and %2$s" : "%1$s و %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s، %2$s و %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s، %2$s، %3$s و %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s، %2$s، %3$s، %4$s و %5$s",
+ "Education Edition" : "الإصدار التعليمي",
+ "Enterprise bundle" : "حزمة المؤسسة",
+ "PHP %s or higher is required." : "إصدار PHP %s أو أحدث منه مطلوب.",
+ "PHP with a version lower than %s is required." : "PHP الإصدار %s أو أقل مطلوب.",
+ "%sbit or higher PHP required." : "مكتبات PHP ذات %s بت أو أعلى مطلوبة.",
+ "Following databases are supported: %s" : "قواعد البيانات التالية مدعومة: %s",
+ "The command line tool %s could not be found" : "لم يتم العثور على أداة سطر الأوامر %s",
+ "The library %s is not available." : "مكتبة %s غير متوفرة.",
+ "Unknown filetype" : "نوع الملف غير معروف",
+ "Invalid image" : "الصورة غير صالحة",
+ "Avatar image is not square" : "الصورة الرمزية ليست على شكل مربّع",
+ "today" : "اليوم",
+ "tomorrow" : "غدًا",
+ "yesterday" : "يوم أمس",
+ "_%n day ago_::_%n days ago_" : ["قبل ساعات","قبل يوم","قبل يومين","قبل %n يوماً","قبل %n يوماً","قبل %n يوماً"],
+ "next month" : "الشهر القادم",
+ "last month" : "الشهر الماضي",
+ "_%n month ago_::_%n months ago_" : ["قبل عدة أيام","قبل شهر","قبل شهرين","قبل %n شهراً","قبل %n شهراً","قبل %n شهراً"],
+ "next year" : "العام القادم",
+ "last year" : "السنةالماضية",
+ "in a few seconds" : "خلال بضع ثواني",
+ "seconds ago" : "منذ ثواني",
+ "File name is a reserved word" : "اسم الملف كلمة محجوزة",
+ "File name contains at least one invalid character" : "اسم الملف به ، على الأقل ، حرف غير صالح",
+ "File name is too long" : "اسم الملف طويل جداً",
+ "Empty filename is not allowed" : "لا يسمح بأسماء فارغة للملفات",
+ "__language_name__" : "اللغة العربية",
+ "Help" : "المساعدة",
+ "Apps" : "التطبيقات",
+ "Settings" : "الإعدادات",
+ "Log out" : "الخروج",
+ "Users" : "المستخدمين",
+ "Unknown user" : "المستخدم غير معروف",
+ "Basic settings" : "الإعدادات الأساسية",
+ "Sharing" : "المشاركة",
+ "Security" : "الأمان",
+ "Encryption" : "التعمية",
+ "Additional settings" : "الإعدادات المتقدمة",
+ "Personal info" : "المعلومات الشخصية",
+ "Unlimited" : "غير محدود",
+ "Verifying" : "التحقق",
+ "Verifying …" : "عملية التحقق جارية …",
+ "Verify" : "التحقق",
+ "%s enter the database username and name." : "%s أدخِل اسم قاعدة البيانات واسم مستخدمها.",
+ "%s enter the database username." : "%s ادخل اسم المستخدم الخاص بقاعدة البيانات.",
+ "%s enter the database name." : "%s ادخل اسم فاعدة البيانات",
+ "%s you may not use dots in the database name" : "%s لا يسمح لك باستخدام نقطه (.) في اسم قاعدة البيانات",
+ "Oracle connection could not be established" : "لم تنجح محاولة اتصال Oracle",
+ "Oracle username and/or password not valid" : "اسم المستخدم و/أو كلمة المرور لنظام Oracle غير صحيح",
+ "PostgreSQL username and/or password not valid" : "اسم المستخدم / أو كلمة المرور الخاصة بـPostgreSQL غير صحيحة",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "نظام ماك الإصدار X غير مدعوم و %s لن يعمل بشكل صحيح على هذه المنصة. استخدمه على مسؤوليتك!",
+ "For the best results, please consider using a GNU/Linux server instead." : "فضلاً ضع في الاعتبار استخدام نظام GNU/Linux بدل الأنظمة الأخرى للحصول على أفضل النتائج.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "فضلاً إحذف إعداد open_basedir من ملف php.ini لديك أو حوّل إلى PHP إصدار 64 بت.",
+ "Set an admin username." : "اعداد اسم مستخدم للمدير",
+ "Set an admin password." : "اعداد كلمة مرور للمدير",
+ "Can't create or write into the data directory %s" : "لا يمكن الإنشاء أو الكتابة في مجلد البيانات %s",
+ "Invalid Federated Cloud ID" : "معرّف سحابة الاتحاد غير صالح",
+ "Sharing %s failed, because the file does not exist" : "فشلت مشاركة %s فالملف غير موجود",
+ "You are not allowed to share %s" : "أنت غير مسموح لك أن تشارك %s",
+ "Sharing %s failed, because you can not share with yourself" : "فشلت مشاركة %s لأنك لايمكنك المشاركة مع نفسك",
+ "Sharing %s failed, because the user %s does not exist" : "فشلت مشاركة %s لأن المستخدم %s غير موجود",
+ "Share type %s is not valid for %s" : "مشاركة النوع %s غير صالحة لـ %s",
+ "%s shared »%s« with you" : "%s شارك »%s« معك",
+ "Click the button below to open it." : "أنقر على الزر أدناه لفتحه.",
+ "%s via %s" : "%s عبر %s",
+ "Could not find category \"%s\"" : "تعذر العثور على المجلد \"%s\"",
+ "Sunday" : "الأحد",
+ "Monday" : "الإثنين",
+ "Tuesday" : "الثلاثاء",
+ "Wednesday" : "الأربعاء",
+ "Thursday" : "الخميس",
+ "Friday" : "الجمعة",
+ "Saturday" : "السبت",
+ "Sun." : "أح.",
+ "Mon." : "إث.",
+ "Tue." : "ثلا.",
+ "Wed." : "أر.",
+ "Thu." : "خم.",
+ "Fri." : "جم.",
+ "Sat." : "سب.",
+ "Su" : "أح",
+ "Mo" : "إث",
+ "Tu" : "ثلا",
+ "We" : "أر",
+ "Th" : "خم",
+ "Fr" : "جم",
+ "Sa" : "سب",
+ "January" : "جانفي",
+ "February" : "فيفري",
+ "March" : "مارس",
+ "April" : "أفريل",
+ "May" : "ماي",
+ "June" : "جوان",
+ "July" : "جويلية",
+ "August" : "أوت",
+ "September" : "سبتمبر",
+ "October" : "أكتوبر",
+ "November" : "نوفمبر",
+ "December" : "ديسمبر",
+ "Jan." : "جان.",
+ "Feb." : "فيف.",
+ "Mar." : "مار.",
+ "Apr." : "أفر.",
+ "May." : "ماي",
+ "Jun." : "جوا.",
+ "Jul." : "جوي.",
+ "Aug." : "أوت",
+ "Sep." : "سبت.",
+ "Oct." : "أكت.",
+ "Nov." : "نوف.",
+ "Dec." : "ديس.",
+ "A valid username must be provided" : "يجب ادخال اسم مستخدم صحيح",
+ "Username contains whitespace at the beginning or at the end" : "إنّ إسم المستخدم يحتوي على مسافة بيضاء سواءا في البداية أو النهاية",
+ "A valid password must be provided" : "يجب ادخال كلمة مرور صحيحة",
+ "Could not create user" : "لا يمكن إنشاء المستخدم",
+ "User disabled" : "المستخدم معطّل",
+ "Login canceled by app" : "تم إلغاء الدخول مِن طرف التطبيق",
+ "a safe home for all your data" : "المكان الآمن لجميع بياناتك",
+ "File is currently busy, please try again later" : "إنّ الملف مشغول الآمن، يرجى إعادة المحاولة لاحقًا",
+ "Can't read file" : "لا يمكن قراءة الملف",
+ "Application is not enabled" : "التطبيق غير مفعّل",
+ "Authentication error" : "لم يتم التأكد من الشخصية بنجاح",
+ "Token expired. Please reload page." : "انتهت صلاحية الكلمة , يرجى اعادة تحميل الصفحة",
+ "Personal" : "الحساب الشخصي",
+ "Admin" : "المدير",
+ "Tips & tricks" : "نصائح و تلميحات",
+ "Sync clients" : "مزامنة العملاء"
+},"pluralForm" :"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;"
+} \ No newline at end of file
diff --git a/lib/l10n/ast.js b/lib/l10n/ast.js
new file mode 100644
index 00000000000..4518070496b
--- /dev/null
+++ b/lib/l10n/ast.js
@@ -0,0 +1,177 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "¡Nun pue escribise nel direutoriu «config»!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Davezu esto pue iguase dándo-y al sirvidor web accesu d'escritura al direutoriu de configuración",
+ "See %s" : "Mira %s",
+ "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Esto davezu íguase dando'l permisu d'escritura nel direutoriu de configuración al sirvidor web. Mira %s",
+ "Sample configuration detected" : "Configuración d'amuesa detectada",
+ "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" : "Detectose que la configuración d'amuesa copiose. Esto pue encaboxar la instalación y dexala ensín soporte. Llee la documentación enantes de facer cambéos 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",
+ "Education Edition" : "Edición educativa",
+ "Enterprise bundle" : "Llote empresarial",
+ "Social sharing bundle" : "Llote de compartición social",
+ "PHP %s or higher is required." : "Necesítase PHP %s o superior",
+ "PHP with a version lower than %s is required." : "Necesítase una versión PHP anterior a %s",
+ "%sbit or higher PHP required." : "Necesítase PHP %sbit o superior",
+ "Following databases are supported: %s" : "Les siguientes bases de datos tan sofitaes: %s",
+ "The command line tool %s could not be found" : "La ferramienta línea de comandu %s nun pudo alcontrase",
+ "The library %s is not available." : "La librería %s nun ta disponible",
+ "Library %s with a version higher than %s is required - available version %s." : "Necesítase una librería %s con ua versión superior a %s - versión disponible %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "Necesítase una librería %s con una versión anterior a %s - versión disponible %s.",
+ "Following platforms are supported: %s" : "Les siguientes plataformes tan sofitaes: %s",
+ "Unknown filetype" : "Triba de ficheru desconocida",
+ "Invalid image" : "Imaxe inválida",
+ "Avatar image is not square" : "La imaxe del avatar nun ye cuadrada",
+ "today" : "güei",
+ "tomorrow" : "mañana",
+ "yesterday" : "ayeri",
+ "_%n day ago_::_%n days ago_" : ["hai %n día","hai %n díes"],
+ "last month" : "mes caberu",
+ "_%n month ago_::_%n months ago_" : ["hai %n mes","hai %n meses"],
+ "last year" : "añu caberu",
+ "_%n year ago_::_%n years ago_" : ["hai %n añu","hai %n años"],
+ "_%n hour ago_::_%n hours ago_" : ["hai %n hora","hai %n hores"],
+ "_%n minute ago_::_%n minutes ago_" : ["hai %n minutu","hai %n minutos"],
+ "seconds ago" : "hai segundos",
+ "File name is a reserved word" : "El nome de ficheru ye una pallabra reservada",
+ "File name contains at least one invalid character" : "El nome del ficheru contién polo menos un carácter non válidu",
+ "File name is too long" : "El nome de ficheru ye demasiáu llargu",
+ "Empty filename is not allowed" : "Nun s'almite un nome de ficheru baleru",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "L'aplicación \"%s\" nun puede instalase porque nun se llee'l ficheru appinfo.",
+ "__language_name__" : "Asturianu",
+ "Help" : "Ayuda",
+ "Apps" : "Aplicaciones",
+ "Log out" : "Zarrar sesión",
+ "Users" : "Usuarios",
+ "Unknown user" : "Usuariu desconocíu",
+ "Basic settings" : "Axustes básicos",
+ "Security" : "Seguranza",
+ "Encryption" : "Cifráu",
+ "Additional settings" : "Axustes adicionales",
+ "%s enter the database username and name." : "%s introducir el nome d'usuariu y el nome de la base de datos .",
+ "%s enter the database username." : "%s introducir l'usuariu de la base de datos.",
+ "%s enter the database name." : "%s introducir nome de la base de datos.",
+ "%s you may not use dots in the database name" : "%s nun pues usar puntos nel nome de la base de datos",
+ "Oracle connection could not be established" : "Nun pudo afitase la conexón d'Oracle",
+ "Oracle username and/or password not valid" : "Nome d'usuariu o contraseña d'Oracle non válidos",
+ "PostgreSQL username and/or password not valid" : "Nome d'usuariu o contraseña PostgreSQL non válidos",
+ "You need to enter details of an existing account." : "Precises introducir los detalles d'una cuenta esistente.",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nun ta sofitáu y %s nun furrulará afayadizamente nesta plataforma. ¡Úsalu baxo'l to riesgu!",
+ "For the best results, please consider using a GNU/Linux server instead." : "Pa los meyores resultaos, por favor considera l'usu d'un sirvidor GNU/Linux nel so llugar.",
+ "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." : "Paez ser que la instancia %s ta executándose nun entornu de PHP 32 bits y el open_basedir configuróse en php.ini. Esto va dar llugar a problemes colos ficheros de más de 4 GB y nun ye nada recomendable.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor, desanicia la configuración open_basedir dientro la so php.ini o camude a PHP 64 bits.",
+ "Set an admin username." : "Afitar nome d'usuariu p'almin",
+ "Set an admin password." : "Afitar contraseña p'almin",
+ "Can't create or write into the data directory %s" : "Nun pue crease o escribir dientro los datos del direutoriu %s",
+ "Invalid Federated Cloud ID" : "ID non válida de ñube federada",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "Compartir %s falló, por cuenta qu'el backend nun dexa acciones de tipu %i",
+ "Sharing %s failed, because the file does not exist" : "Compartir %s falló, porque'l ficheru nun esiste",
+ "You are not allowed to share %s" : "Nun tienes permisu pa compartir %s",
+ "Sharing %s failed, because you can not share with yourself" : "Compartir %s falló, porque nun puede compartise contigo mesmu",
+ "Sharing %s failed, because the user %s does not exist" : "Compartir %s falló, yá que l'usuariu %s nun esiste",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Compartir %s falló, yá que l'usuariu %s nun ye miembru de nengún de los grupos de los que ye miembru %s",
+ "Sharing %s failed, because this item is already shared with %s" : "Compartir %s falló, porque esti elementu yá ta compartiéndose con %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "Compartir %s falló, porque esti elementu yá ta compartiéndose col usuariu %s",
+ "Sharing %s failed, because the group %s does not exist" : "Compartir %s falló, porque'l grupu %s nun esiste",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Compartir %s falló, porque %s nun ye miembru del grupu %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Necesites apurrir una contraseña pa crear un enllaz públicu, namái tan permitíos los enllaces protexíos",
+ "Sharing %s failed, because sharing with links is not allowed" : "Compartir %s falló, porque nun se permite compartir con enllaces",
+ "Not allowed to create a federated share with the same user" : "Nun s'almite crear un recursu compartíu federáu col mesmu usuariu",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Compartir %s falló, nun pudo atopase %s, pue qu'el servidor nun seya anguaño algamable.",
+ "Share type %s is not valid for %s" : "La triba de compartición %s nun ye válida pa %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Nun pue afitase la data de caducidá. Ficheros compartíos nun puen caducar dempués de %s de compartise",
+ "Cannot set expiration date. Expiration date is in the past" : "Nun pue afitase la data d'espiración. La data d'espiración ta nel pasáu",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El motor compartíu %s tien d'implementar la interfaz OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Nun s'alcontró'l botón de compartición %s",
+ "Sharing backend for %s not found" : "Nun s'alcontró'l botón de partición pa %s",
+ "Sharing failed, because the user %s is the original sharer" : "Compartir falló, porque l'usuariu %s ye'l compartidor orixinal",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Compartir %s falló, porque los permisos perpasen los otorgaos a %s",
+ "Sharing %s failed, because resharing is not allowed" : "Compartir %s falló, porque nun se permite la re-compartición",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Compartir %s falló porque'l motor compartíu pa %s podría nun atopar el so orixe",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Compartir %s falló, yá que'l ficheru nun pudo atopase na caché de ficheru",
+ "Can’t increase permissions of %s" : "Nun pue aumentase los permisos de %s",
+ "Files can’t be shared with delete permissions" : "Los ficheros nun puen compartise colos permisos de desaniciu",
+ "Files can’t be shared with create permissions" : "Los ficheros nun puen compartise colos permisos de creación",
+ "Expiration date is in the past" : "La data de caducidá ta nel pasáu.",
+ "Can’t set expiration date more than %s days in the future" : "Nun pue afitase la data de caducidá más de %s díes nel futuru",
+ "%s shared »%s« with you" : "%s compartió »%s« contigo",
+ "%s via %s" : "%s via %s",
+ "Could not find category \"%s\"" : "Nun pudo alcontrase la estaya \"%s.\"",
+ "Sunday" : "Domingu",
+ "Monday" : "Llunes",
+ "Friday" : "Vienres",
+ "Saturday" : "Sábadu",
+ "Mon." : "Llu.",
+ "Sat." : "Sáb.",
+ "January" : "Xineru",
+ "February" : "Febreru",
+ "March" : "Marzu",
+ "April" : "Abril",
+ "May" : "Mayu",
+ "June" : "Xunu",
+ "July" : "Xunetu",
+ "August" : "Agostu",
+ "September" : "Setiembre",
+ "October" : "Ochobre",
+ "November" : "Payares",
+ "December" : "Avientu",
+ "Jan." : "Xin.",
+ "Feb." : "Feb.",
+ "Mar." : "Mar.",
+ "Apr." : "Abr.",
+ "May." : "May.",
+ "Jun." : "Xun.",
+ "Jul." : "Xnt.",
+ "Sep." : "Set.",
+ "Oct." : "Och.",
+ "Nov." : "Pay.",
+ "Dec." : "Avi.",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Namái tan permitíos los siguientes caráuteres nun nome d'usuariu: \"a-z\", \"A-Z\", \"0-9\", y \"_.@-'\"",
+ "A valid username must be provided" : "Tien d'apurrise un nome d'usuariu válidu",
+ "Username contains whitespace at the beginning or at the end" : "El nome d'usuario contién espacios en blancu al entamu o al final",
+ "Username must not consist of dots only" : "El nome d'usuariu nun pue tener puntos",
+ "A valid password must be provided" : "Tien d'apurrise una contraseña válida",
+ "The username is already being used" : "El nome d'usuariu yá ta usándose",
+ "User disabled" : "Usuariu desactiváu",
+ "Login canceled by app" : "Aniciar sesión canceláu pola aplicación",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "L'aplicación \"%s\" nun puede instalase porque les siguientes dependencies nun se cumplen: %s",
+ "a safe home for all your data" : "un llar seguru pa tolos tos datos",
+ "File is currently busy, please try again later" : "Fichaeru ta ocupáu, por favor intentelo de nuevu más tarde",
+ "Can't read file" : "Nun ye a lleese'l ficheru",
+ "Application is not enabled" : "L'aplicación nun ta habilitada",
+ "Authentication error" : "Fallu d'autenticación",
+ "Token expired. Please reload page." : "Token caducáu. Recarga la páxina.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Nun hai controladores de bases de datos (sqlite, mysql, o postgresql)",
+ "Cannot write into \"config\" directory" : "Nun pue escribise nel direutoriu \"config\"",
+ "Cannot write into \"apps\" directory" : "Nun pue escribise nel direutoriu \"apps\"",
+ "Cannot create \"data\" directory" : "Nun pue crease'l direutoriu «datos»",
+ "Setting locale to %s failed" : "Falló l'activación del idioma %s",
+ "Please install one of these locales on your system and restart your webserver." : "Instala ún d'estos locales nel to sistema y reanicia'l sirvidor web",
+ "Please ask your server administrator to install the module." : "Por favor, entrúga-y al to alministrador del sirvidor pa instalar el módulu.",
+ "PHP module %s not installed." : "Nun ta instaláu'l módulu PHP %s",
+ "PHP setting \"%s\" is not set to \"%s\"." : "La configuración de PHP \"%s\" nun s'afita \"%s\".",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload afita \"%s\" en llugar del valor esperáu \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Pa solucionar esti problema definíu <code>mbstring.func_overload</code>a <code>0</code> nel so php.ini",
+ "libxml2 2.7.0 is at least required. Currently %s is installed." : "libxml2 2.7.0 ríquese siquier. Anguaño ta instaláu %s.",
+ "To fix this issue update your libxml2 version and restart your web server." : "Pa solucionar esti problema actualiza latso versión de libxml2 y reanicia'l to sirvidor web.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ta aparentemente configuráu pa desaniciar bloques de documentos en llinia. Esto va facer que delles aplicaciones principales nun tean accesibles.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dablemente esto seya culpa d'un caché o acelerador, como por exemplu Zend OPcache o eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "Instaláronse los módulos PHP, ¿pero tán entá llistaos como faltantes?",
+ "Please ask your server administrator to restart the web server." : "Por favor, entruga al to alministrador pa reaniciar el sirvidor web.",
+ "PostgreSQL >= 9 required" : "PostgreSQL >= 9 requeríu",
+ "Please upgrade your database version" : "Por favor, anueva la versión de la to base de datos",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor, camuda los permisos a 0770 pa que'l direutoriu nun pueda llistase por otros usuarios.",
+ "Check the value of \"datadirectory\" in your configuration" : "Comprobar el valor del \"datadirectory\" na so configuración",
+ "Your data directory is invalid" : "El to direutoriu de datos nun ye válidu",
+ "Could not obtain lock type %d on \"%s\"." : "Nun pudo facese'l bloquéu %d en \"%s\".",
+ "Storage unauthorized. %s" : "Almacenamientu desautorizáu. %s",
+ "Storage incomplete configuration. %s" : "Configuración d'almacenamientu incompleta. %s",
+ "Storage connection error. %s" : "Fallu de conexón al almacenamientu. %s",
+ "Storage is temporarily not available" : "L'almacenamientu ta temporalmente non disponible",
+ "Storage connection timeout. %s" : "Tiempu escosao de conexón al almacenamientu. %s",
+ "APCu" : "APCu",
+ "Tips & tricks" : "Conseyos y trucos"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/ast.json b/lib/l10n/ast.json
new file mode 100644
index 00000000000..53f8b0c1312
--- /dev/null
+++ b/lib/l10n/ast.json
@@ -0,0 +1,175 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "¡Nun pue escribise nel direutoriu «config»!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Davezu esto pue iguase dándo-y al sirvidor web accesu d'escritura al direutoriu de configuración",
+ "See %s" : "Mira %s",
+ "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Esto davezu íguase dando'l permisu d'escritura nel direutoriu de configuración al sirvidor web. Mira %s",
+ "Sample configuration detected" : "Configuración d'amuesa detectada",
+ "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" : "Detectose que la configuración d'amuesa copiose. Esto pue encaboxar la instalación y dexala ensín soporte. Llee la documentación enantes de facer cambéos 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",
+ "Education Edition" : "Edición educativa",
+ "Enterprise bundle" : "Llote empresarial",
+ "Social sharing bundle" : "Llote de compartición social",
+ "PHP %s or higher is required." : "Necesítase PHP %s o superior",
+ "PHP with a version lower than %s is required." : "Necesítase una versión PHP anterior a %s",
+ "%sbit or higher PHP required." : "Necesítase PHP %sbit o superior",
+ "Following databases are supported: %s" : "Les siguientes bases de datos tan sofitaes: %s",
+ "The command line tool %s could not be found" : "La ferramienta línea de comandu %s nun pudo alcontrase",
+ "The library %s is not available." : "La librería %s nun ta disponible",
+ "Library %s with a version higher than %s is required - available version %s." : "Necesítase una librería %s con ua versión superior a %s - versión disponible %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "Necesítase una librería %s con una versión anterior a %s - versión disponible %s.",
+ "Following platforms are supported: %s" : "Les siguientes plataformes tan sofitaes: %s",
+ "Unknown filetype" : "Triba de ficheru desconocida",
+ "Invalid image" : "Imaxe inválida",
+ "Avatar image is not square" : "La imaxe del avatar nun ye cuadrada",
+ "today" : "güei",
+ "tomorrow" : "mañana",
+ "yesterday" : "ayeri",
+ "_%n day ago_::_%n days ago_" : ["hai %n día","hai %n díes"],
+ "last month" : "mes caberu",
+ "_%n month ago_::_%n months ago_" : ["hai %n mes","hai %n meses"],
+ "last year" : "añu caberu",
+ "_%n year ago_::_%n years ago_" : ["hai %n añu","hai %n años"],
+ "_%n hour ago_::_%n hours ago_" : ["hai %n hora","hai %n hores"],
+ "_%n minute ago_::_%n minutes ago_" : ["hai %n minutu","hai %n minutos"],
+ "seconds ago" : "hai segundos",
+ "File name is a reserved word" : "El nome de ficheru ye una pallabra reservada",
+ "File name contains at least one invalid character" : "El nome del ficheru contién polo menos un carácter non válidu",
+ "File name is too long" : "El nome de ficheru ye demasiáu llargu",
+ "Empty filename is not allowed" : "Nun s'almite un nome de ficheru baleru",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "L'aplicación \"%s\" nun puede instalase porque nun se llee'l ficheru appinfo.",
+ "__language_name__" : "Asturianu",
+ "Help" : "Ayuda",
+ "Apps" : "Aplicaciones",
+ "Log out" : "Zarrar sesión",
+ "Users" : "Usuarios",
+ "Unknown user" : "Usuariu desconocíu",
+ "Basic settings" : "Axustes básicos",
+ "Security" : "Seguranza",
+ "Encryption" : "Cifráu",
+ "Additional settings" : "Axustes adicionales",
+ "%s enter the database username and name." : "%s introducir el nome d'usuariu y el nome de la base de datos .",
+ "%s enter the database username." : "%s introducir l'usuariu de la base de datos.",
+ "%s enter the database name." : "%s introducir nome de la base de datos.",
+ "%s you may not use dots in the database name" : "%s nun pues usar puntos nel nome de la base de datos",
+ "Oracle connection could not be established" : "Nun pudo afitase la conexón d'Oracle",
+ "Oracle username and/or password not valid" : "Nome d'usuariu o contraseña d'Oracle non válidos",
+ "PostgreSQL username and/or password not valid" : "Nome d'usuariu o contraseña PostgreSQL non válidos",
+ "You need to enter details of an existing account." : "Precises introducir los detalles d'una cuenta esistente.",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nun ta sofitáu y %s nun furrulará afayadizamente nesta plataforma. ¡Úsalu baxo'l to riesgu!",
+ "For the best results, please consider using a GNU/Linux server instead." : "Pa los meyores resultaos, por favor considera l'usu d'un sirvidor GNU/Linux nel so llugar.",
+ "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." : "Paez ser que la instancia %s ta executándose nun entornu de PHP 32 bits y el open_basedir configuróse en php.ini. Esto va dar llugar a problemes colos ficheros de más de 4 GB y nun ye nada recomendable.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor, desanicia la configuración open_basedir dientro la so php.ini o camude a PHP 64 bits.",
+ "Set an admin username." : "Afitar nome d'usuariu p'almin",
+ "Set an admin password." : "Afitar contraseña p'almin",
+ "Can't create or write into the data directory %s" : "Nun pue crease o escribir dientro los datos del direutoriu %s",
+ "Invalid Federated Cloud ID" : "ID non válida de ñube federada",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "Compartir %s falló, por cuenta qu'el backend nun dexa acciones de tipu %i",
+ "Sharing %s failed, because the file does not exist" : "Compartir %s falló, porque'l ficheru nun esiste",
+ "You are not allowed to share %s" : "Nun tienes permisu pa compartir %s",
+ "Sharing %s failed, because you can not share with yourself" : "Compartir %s falló, porque nun puede compartise contigo mesmu",
+ "Sharing %s failed, because the user %s does not exist" : "Compartir %s falló, yá que l'usuariu %s nun esiste",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Compartir %s falló, yá que l'usuariu %s nun ye miembru de nengún de los grupos de los que ye miembru %s",
+ "Sharing %s failed, because this item is already shared with %s" : "Compartir %s falló, porque esti elementu yá ta compartiéndose con %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "Compartir %s falló, porque esti elementu yá ta compartiéndose col usuariu %s",
+ "Sharing %s failed, because the group %s does not exist" : "Compartir %s falló, porque'l grupu %s nun esiste",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Compartir %s falló, porque %s nun ye miembru del grupu %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Necesites apurrir una contraseña pa crear un enllaz públicu, namái tan permitíos los enllaces protexíos",
+ "Sharing %s failed, because sharing with links is not allowed" : "Compartir %s falló, porque nun se permite compartir con enllaces",
+ "Not allowed to create a federated share with the same user" : "Nun s'almite crear un recursu compartíu federáu col mesmu usuariu",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Compartir %s falló, nun pudo atopase %s, pue qu'el servidor nun seya anguaño algamable.",
+ "Share type %s is not valid for %s" : "La triba de compartición %s nun ye válida pa %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Nun pue afitase la data de caducidá. Ficheros compartíos nun puen caducar dempués de %s de compartise",
+ "Cannot set expiration date. Expiration date is in the past" : "Nun pue afitase la data d'espiración. La data d'espiración ta nel pasáu",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El motor compartíu %s tien d'implementar la interfaz OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Nun s'alcontró'l botón de compartición %s",
+ "Sharing backend for %s not found" : "Nun s'alcontró'l botón de partición pa %s",
+ "Sharing failed, because the user %s is the original sharer" : "Compartir falló, porque l'usuariu %s ye'l compartidor orixinal",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Compartir %s falló, porque los permisos perpasen los otorgaos a %s",
+ "Sharing %s failed, because resharing is not allowed" : "Compartir %s falló, porque nun se permite la re-compartición",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Compartir %s falló porque'l motor compartíu pa %s podría nun atopar el so orixe",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Compartir %s falló, yá que'l ficheru nun pudo atopase na caché de ficheru",
+ "Can’t increase permissions of %s" : "Nun pue aumentase los permisos de %s",
+ "Files can’t be shared with delete permissions" : "Los ficheros nun puen compartise colos permisos de desaniciu",
+ "Files can’t be shared with create permissions" : "Los ficheros nun puen compartise colos permisos de creación",
+ "Expiration date is in the past" : "La data de caducidá ta nel pasáu.",
+ "Can’t set expiration date more than %s days in the future" : "Nun pue afitase la data de caducidá más de %s díes nel futuru",
+ "%s shared »%s« with you" : "%s compartió »%s« contigo",
+ "%s via %s" : "%s via %s",
+ "Could not find category \"%s\"" : "Nun pudo alcontrase la estaya \"%s.\"",
+ "Sunday" : "Domingu",
+ "Monday" : "Llunes",
+ "Friday" : "Vienres",
+ "Saturday" : "Sábadu",
+ "Mon." : "Llu.",
+ "Sat." : "Sáb.",
+ "January" : "Xineru",
+ "February" : "Febreru",
+ "March" : "Marzu",
+ "April" : "Abril",
+ "May" : "Mayu",
+ "June" : "Xunu",
+ "July" : "Xunetu",
+ "August" : "Agostu",
+ "September" : "Setiembre",
+ "October" : "Ochobre",
+ "November" : "Payares",
+ "December" : "Avientu",
+ "Jan." : "Xin.",
+ "Feb." : "Feb.",
+ "Mar." : "Mar.",
+ "Apr." : "Abr.",
+ "May." : "May.",
+ "Jun." : "Xun.",
+ "Jul." : "Xnt.",
+ "Sep." : "Set.",
+ "Oct." : "Och.",
+ "Nov." : "Pay.",
+ "Dec." : "Avi.",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Namái tan permitíos los siguientes caráuteres nun nome d'usuariu: \"a-z\", \"A-Z\", \"0-9\", y \"_.@-'\"",
+ "A valid username must be provided" : "Tien d'apurrise un nome d'usuariu válidu",
+ "Username contains whitespace at the beginning or at the end" : "El nome d'usuario contién espacios en blancu al entamu o al final",
+ "Username must not consist of dots only" : "El nome d'usuariu nun pue tener puntos",
+ "A valid password must be provided" : "Tien d'apurrise una contraseña válida",
+ "The username is already being used" : "El nome d'usuariu yá ta usándose",
+ "User disabled" : "Usuariu desactiváu",
+ "Login canceled by app" : "Aniciar sesión canceláu pola aplicación",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "L'aplicación \"%s\" nun puede instalase porque les siguientes dependencies nun se cumplen: %s",
+ "a safe home for all your data" : "un llar seguru pa tolos tos datos",
+ "File is currently busy, please try again later" : "Fichaeru ta ocupáu, por favor intentelo de nuevu más tarde",
+ "Can't read file" : "Nun ye a lleese'l ficheru",
+ "Application is not enabled" : "L'aplicación nun ta habilitada",
+ "Authentication error" : "Fallu d'autenticación",
+ "Token expired. Please reload page." : "Token caducáu. Recarga la páxina.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Nun hai controladores de bases de datos (sqlite, mysql, o postgresql)",
+ "Cannot write into \"config\" directory" : "Nun pue escribise nel direutoriu \"config\"",
+ "Cannot write into \"apps\" directory" : "Nun pue escribise nel direutoriu \"apps\"",
+ "Cannot create \"data\" directory" : "Nun pue crease'l direutoriu «datos»",
+ "Setting locale to %s failed" : "Falló l'activación del idioma %s",
+ "Please install one of these locales on your system and restart your webserver." : "Instala ún d'estos locales nel to sistema y reanicia'l sirvidor web",
+ "Please ask your server administrator to install the module." : "Por favor, entrúga-y al to alministrador del sirvidor pa instalar el módulu.",
+ "PHP module %s not installed." : "Nun ta instaláu'l módulu PHP %s",
+ "PHP setting \"%s\" is not set to \"%s\"." : "La configuración de PHP \"%s\" nun s'afita \"%s\".",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload afita \"%s\" en llugar del valor esperáu \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Pa solucionar esti problema definíu <code>mbstring.func_overload</code>a <code>0</code> nel so php.ini",
+ "libxml2 2.7.0 is at least required. Currently %s is installed." : "libxml2 2.7.0 ríquese siquier. Anguaño ta instaláu %s.",
+ "To fix this issue update your libxml2 version and restart your web server." : "Pa solucionar esti problema actualiza latso versión de libxml2 y reanicia'l to sirvidor web.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ta aparentemente configuráu pa desaniciar bloques de documentos en llinia. Esto va facer que delles aplicaciones principales nun tean accesibles.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dablemente esto seya culpa d'un caché o acelerador, como por exemplu Zend OPcache o eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "Instaláronse los módulos PHP, ¿pero tán entá llistaos como faltantes?",
+ "Please ask your server administrator to restart the web server." : "Por favor, entruga al to alministrador pa reaniciar el sirvidor web.",
+ "PostgreSQL >= 9 required" : "PostgreSQL >= 9 requeríu",
+ "Please upgrade your database version" : "Por favor, anueva la versión de la to base de datos",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor, camuda los permisos a 0770 pa que'l direutoriu nun pueda llistase por otros usuarios.",
+ "Check the value of \"datadirectory\" in your configuration" : "Comprobar el valor del \"datadirectory\" na so configuración",
+ "Your data directory is invalid" : "El to direutoriu de datos nun ye válidu",
+ "Could not obtain lock type %d on \"%s\"." : "Nun pudo facese'l bloquéu %d en \"%s\".",
+ "Storage unauthorized. %s" : "Almacenamientu desautorizáu. %s",
+ "Storage incomplete configuration. %s" : "Configuración d'almacenamientu incompleta. %s",
+ "Storage connection error. %s" : "Fallu de conexón al almacenamientu. %s",
+ "Storage is temporarily not available" : "L'almacenamientu ta temporalmente non disponible",
+ "Storage connection timeout. %s" : "Tiempu escosao de conexón al almacenamientu. %s",
+ "APCu" : "APCu",
+ "Tips & tricks" : "Conseyos y trucos"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/az.js b/lib/l10n/az.js
new file mode 100644
index 00000000000..ef9db4bc61f
--- /dev/null
+++ b/lib/l10n/az.js
@@ -0,0 +1,32 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "\"configurasiya\" direktoriyasının daxilində yazmaq mümkün deyil",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Adətən tez həll etmək üçün WEB serverdə yazma yetkisi verilir",
+ "See %s" : "Bax %s",
+ "Sample configuration detected" : "Konfiqurasiya nüsxəsi təyin edildi",
+ "Unknown filetype" : "Fayl tipi bəlli deyil.",
+ "Invalid image" : "Yalnış şəkil",
+ "today" : "Bu gün",
+ "seconds ago" : "saniyələr öncə",
+ "__language_name__" : "Azərbaycan dili",
+ "Users" : "İstifadəçilər",
+ "Unknown user" : "Istifadəçi tanınmır ",
+ "%s enter the database username." : "Verilənlər bazası istifadəçi adını %s daxil et.",
+ "%s enter the database name." : "Verilənlər bazası adını %s daxil et.",
+ "Oracle connection could not be established" : "Oracle qoşulması alınmır",
+ "Oracle username and/or password not valid" : "Oracle istifadəçi adı və/ya şifrəsi düzgün deyil",
+ "Set an admin username." : "İnzibatçı istifadəçi adını təyin et.",
+ "Set an admin password." : "İnzibatçı şifrəsini təyin et.",
+ "Sharing %s failed, because the file does not exist" : "%s yayımlanmasında səhv baş verdi ona görə ki, fayl mövcud deyil.",
+ "You are not allowed to share %s" : "%s-in yayimlanmasına sizə izin verilmir",
+ "Share type %s is not valid for %s" : "Yayımlanma tipi %s etibarlı deyil %s üçün",
+ "%s shared »%s« with you" : "%s yayımlandı »%s« sizinlə",
+ "A valid username must be provided" : "Düzgün istifadəçi adı daxil edilməlidir",
+ "A valid password must be provided" : "Düzgün şifrə daxil edilməlidir",
+ "Application is not enabled" : "Proqram təminatı aktiv edilməyib",
+ "Authentication error" : "Təyinat metodikası",
+ "Token expired. Please reload page." : "Token vaxtı bitib. Xahiş olunur səhifəni yenidən yükləyəsiniz.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Bu ola bilər ki, cache/accelerator such tərəfindən cağırılıb hansi ki, Zend OPcache və eAccelerator-da olduğu kimidir."
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/az.json b/lib/l10n/az.json
new file mode 100644
index 00000000000..47ec9365727
--- /dev/null
+++ b/lib/l10n/az.json
@@ -0,0 +1,30 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "\"configurasiya\" direktoriyasının daxilində yazmaq mümkün deyil",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Adətən tez həll etmək üçün WEB serverdə yazma yetkisi verilir",
+ "See %s" : "Bax %s",
+ "Sample configuration detected" : "Konfiqurasiya nüsxəsi təyin edildi",
+ "Unknown filetype" : "Fayl tipi bəlli deyil.",
+ "Invalid image" : "Yalnış şəkil",
+ "today" : "Bu gün",
+ "seconds ago" : "saniyələr öncə",
+ "__language_name__" : "Azərbaycan dili",
+ "Users" : "İstifadəçilər",
+ "Unknown user" : "Istifadəçi tanınmır ",
+ "%s enter the database username." : "Verilənlər bazası istifadəçi adını %s daxil et.",
+ "%s enter the database name." : "Verilənlər bazası adını %s daxil et.",
+ "Oracle connection could not be established" : "Oracle qoşulması alınmır",
+ "Oracle username and/or password not valid" : "Oracle istifadəçi adı və/ya şifrəsi düzgün deyil",
+ "Set an admin username." : "İnzibatçı istifadəçi adını təyin et.",
+ "Set an admin password." : "İnzibatçı şifrəsini təyin et.",
+ "Sharing %s failed, because the file does not exist" : "%s yayımlanmasında səhv baş verdi ona görə ki, fayl mövcud deyil.",
+ "You are not allowed to share %s" : "%s-in yayimlanmasına sizə izin verilmir",
+ "Share type %s is not valid for %s" : "Yayımlanma tipi %s etibarlı deyil %s üçün",
+ "%s shared »%s« with you" : "%s yayımlandı »%s« sizinlə",
+ "A valid username must be provided" : "Düzgün istifadəçi adı daxil edilməlidir",
+ "A valid password must be provided" : "Düzgün şifrə daxil edilməlidir",
+ "Application is not enabled" : "Proqram təminatı aktiv edilməyib",
+ "Authentication error" : "Təyinat metodikası",
+ "Token expired. Please reload page." : "Token vaxtı bitib. Xahiş olunur səhifəni yenidən yükləyəsiniz.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Bu ola bilər ki, cache/accelerator such tərəfindən cağırılıb hansi ki, Zend OPcache və eAccelerator-da olduğu kimidir."
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/bg.js b/lib/l10n/bg.js
new file mode 100644
index 00000000000..18c8af414e4
--- /dev/null
+++ b/lib/l10n/bg.js
@@ -0,0 +1,149 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Неуспешен опит за запис в \"config\" папката!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Това може да бъде решено единствено като разрешиш на уеб сървъра да пише в config папката.",
+ "See %s" : "Вижте %s",
+ "Sample configuration detected" : "Открита е примерна конфигурация",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Усетено беше че примерната конфигурация е копирана. Това може да развли инсталацията ти и не се поддържа. Моля, прочети документацията преди да правиш промени на config.php",
+ "%1$s and %2$s" : "%1$s и %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s и %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s и %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s и %5$s",
+ "PHP %s or higher is required." : "Изисква се PHP %s или по-нова.",
+ "PHP with a version lower than %s is required." : "Необходим е PHP с версия по-ниска от %s.",
+ "Following databases are supported: %s" : "Следните бази данни са поддържани: %s",
+ "The command line tool %s could not be found" : "Конзолната команда %s не може да бъде намерена",
+ "The library %s is not available." : "Библиотеката %s не е налична",
+ "Library %s with a version higher than %s is required - available version %s." : "Необходима е библиотеката %s с версия по-висока от %s - налична версия %s. ",
+ "Library %s with a version lower than %s is required - available version %s." : "Необходима е библиотеката %s с версия по-ниска от %s - налична версия %s. ",
+ "Following platforms are supported: %s" : "Поддържани са следните платформи: %s",
+ "Unknown filetype" : "Непознат тип файл",
+ "Invalid image" : "Невалидно изображение.",
+ "today" : "днес",
+ "yesterday" : "вчера",
+ "_%n day ago_::_%n days ago_" : ["преди %n ден","преди %n дни"],
+ "last month" : "миналия месец",
+ "_%n month ago_::_%n months ago_" : ["преди %n месец","преди %n месеца"],
+ "last year" : "миналата година",
+ "_%n year ago_::_%n years ago_" : ["преди %n година","преди %n години"],
+ "_%n hour ago_::_%n hours ago_" : ["преди %n час","преди %n часа"],
+ "_%n minute ago_::_%n minutes ago_" : ["преди %n минута","преди %n минути"],
+ "seconds ago" : "преди секунди",
+ "File name contains at least one invalid character" : "Името на файла съдържа поне един невалиден символ",
+ "File name is too long" : "Името на файла е твърде дълго",
+ "__language_name__" : "Български",
+ "Help" : "Помощ",
+ "Apps" : "Приложения",
+ "Users" : "Потребители",
+ "Unknown user" : "Непознат потребител",
+ "Sharing" : "Споделяне",
+ "Additional settings" : "Допълнителни настройки",
+ "%s enter the database username and name." : "%s въведете потребителско име и име за базата данни",
+ "%s enter the database username." : "%s въведете потребител за базата данни.",
+ "%s enter the database name." : "%s въведи име на базата данни.",
+ "%s you may not use dots in the database name" : "%s, не може да ползваш точки в името на базата данни.",
+ "Oracle username and/or password not valid" : "Невалидно Oracle потребителско име и/или парола.",
+ "PostgreSQL username and/or password not valid" : "Невалидно PostgreSQL потребителско име и/или парола.",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X не се подържа и %s няма да работи правилно на тази платформа. Използвайте го на свой собствен риск!",
+ "For the best results, please consider using a GNU/Linux server instead." : "За най-добри резултати, моля, помисли дали не бихте желали да използваште GNU/Linux сървър.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Моля, премахтене настройката за open_basedir от вашия php.ini или преминете към 64-битово PHP.",
+ "Set an admin username." : "Задайте потребителско име за администратор.",
+ "Set an admin password." : "Задай парола за администратор.",
+ "Can't create or write into the data directory %s" : "Неуспешно създаване или записване в \"data\" папката %s",
+ "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, защото файлът не съществува.",
+ "You are not allowed to share %s" : "Не ти е разрешено да споделяш %s.",
+ "Sharing %s failed, because the user %s does not exist" : "Неуспешно споделяне на %s, защото потребител %s не съществува.",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Неуспешно споделяне на %s, защото %s не е член никоя от групите, в които е %s.",
+ "Sharing %s failed, because this item is already shared with %s" : "Неуспешно споделяне на %s, защото това съдържание е вече споделено с %s.",
+ "Sharing %s failed, because the group %s does not exist" : "Неупешно споделяне на %s, защото групата %s не съществува.",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Неуспешно споделяне на %s, защото %s не е член на групата %s.",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Трябва да зададеш парола, за да създадеш общодостъпен линк за споделяне, само защитени с пароли линкове са разрешени.",
+ "Sharing %s failed, because sharing with links is not allowed" : "Неуспешно споделяне на %s, защото споделянето посредством връзки не е разрешено.",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Неуспешно споделяне на на %s, не може бъде намерено %s. Може би сървъра в момента е недостъпен.",
+ "Share type %s is not valid for %s" : "Споделянето на тип %s не валидно за %s.",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Неуспешно задаване на дата на изтичане. Споделни папки или файлове не могат да изтичат по-късно от %s след като са били споделени",
+ "Cannot set expiration date. Expiration date is in the past" : "Неуспешно задаване на дата на изтичане. Датата на изтичане е в миналото",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Споделянето на сървърния %s трябва да поддържа OCP\\Share_Backend интерфейс.",
+ "Sharing backend %s not found" : "Споделянето на сървърния %s не е открито.",
+ "Sharing backend for %s not found" : "Споделянето на сървъра за %s не е открито.",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Неуспешно споделяне на %s, защото промените надвишават правата на достъп дадени на %s.",
+ "Sharing %s failed, because resharing is not allowed" : "Неуспешно споделяне на %s, защото повторно споделяне не е разрешено.",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Неуспешно споделяне на %s, защото не е открит първоизточникът на %s, за да бъде споделяне по сървъра.",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Неуспешно споделяне на %s, защото файлът не може да бъде намерен в кеша.",
+ "%s shared »%s« with you" : "%s сподели »%s« с теб",
+ "%s via %s" : "%s чрез %s",
+ "Could not find category \"%s\"" : "Невъзможно откриване на категорията \"%s\".",
+ "Sunday" : "неделя",
+ "Monday" : "понеделник",
+ "Tuesday" : "вторник",
+ "Wednesday" : "сряда",
+ "Thursday" : "четвъртък",
+ "Friday" : "петък",
+ "Saturday" : "събота",
+ "Sun." : "нед",
+ "Mon." : "пон",
+ "Tue." : "вт",
+ "Wed." : "ср",
+ "Thu." : "чет",
+ "Fri." : "пет",
+ "Sat." : "съб",
+ "Su" : "нд",
+ "Mo" : "пн",
+ "We" : "ср",
+ "Th" : "чт",
+ "Fr" : "пт",
+ "Sa" : "сб",
+ "January" : "януари",
+ "February" : "февруару",
+ "March" : "март",
+ "April" : "април",
+ "May" : "май",
+ "June" : "юни",
+ "July" : "юли",
+ "August" : "август",
+ "September" : "септември",
+ "October" : "октомври",
+ "November" : "ноември",
+ "December" : "декември",
+ "Jan." : "яну",
+ "Feb." : "фев",
+ "Mar." : "мар",
+ "Apr." : "апр",
+ "May." : "май",
+ "Jun." : "юни",
+ "Jul." : "юли",
+ "Aug." : "авг",
+ "Sep." : "сеп",
+ "Oct." : "окт",
+ "Nov." : "ное",
+ "Dec." : "дек",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Потребителските имена може да съдържат следните знаци: \"a-z\", \"A-Z\", \"0-9\" и \"_.@-'\"",
+ "A valid username must be provided" : "Трябва да въведете валидно потребителско.",
+ "Username contains whitespace at the beginning or at the end" : "Потребителското име започва или завършва с интервал.",
+ "A valid password must be provided" : "Трябва да въведете валидна парола.",
+ "The username is already being used" : "Потребителското име е вече заето.",
+ "a safe home for all your data" : "безопасен дом за всички ваши данни",
+ "Can't read file" : "Файлът не може да бъде прочетен",
+ "Application is not enabled" : "Приложението не е включено",
+ "Authentication error" : "Проблем с идентификацията",
+ "Token expired. Please reload page." : "Изтекла сесия. Моля, презареди страницата.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Липсват инсталирани драйвери за бази данни(sqlite, mysql или postgresql).",
+ "Cannot write into \"config\" directory" : "Неуспешен опит за запис в \"config\" папката.",
+ "Cannot write into \"apps\" directory" : "Писането в папка приложения не е възможно",
+ "Setting locale to %s failed" : "Неуспешно задаване на %s като настройка език-държава.",
+ "Please install one of these locales on your system and restart your webserver." : "Моля, инсталирай едно от следните език-държава на сървъра и рестартирай уеб сървъра.",
+ "Please ask your server administrator to install the module." : "Моля, помолете вашия администратор да инсталира модула.",
+ "PHP module %s not installed." : "PHP модулът %s не е инсталиран.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Това може да се дължи на cache/accelerator като Zend OPache или eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "PHP модулите са инсталирани, но все още се обявяват като липсващи?",
+ "Please ask your server administrator to restart the web server." : "Моля, поискай от своя администратор да рестартира уеб сървъра.",
+ "PostgreSQL >= 9 required" : "Изисква се PostgreSQL >= 9",
+ "Please upgrade your database version" : "Моля, обнови базата данни.",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Моля, променете правата за достъп на 0770, за да не може директорията да бъде видяна от други потребители.",
+ "Could not obtain lock type %d on \"%s\"." : "Неуспешен опит за ексклузивен достъп от типa %d върху \"%s\".",
+ "APCu" : "APCu",
+ "Redis" : "Redis"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/bg.json b/lib/l10n/bg.json
new file mode 100644
index 00000000000..1a0feea7c23
--- /dev/null
+++ b/lib/l10n/bg.json
@@ -0,0 +1,147 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Неуспешен опит за запис в \"config\" папката!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Това може да бъде решено единствено като разрешиш на уеб сървъра да пише в config папката.",
+ "See %s" : "Вижте %s",
+ "Sample configuration detected" : "Открита е примерна конфигурация",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Усетено беше че примерната конфигурация е копирана. Това може да развли инсталацията ти и не се поддържа. Моля, прочети документацията преди да правиш промени на config.php",
+ "%1$s and %2$s" : "%1$s и %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s и %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s и %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s и %5$s",
+ "PHP %s or higher is required." : "Изисква се PHP %s или по-нова.",
+ "PHP with a version lower than %s is required." : "Необходим е PHP с версия по-ниска от %s.",
+ "Following databases are supported: %s" : "Следните бази данни са поддържани: %s",
+ "The command line tool %s could not be found" : "Конзолната команда %s не може да бъде намерена",
+ "The library %s is not available." : "Библиотеката %s не е налична",
+ "Library %s with a version higher than %s is required - available version %s." : "Необходима е библиотеката %s с версия по-висока от %s - налична версия %s. ",
+ "Library %s with a version lower than %s is required - available version %s." : "Необходима е библиотеката %s с версия по-ниска от %s - налична версия %s. ",
+ "Following platforms are supported: %s" : "Поддържани са следните платформи: %s",
+ "Unknown filetype" : "Непознат тип файл",
+ "Invalid image" : "Невалидно изображение.",
+ "today" : "днес",
+ "yesterday" : "вчера",
+ "_%n day ago_::_%n days ago_" : ["преди %n ден","преди %n дни"],
+ "last month" : "миналия месец",
+ "_%n month ago_::_%n months ago_" : ["преди %n месец","преди %n месеца"],
+ "last year" : "миналата година",
+ "_%n year ago_::_%n years ago_" : ["преди %n година","преди %n години"],
+ "_%n hour ago_::_%n hours ago_" : ["преди %n час","преди %n часа"],
+ "_%n minute ago_::_%n minutes ago_" : ["преди %n минута","преди %n минути"],
+ "seconds ago" : "преди секунди",
+ "File name contains at least one invalid character" : "Името на файла съдържа поне един невалиден символ",
+ "File name is too long" : "Името на файла е твърде дълго",
+ "__language_name__" : "Български",
+ "Help" : "Помощ",
+ "Apps" : "Приложения",
+ "Users" : "Потребители",
+ "Unknown user" : "Непознат потребител",
+ "Sharing" : "Споделяне",
+ "Additional settings" : "Допълнителни настройки",
+ "%s enter the database username and name." : "%s въведете потребителско име и име за базата данни",
+ "%s enter the database username." : "%s въведете потребител за базата данни.",
+ "%s enter the database name." : "%s въведи име на базата данни.",
+ "%s you may not use dots in the database name" : "%s, не може да ползваш точки в името на базата данни.",
+ "Oracle username and/or password not valid" : "Невалидно Oracle потребителско име и/или парола.",
+ "PostgreSQL username and/or password not valid" : "Невалидно PostgreSQL потребителско име и/или парола.",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X не се подържа и %s няма да работи правилно на тази платформа. Използвайте го на свой собствен риск!",
+ "For the best results, please consider using a GNU/Linux server instead." : "За най-добри резултати, моля, помисли дали не бихте желали да използваште GNU/Linux сървър.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Моля, премахтене настройката за open_basedir от вашия php.ini или преминете към 64-битово PHP.",
+ "Set an admin username." : "Задайте потребителско име за администратор.",
+ "Set an admin password." : "Задай парола за администратор.",
+ "Can't create or write into the data directory %s" : "Неуспешно създаване или записване в \"data\" папката %s",
+ "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, защото файлът не съществува.",
+ "You are not allowed to share %s" : "Не ти е разрешено да споделяш %s.",
+ "Sharing %s failed, because the user %s does not exist" : "Неуспешно споделяне на %s, защото потребител %s не съществува.",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Неуспешно споделяне на %s, защото %s не е член никоя от групите, в които е %s.",
+ "Sharing %s failed, because this item is already shared with %s" : "Неуспешно споделяне на %s, защото това съдържание е вече споделено с %s.",
+ "Sharing %s failed, because the group %s does not exist" : "Неупешно споделяне на %s, защото групата %s не съществува.",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Неуспешно споделяне на %s, защото %s не е член на групата %s.",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Трябва да зададеш парола, за да създадеш общодостъпен линк за споделяне, само защитени с пароли линкове са разрешени.",
+ "Sharing %s failed, because sharing with links is not allowed" : "Неуспешно споделяне на %s, защото споделянето посредством връзки не е разрешено.",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Неуспешно споделяне на на %s, не може бъде намерено %s. Може би сървъра в момента е недостъпен.",
+ "Share type %s is not valid for %s" : "Споделянето на тип %s не валидно за %s.",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Неуспешно задаване на дата на изтичане. Споделни папки или файлове не могат да изтичат по-късно от %s след като са били споделени",
+ "Cannot set expiration date. Expiration date is in the past" : "Неуспешно задаване на дата на изтичане. Датата на изтичане е в миналото",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Споделянето на сървърния %s трябва да поддържа OCP\\Share_Backend интерфейс.",
+ "Sharing backend %s not found" : "Споделянето на сървърния %s не е открито.",
+ "Sharing backend for %s not found" : "Споделянето на сървъра за %s не е открито.",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Неуспешно споделяне на %s, защото промените надвишават правата на достъп дадени на %s.",
+ "Sharing %s failed, because resharing is not allowed" : "Неуспешно споделяне на %s, защото повторно споделяне не е разрешено.",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Неуспешно споделяне на %s, защото не е открит първоизточникът на %s, за да бъде споделяне по сървъра.",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Неуспешно споделяне на %s, защото файлът не може да бъде намерен в кеша.",
+ "%s shared »%s« with you" : "%s сподели »%s« с теб",
+ "%s via %s" : "%s чрез %s",
+ "Could not find category \"%s\"" : "Невъзможно откриване на категорията \"%s\".",
+ "Sunday" : "неделя",
+ "Monday" : "понеделник",
+ "Tuesday" : "вторник",
+ "Wednesday" : "сряда",
+ "Thursday" : "четвъртък",
+ "Friday" : "петък",
+ "Saturday" : "събота",
+ "Sun." : "нед",
+ "Mon." : "пон",
+ "Tue." : "вт",
+ "Wed." : "ср",
+ "Thu." : "чет",
+ "Fri." : "пет",
+ "Sat." : "съб",
+ "Su" : "нд",
+ "Mo" : "пн",
+ "We" : "ср",
+ "Th" : "чт",
+ "Fr" : "пт",
+ "Sa" : "сб",
+ "January" : "януари",
+ "February" : "февруару",
+ "March" : "март",
+ "April" : "април",
+ "May" : "май",
+ "June" : "юни",
+ "July" : "юли",
+ "August" : "август",
+ "September" : "септември",
+ "October" : "октомври",
+ "November" : "ноември",
+ "December" : "декември",
+ "Jan." : "яну",
+ "Feb." : "фев",
+ "Mar." : "мар",
+ "Apr." : "апр",
+ "May." : "май",
+ "Jun." : "юни",
+ "Jul." : "юли",
+ "Aug." : "авг",
+ "Sep." : "сеп",
+ "Oct." : "окт",
+ "Nov." : "ное",
+ "Dec." : "дек",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Потребителските имена може да съдържат следните знаци: \"a-z\", \"A-Z\", \"0-9\" и \"_.@-'\"",
+ "A valid username must be provided" : "Трябва да въведете валидно потребителско.",
+ "Username contains whitespace at the beginning or at the end" : "Потребителското име започва или завършва с интервал.",
+ "A valid password must be provided" : "Трябва да въведете валидна парола.",
+ "The username is already being used" : "Потребителското име е вече заето.",
+ "a safe home for all your data" : "безопасен дом за всички ваши данни",
+ "Can't read file" : "Файлът не може да бъде прочетен",
+ "Application is not enabled" : "Приложението не е включено",
+ "Authentication error" : "Проблем с идентификацията",
+ "Token expired. Please reload page." : "Изтекла сесия. Моля, презареди страницата.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Липсват инсталирани драйвери за бази данни(sqlite, mysql или postgresql).",
+ "Cannot write into \"config\" directory" : "Неуспешен опит за запис в \"config\" папката.",
+ "Cannot write into \"apps\" directory" : "Писането в папка приложения не е възможно",
+ "Setting locale to %s failed" : "Неуспешно задаване на %s като настройка език-държава.",
+ "Please install one of these locales on your system and restart your webserver." : "Моля, инсталирай едно от следните език-държава на сървъра и рестартирай уеб сървъра.",
+ "Please ask your server administrator to install the module." : "Моля, помолете вашия администратор да инсталира модула.",
+ "PHP module %s not installed." : "PHP модулът %s не е инсталиран.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Това може да се дължи на cache/accelerator като Zend OPache или eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "PHP модулите са инсталирани, но все още се обявяват като липсващи?",
+ "Please ask your server administrator to restart the web server." : "Моля, поискай от своя администратор да рестартира уеб сървъра.",
+ "PostgreSQL >= 9 required" : "Изисква се PostgreSQL >= 9",
+ "Please upgrade your database version" : "Моля, обнови базата данни.",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Моля, променете правата за достъп на 0770, за да не може директорията да бъде видяна от други потребители.",
+ "Could not obtain lock type %d on \"%s\"." : "Неуспешен опит за ексклузивен достъп от типa %d върху \"%s\".",
+ "APCu" : "APCu",
+ "Redis" : "Redis"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/bn_BD.js b/lib/l10n/bn_BD.js
new file mode 100644
index 00000000000..b5d987fc829
--- /dev/null
+++ b/lib/l10n/bn_BD.js
@@ -0,0 +1,26 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "\"config\" ডিরেক্টরিতে লেখা যায়না!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "সাধারণতঃ ওয়বসার্ভারকে কনফিগ ডিরেক্টরিতে লেখার অধিকার দিয়ে এই সমস্যা সমাধান করা যায়",
+ "See %s" : "%s দেখ",
+ "Sample configuration detected" : "নমুনা কনফিগারেশন পাওয়া গেছে",
+ "Unknown filetype" : "অজানা প্রকৃতির ফাইল",
+ "Invalid image" : "অবৈধ চিত্র",
+ "today" : "আজ",
+ "yesterday" : "গতকাল",
+ "last month" : "গত মাস",
+ "last year" : "গত বছর",
+ "seconds ago" : "সেকেন্ড পূর্বে",
+ "__language_name__" : "বাংলা ভাষা",
+ "Apps" : "অ্যাপ",
+ "Users" : "ব্যবহারকারী",
+ "Unknown user" : "অপরিচিত ব্যবহারকারী",
+ "Sharing %s failed, because the file does not exist" : "%s ভাগাভাগি ব্যার্থ, কারণ ফাইলটি নেই",
+ "You are not allowed to share %s" : "আপনি %s ভাগাভাগি করতে পারবেননা",
+ "%s shared »%s« with you" : "%s আপনার সাথে »%s« ভাগাভাগি করেছে",
+ "Application is not enabled" : "অ্যাপ্লিকেসনটি সক্রিয় নয়",
+ "Authentication error" : "অনুমোদন ঘটিত সমস্যা",
+ "Token expired. Please reload page." : "টোকেন মেয়াদোত্তীর্ণ। দয়া করে পৃষ্ঠাটি পূনরায় লোড করুন।"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/bn_BD.json b/lib/l10n/bn_BD.json
new file mode 100644
index 00000000000..50adb7a040d
--- /dev/null
+++ b/lib/l10n/bn_BD.json
@@ -0,0 +1,24 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "\"config\" ডিরেক্টরিতে লেখা যায়না!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "সাধারণতঃ ওয়বসার্ভারকে কনফিগ ডিরেক্টরিতে লেখার অধিকার দিয়ে এই সমস্যা সমাধান করা যায়",
+ "See %s" : "%s দেখ",
+ "Sample configuration detected" : "নমুনা কনফিগারেশন পাওয়া গেছে",
+ "Unknown filetype" : "অজানা প্রকৃতির ফাইল",
+ "Invalid image" : "অবৈধ চিত্র",
+ "today" : "আজ",
+ "yesterday" : "গতকাল",
+ "last month" : "গত মাস",
+ "last year" : "গত বছর",
+ "seconds ago" : "সেকেন্ড পূর্বে",
+ "__language_name__" : "বাংলা ভাষা",
+ "Apps" : "অ্যাপ",
+ "Users" : "ব্যবহারকারী",
+ "Unknown user" : "অপরিচিত ব্যবহারকারী",
+ "Sharing %s failed, because the file does not exist" : "%s ভাগাভাগি ব্যার্থ, কারণ ফাইলটি নেই",
+ "You are not allowed to share %s" : "আপনি %s ভাগাভাগি করতে পারবেননা",
+ "%s shared »%s« with you" : "%s আপনার সাথে »%s« ভাগাভাগি করেছে",
+ "Application is not enabled" : "অ্যাপ্লিকেসনটি সক্রিয় নয়",
+ "Authentication error" : "অনুমোদন ঘটিত সমস্যা",
+ "Token expired. Please reload page." : "টোকেন মেয়াদোত্তীর্ণ। দয়া করে পৃষ্ঠাটি পূনরায় লোড করুন।"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/bs.js b/lib/l10n/bs.js
new file mode 100644
index 00000000000..3195417a9fd
--- /dev/null
+++ b/lib/l10n/bs.js
@@ -0,0 +1,16 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Unknown filetype" : "Nepoznat tip datoteke",
+ "Invalid image" : "Nevažeća datoteka",
+ "__language_name__" : "Bosanski jezik",
+ "Apps" : "Aplikacije",
+ "Users" : "Korisnici",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nije podržan i %s na ovoj platformi neće raditi kako treba. Korištenje na vlastiti rizik!",
+ "For the best results, please consider using a GNU/Linux server instead." : "Umjesto toga, za najbolje rezultate, molimo razmislite o mogućnosti korištenje GNU/Linux servera.",
+ "A valid username must be provided" : "Nužno je navesti valjano korisničko ime",
+ "A valid password must be provided" : "Nužno je navesti valjanu lozinku",
+ "Authentication error" : "Grešna autentifikacije",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Uzrok tome je vjerojatno neki ubrzivač predmemorisanja kao što je Zend OPcache ili eAccelerator."
+},
+"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);");
diff --git a/lib/l10n/bs.json b/lib/l10n/bs.json
new file mode 100644
index 00000000000..2be7589a1a0
--- /dev/null
+++ b/lib/l10n/bs.json
@@ -0,0 +1,14 @@
+{ "translations": {
+ "Unknown filetype" : "Nepoznat tip datoteke",
+ "Invalid image" : "Nevažeća datoteka",
+ "__language_name__" : "Bosanski jezik",
+ "Apps" : "Aplikacije",
+ "Users" : "Korisnici",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nije podržan i %s na ovoj platformi neće raditi kako treba. Korištenje na vlastiti rizik!",
+ "For the best results, please consider using a GNU/Linux server instead." : "Umjesto toga, za najbolje rezultate, molimo razmislite o mogućnosti korištenje GNU/Linux servera.",
+ "A valid username must be provided" : "Nužno je navesti valjano korisničko ime",
+ "A valid password must be provided" : "Nužno je navesti valjanu lozinku",
+ "Authentication error" : "Grešna autentifikacije",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Uzrok tome je vjerojatno neki ubrzivač predmemorisanja kao što je Zend OPcache ili eAccelerator."
+},"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
+} \ No newline at end of file
diff --git a/lib/l10n/ca.js b/lib/l10n/ca.js
new file mode 100644
index 00000000000..8ee2e416751
--- /dev/null
+++ b/lib/l10n/ca.js
@@ -0,0 +1,193 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "No es pot escriure a la carpeta \"config\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Això normalment es pot solucionar donant al servidor web permís d'escriptura a la carpeta de configuració",
+ "See %s" : "Comproveu %s",
+ "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Això normalment es soluciona donant permisos d'escriptura al servidor al directori de configuració. Consulta %s",
+ "Sample configuration detected" : "Configuració d'exemple detectada",
+ "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" : "S'ha detectat que la configuració d'exemple ha estat copiada. Això no està suportat, i podria corrompre la vostra instalació. Siusplau, llegiu la documentació abans de realitzar canvis a config.php",
+ "%1$s and %2$s" : "%1$s i %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s i %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s i %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s i %5$s",
+ "Education Edition" : "Edició educativa",
+ "Enterprise bundle" : "Paquet empresarial",
+ "Groupware bundle" : "Paquet de treball en grup",
+ "Social sharing bundle" : "Paquet social",
+ "PHP %s or higher is required." : "Es requereix PHP %s o superior.",
+ "PHP with a version lower than %s is required." : "Es requereix php amb versió menor a %s.",
+ "%sbit or higher PHP required." : "Es requereix PHP %s o superior.",
+ "Following databases are supported: %s" : "Es suporten les següents bases de dades: %s",
+ "The command line tool %s could not be found" : "No s'ha pogut trobar l'eina per intèrpret de comandes %s",
+ "The library %s is not available." : "La llibreria %s no es troba disponible.",
+ "Server version %s or higher is required." : "Es requereix una versió de servidor %s o superior",
+ "Server version %s or lower is required." : "Es requereix una versió de servidor %s o inferior",
+ "Unknown filetype" : "Tipus de fitxer desconegut",
+ "Invalid image" : "Imatge no vàlida",
+ "Avatar image is not square" : "La imatge de perfil no és quadrada",
+ "today" : "avui",
+ "tomorrow" : "demà",
+ "yesterday" : "ahir",
+ "_in %n day_::_in %n days_" : ["d'aquí %n dia","d'aquí %n dies"],
+ "_%n day ago_::_%n days ago_" : ["fa %n dia","fa %n dies"],
+ "next month" : "mes següent",
+ "last month" : "el mes passat",
+ "_in %n month_::_in %n months_" : ["d'aquí %n mesos","d'aquí %n mesos"],
+ "_%n month ago_::_%n months ago_" : ["fa %n mes","fa %n mesos"],
+ "next year" : "any següent",
+ "last year" : "l'any passat",
+ "_in %n year_::_in %n years_" : ["d'aquí %n any","d'aquí %n anys"],
+ "_%n year ago_::_%n years ago_" : ["fa %n any","fa %n anys"],
+ "_in %n hour_::_in %n hours_" : ["d'aquí %n hora","d'aquí %n hores"],
+ "_%n hour ago_::_%n hours ago_" : ["fa %n hora","fa %n hores"],
+ "_in %n minute_::_in %n minutes_" : ["d'aquí %n minut","d'aquí %n minuts"],
+ "_%n minute ago_::_%n minutes ago_" : ["fa %n minut","fa %n minuts"],
+ "in a few seconds" : "en uns segons",
+ "seconds ago" : "fa uns segons",
+ "File name is a reserved word" : "El nom de fitxer és una paraula reservada",
+ "File name contains at least one invalid character" : "El nom del fitxer conté al menys un caràcter invàlid",
+ "File name is too long" : "el nom del fitxer es massa gran",
+ "Dot files are not allowed" : "No estan permesos fitxers amb punt",
+ "Empty filename is not allowed" : "Mo estan permesos noms buits",
+ "__language_name__" : "Català",
+ "Help" : "Ajuda",
+ "Apps" : "Aplicacions",
+ "Settings" : "Configuració",
+ "Log out" : "Surt",
+ "Users" : "Usuaris",
+ "Unknown user" : "Usuari desconegut",
+ "Create" : "Crea",
+ "Change" : "Modifica",
+ "Delete" : "Esborra",
+ "Share" : "Comparteix",
+ "Overview" : "Resum",
+ "Basic settings" : "Configuració bàsica",
+ "Sharing" : "Compartir",
+ "Security" : "Seguretat",
+ "Encryption" : "Xifrat",
+ "Additional settings" : "Configuració addicional",
+ "Personal info" : "Informació personal",
+ "Unlimited" : "Il·limitat",
+ "Verifying" : "Verificant",
+ "Verifying …" : "Verificant ...",
+ "Verify" : "Verifica",
+ "%s enter the database username and name." : "%s escriviu el nom d'usuari i el nom de la base de dades.",
+ "%s enter the database username." : "%s escriviu el nom d'usuari de la base de dades.",
+ "%s enter the database name." : "%s escriviu el nom de la base de dades.",
+ "%s you may not use dots in the database name" : "%s no podeu usar punts en el nom de la base de dades",
+ "Oracle connection could not be established" : "No s'ha pogut establir la connexió Oracle",
+ "Oracle username and/or password not valid" : "Nom d'usuari i/o contrasenya Oracle no vàlids",
+ "PostgreSQL username and/or password not valid" : "Nom d'usuari i/o contrasenya PostgreSQL no vàlids",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X no té suport i %s no funcionarà correctament en aquesta plataforma. Useu-ho al vostre risc!",
+ "For the best results, please consider using a GNU/Linux server instead." : "Per millors resultats, millor considereu utilitzar un servidor GNU/Linux.",
+ "Set an admin username." : "Establiu un nom d'usuari per l'administrador.",
+ "Set an admin password." : "Establiu una contrasenya per l'administrador.",
+ "Invalid Federated Cloud ID" : "ID de núvol federat invàlid",
+ "Sharing %s failed, because the file does not exist" : "Ha fallat en compartir %s, perquè el fitxer no existeix",
+ "You are not allowed to share %s" : "No se us permet compartir %s",
+ "Sharing %s failed, because the user %s does not exist" : "Ha fallat en compartir %s, perquè l'usuari %s no existeix",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Ha fallat en compartir %s, perquè l'usuari %s no és membre de cap grup dels que %s és membre",
+ "Sharing %s failed, because this item is already shared with %s" : "Ha fallat en compartir %s, perquè l'element ja està compartit amb %s",
+ "Sharing %s failed, because the group %s does not exist" : "Ha fallat en compartir %s, perquè el grup %s no existeix",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Ha fallat en compartir %s, perquè %s no és membre del grup %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Heu de proporcionar una contrasenya per crear un enllaç públic. Només es permeten enllaços segurs.",
+ "Sharing %s failed, because sharing with links is not allowed" : "Ha fallat en compartir %s, perquè no es permet compartir amb enllaços",
+ "Not allowed to create a federated share with the same user" : "No està permés crear una compartició federada amb el mateix usuari",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "La compartició de %s ha fallat, no es pot trobar %s, potser el servidor està actualment innacessible.",
+ "Share type %s is not valid for %s" : "La compartició tipus %s no és vàlida per %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "No es pot guardar la data d'expiració. Els fitxers o carpetes compartits no poden expirar més tard de %s després d'haver-se compratit.",
+ "Cannot set expiration date. Expiration date is in the past" : "No es pot guardar la data d'expiració. La data d'expiració ja ha passat.",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El rerefons de compartició %s ha d'implementar la interfície OCP\\Share_Backend",
+ "Sharing backend %s not found" : "El rerefons de compartició %s no s'ha trobat",
+ "Sharing backend for %s not found" : "El rerefons de compartició per a %s no s'ha trobat",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Ha fallat en compartir %s perquè els permisos excedeixen els permesos per a %s",
+ "Sharing %s failed, because resharing is not allowed" : "Ha fallat en compartir %s, perquè no es permet compartir de nou",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Ha fallat en compartir %s, perquè el rerefons de compartir per %s no pot trobar la seva font",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Ha fallat en compartir %s, perquè el fitxer no s'ha trobat en el fitxer cau",
+ "Files can’t be shared with delete permissions" : "No es poden compartir els fitxers amb permisos d'esborrat",
+ "Files can’t be shared with create permissions" : "No es poden compartir els fitxers amb permisos de creació",
+ "%s shared »%s« with you" : "%s ha compartit »%s« amb tu",
+ "Click the button below to open it." : "Feu clic al botó següent per obrir-lo.",
+ "Open »%s«" : "Obre »%s«",
+ "%s via %s" : "%s via %s",
+ "The requested share does not exist anymore" : "El recurs sol·licitat ja no existeix",
+ "Could not find category \"%s\"" : "No s'ha trobat la categoria \"%s\"",
+ "Sunday" : "Diumenge",
+ "Monday" : "Dilluns",
+ "Tuesday" : "Dimarts",
+ "Wednesday" : "Dimecres",
+ "Thursday" : "Dijous",
+ "Friday" : "Divendres",
+ "Saturday" : "Dissabte",
+ "Sun." : "Dg.",
+ "Mon." : "Mon.",
+ "Tue." : "Dm.",
+ "Wed." : "Dc.",
+ "Thu." : "Dj.",
+ "Fri." : "Dv.",
+ "Sat." : "Ds.",
+ "Su" : "Dg",
+ "Mo" : "Dl",
+ "Tu" : "Dm",
+ "We" : "Dc",
+ "Th" : "Dj",
+ "Fr" : "Dv",
+ "Sa" : "Ds",
+ "January" : "Gener",
+ "February" : "Febrer",
+ "March" : "Març",
+ "April" : "Abril",
+ "May" : "Maig",
+ "June" : "Juny",
+ "July" : "Juliol",
+ "August" : "Agost",
+ "September" : "Setembre",
+ "October" : "Octubre",
+ "November" : "Novembre",
+ "December" : "Desembre",
+ "Jan." : "Gen.",
+ "Feb." : "Febr.",
+ "Mar." : "Març",
+ "Apr." : "Abr",
+ "May." : "Maig",
+ "Jun." : "Juny",
+ "Jul." : "Jul.",
+ "Aug." : "Ag.",
+ "Sep." : "Set",
+ "Oct." : "Oct.",
+ "Nov." : "Nov.",
+ "Dec." : "Des.",
+ "A valid username must be provided" : "Heu de facilitar un nom d'usuari vàlid",
+ "Username must not consist of dots only" : "El nom d'usuari no pot està format només per punts",
+ "A valid password must be provided" : "Heu de facilitar una contrasenya vàlida",
+ "The username is already being used" : "El nom d'usuari ja està en ús",
+ "Could not create user" : "No s'ha pogut crear l'usuari",
+ "User disabled" : "Usuari desactivat",
+ "Login canceled by app" : "Accés cancel·lat per l'App",
+ "a safe home for all your data" : "un lloc segur per a les teves dades",
+ "Can't read file" : "No es pot llegir el fitxer",
+ "Application is not enabled" : "L'aplicació no està habilitada",
+ "Authentication error" : "Error d'autenticació",
+ "Token expired. Please reload page." : "El testimoni ha expirat. Torneu a carregar la pàgina.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "No hi ha instal·lats controladors de bases de dades (sqlite, mysql o postgresql).",
+ "Cannot write into \"config\" directory" : "No es pot escriure a la carpeta \"config\"",
+ "Cannot write into \"apps\" directory" : "No es pot escriure a la carpeta \"apps\"",
+ "Setting locale to %s failed" : "Ha fallat en establir la llengua a %s",
+ "Please install one of these locales on your system and restart your webserver." : "Siusplau, instal·li un d'aquests arxius de localització en el seu sistema, i reinicii el seu servidor web.",
+ "Please ask your server administrator to install the module." : "Demaneu a l'administrador del sistema que instal·li el mòdul.",
+ "PHP module %s not installed." : "El mòdul PHP %s no està instal·lat.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Això probablement està provocat per una cau/accelerador com Zend OPcache o eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "S'han instal·lat mòduls PHP, però encara es llisten com una mancança?",
+ "Please ask your server administrator to restart the web server." : "Demaneu a l'administrador que reinici el servidor web.",
+ "PostgreSQL >= 9 required" : "Es requereix PostgreSQL >= 9",
+ "Please upgrade your database version" : "Actualitzeu la versió de la base de dades",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Canvieu els permisos a 0770 per tal que la carpeta no es pugui llistar per altres usuaris.",
+ "Could not obtain lock type %d on \"%s\"." : "No s'ha pogut obtenir un bloqueig tipus %d a \"%s\".",
+ "Personal" : "Personal",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consells i trucs",
+ "Sync clients" : "Aplicacions per sincronitzar"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/ca.json b/lib/l10n/ca.json
new file mode 100644
index 00000000000..26c96edb590
--- /dev/null
+++ b/lib/l10n/ca.json
@@ -0,0 +1,191 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "No es pot escriure a la carpeta \"config\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Això normalment es pot solucionar donant al servidor web permís d'escriptura a la carpeta de configuració",
+ "See %s" : "Comproveu %s",
+ "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Això normalment es soluciona donant permisos d'escriptura al servidor al directori de configuració. Consulta %s",
+ "Sample configuration detected" : "Configuració d'exemple detectada",
+ "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" : "S'ha detectat que la configuració d'exemple ha estat copiada. Això no està suportat, i podria corrompre la vostra instalació. Siusplau, llegiu la documentació abans de realitzar canvis a config.php",
+ "%1$s and %2$s" : "%1$s i %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s i %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s i %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s i %5$s",
+ "Education Edition" : "Edició educativa",
+ "Enterprise bundle" : "Paquet empresarial",
+ "Groupware bundle" : "Paquet de treball en grup",
+ "Social sharing bundle" : "Paquet social",
+ "PHP %s or higher is required." : "Es requereix PHP %s o superior.",
+ "PHP with a version lower than %s is required." : "Es requereix php amb versió menor a %s.",
+ "%sbit or higher PHP required." : "Es requereix PHP %s o superior.",
+ "Following databases are supported: %s" : "Es suporten les següents bases de dades: %s",
+ "The command line tool %s could not be found" : "No s'ha pogut trobar l'eina per intèrpret de comandes %s",
+ "The library %s is not available." : "La llibreria %s no es troba disponible.",
+ "Server version %s or higher is required." : "Es requereix una versió de servidor %s o superior",
+ "Server version %s or lower is required." : "Es requereix una versió de servidor %s o inferior",
+ "Unknown filetype" : "Tipus de fitxer desconegut",
+ "Invalid image" : "Imatge no vàlida",
+ "Avatar image is not square" : "La imatge de perfil no és quadrada",
+ "today" : "avui",
+ "tomorrow" : "demà",
+ "yesterday" : "ahir",
+ "_in %n day_::_in %n days_" : ["d'aquí %n dia","d'aquí %n dies"],
+ "_%n day ago_::_%n days ago_" : ["fa %n dia","fa %n dies"],
+ "next month" : "mes següent",
+ "last month" : "el mes passat",
+ "_in %n month_::_in %n months_" : ["d'aquí %n mesos","d'aquí %n mesos"],
+ "_%n month ago_::_%n months ago_" : ["fa %n mes","fa %n mesos"],
+ "next year" : "any següent",
+ "last year" : "l'any passat",
+ "_in %n year_::_in %n years_" : ["d'aquí %n any","d'aquí %n anys"],
+ "_%n year ago_::_%n years ago_" : ["fa %n any","fa %n anys"],
+ "_in %n hour_::_in %n hours_" : ["d'aquí %n hora","d'aquí %n hores"],
+ "_%n hour ago_::_%n hours ago_" : ["fa %n hora","fa %n hores"],
+ "_in %n minute_::_in %n minutes_" : ["d'aquí %n minut","d'aquí %n minuts"],
+ "_%n minute ago_::_%n minutes ago_" : ["fa %n minut","fa %n minuts"],
+ "in a few seconds" : "en uns segons",
+ "seconds ago" : "fa uns segons",
+ "File name is a reserved word" : "El nom de fitxer és una paraula reservada",
+ "File name contains at least one invalid character" : "El nom del fitxer conté al menys un caràcter invàlid",
+ "File name is too long" : "el nom del fitxer es massa gran",
+ "Dot files are not allowed" : "No estan permesos fitxers amb punt",
+ "Empty filename is not allowed" : "Mo estan permesos noms buits",
+ "__language_name__" : "Català",
+ "Help" : "Ajuda",
+ "Apps" : "Aplicacions",
+ "Settings" : "Configuració",
+ "Log out" : "Surt",
+ "Users" : "Usuaris",
+ "Unknown user" : "Usuari desconegut",
+ "Create" : "Crea",
+ "Change" : "Modifica",
+ "Delete" : "Esborra",
+ "Share" : "Comparteix",
+ "Overview" : "Resum",
+ "Basic settings" : "Configuració bàsica",
+ "Sharing" : "Compartir",
+ "Security" : "Seguretat",
+ "Encryption" : "Xifrat",
+ "Additional settings" : "Configuració addicional",
+ "Personal info" : "Informació personal",
+ "Unlimited" : "Il·limitat",
+ "Verifying" : "Verificant",
+ "Verifying …" : "Verificant ...",
+ "Verify" : "Verifica",
+ "%s enter the database username and name." : "%s escriviu el nom d'usuari i el nom de la base de dades.",
+ "%s enter the database username." : "%s escriviu el nom d'usuari de la base de dades.",
+ "%s enter the database name." : "%s escriviu el nom de la base de dades.",
+ "%s you may not use dots in the database name" : "%s no podeu usar punts en el nom de la base de dades",
+ "Oracle connection could not be established" : "No s'ha pogut establir la connexió Oracle",
+ "Oracle username and/or password not valid" : "Nom d'usuari i/o contrasenya Oracle no vàlids",
+ "PostgreSQL username and/or password not valid" : "Nom d'usuari i/o contrasenya PostgreSQL no vàlids",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X no té suport i %s no funcionarà correctament en aquesta plataforma. Useu-ho al vostre risc!",
+ "For the best results, please consider using a GNU/Linux server instead." : "Per millors resultats, millor considereu utilitzar un servidor GNU/Linux.",
+ "Set an admin username." : "Establiu un nom d'usuari per l'administrador.",
+ "Set an admin password." : "Establiu una contrasenya per l'administrador.",
+ "Invalid Federated Cloud ID" : "ID de núvol federat invàlid",
+ "Sharing %s failed, because the file does not exist" : "Ha fallat en compartir %s, perquè el fitxer no existeix",
+ "You are not allowed to share %s" : "No se us permet compartir %s",
+ "Sharing %s failed, because the user %s does not exist" : "Ha fallat en compartir %s, perquè l'usuari %s no existeix",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Ha fallat en compartir %s, perquè l'usuari %s no és membre de cap grup dels que %s és membre",
+ "Sharing %s failed, because this item is already shared with %s" : "Ha fallat en compartir %s, perquè l'element ja està compartit amb %s",
+ "Sharing %s failed, because the group %s does not exist" : "Ha fallat en compartir %s, perquè el grup %s no existeix",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Ha fallat en compartir %s, perquè %s no és membre del grup %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Heu de proporcionar una contrasenya per crear un enllaç públic. Només es permeten enllaços segurs.",
+ "Sharing %s failed, because sharing with links is not allowed" : "Ha fallat en compartir %s, perquè no es permet compartir amb enllaços",
+ "Not allowed to create a federated share with the same user" : "No està permés crear una compartició federada amb el mateix usuari",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "La compartició de %s ha fallat, no es pot trobar %s, potser el servidor està actualment innacessible.",
+ "Share type %s is not valid for %s" : "La compartició tipus %s no és vàlida per %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "No es pot guardar la data d'expiració. Els fitxers o carpetes compartits no poden expirar més tard de %s després d'haver-se compratit.",
+ "Cannot set expiration date. Expiration date is in the past" : "No es pot guardar la data d'expiració. La data d'expiració ja ha passat.",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El rerefons de compartició %s ha d'implementar la interfície OCP\\Share_Backend",
+ "Sharing backend %s not found" : "El rerefons de compartició %s no s'ha trobat",
+ "Sharing backend for %s not found" : "El rerefons de compartició per a %s no s'ha trobat",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Ha fallat en compartir %s perquè els permisos excedeixen els permesos per a %s",
+ "Sharing %s failed, because resharing is not allowed" : "Ha fallat en compartir %s, perquè no es permet compartir de nou",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Ha fallat en compartir %s, perquè el rerefons de compartir per %s no pot trobar la seva font",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Ha fallat en compartir %s, perquè el fitxer no s'ha trobat en el fitxer cau",
+ "Files can’t be shared with delete permissions" : "No es poden compartir els fitxers amb permisos d'esborrat",
+ "Files can’t be shared with create permissions" : "No es poden compartir els fitxers amb permisos de creació",
+ "%s shared »%s« with you" : "%s ha compartit »%s« amb tu",
+ "Click the button below to open it." : "Feu clic al botó següent per obrir-lo.",
+ "Open »%s«" : "Obre »%s«",
+ "%s via %s" : "%s via %s",
+ "The requested share does not exist anymore" : "El recurs sol·licitat ja no existeix",
+ "Could not find category \"%s\"" : "No s'ha trobat la categoria \"%s\"",
+ "Sunday" : "Diumenge",
+ "Monday" : "Dilluns",
+ "Tuesday" : "Dimarts",
+ "Wednesday" : "Dimecres",
+ "Thursday" : "Dijous",
+ "Friday" : "Divendres",
+ "Saturday" : "Dissabte",
+ "Sun." : "Dg.",
+ "Mon." : "Mon.",
+ "Tue." : "Dm.",
+ "Wed." : "Dc.",
+ "Thu." : "Dj.",
+ "Fri." : "Dv.",
+ "Sat." : "Ds.",
+ "Su" : "Dg",
+ "Mo" : "Dl",
+ "Tu" : "Dm",
+ "We" : "Dc",
+ "Th" : "Dj",
+ "Fr" : "Dv",
+ "Sa" : "Ds",
+ "January" : "Gener",
+ "February" : "Febrer",
+ "March" : "Març",
+ "April" : "Abril",
+ "May" : "Maig",
+ "June" : "Juny",
+ "July" : "Juliol",
+ "August" : "Agost",
+ "September" : "Setembre",
+ "October" : "Octubre",
+ "November" : "Novembre",
+ "December" : "Desembre",
+ "Jan." : "Gen.",
+ "Feb." : "Febr.",
+ "Mar." : "Març",
+ "Apr." : "Abr",
+ "May." : "Maig",
+ "Jun." : "Juny",
+ "Jul." : "Jul.",
+ "Aug." : "Ag.",
+ "Sep." : "Set",
+ "Oct." : "Oct.",
+ "Nov." : "Nov.",
+ "Dec." : "Des.",
+ "A valid username must be provided" : "Heu de facilitar un nom d'usuari vàlid",
+ "Username must not consist of dots only" : "El nom d'usuari no pot està format només per punts",
+ "A valid password must be provided" : "Heu de facilitar una contrasenya vàlida",
+ "The username is already being used" : "El nom d'usuari ja està en ús",
+ "Could not create user" : "No s'ha pogut crear l'usuari",
+ "User disabled" : "Usuari desactivat",
+ "Login canceled by app" : "Accés cancel·lat per l'App",
+ "a safe home for all your data" : "un lloc segur per a les teves dades",
+ "Can't read file" : "No es pot llegir el fitxer",
+ "Application is not enabled" : "L'aplicació no està habilitada",
+ "Authentication error" : "Error d'autenticació",
+ "Token expired. Please reload page." : "El testimoni ha expirat. Torneu a carregar la pàgina.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "No hi ha instal·lats controladors de bases de dades (sqlite, mysql o postgresql).",
+ "Cannot write into \"config\" directory" : "No es pot escriure a la carpeta \"config\"",
+ "Cannot write into \"apps\" directory" : "No es pot escriure a la carpeta \"apps\"",
+ "Setting locale to %s failed" : "Ha fallat en establir la llengua a %s",
+ "Please install one of these locales on your system and restart your webserver." : "Siusplau, instal·li un d'aquests arxius de localització en el seu sistema, i reinicii el seu servidor web.",
+ "Please ask your server administrator to install the module." : "Demaneu a l'administrador del sistema que instal·li el mòdul.",
+ "PHP module %s not installed." : "El mòdul PHP %s no està instal·lat.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Això probablement està provocat per una cau/accelerador com Zend OPcache o eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "S'han instal·lat mòduls PHP, però encara es llisten com una mancança?",
+ "Please ask your server administrator to restart the web server." : "Demaneu a l'administrador que reinici el servidor web.",
+ "PostgreSQL >= 9 required" : "Es requereix PostgreSQL >= 9",
+ "Please upgrade your database version" : "Actualitzeu la versió de la base de dades",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Canvieu els permisos a 0770 per tal que la carpeta no es pugui llistar per altres usuaris.",
+ "Could not obtain lock type %d on \"%s\"." : "No s'ha pogut obtenir un bloqueig tipus %d a \"%s\".",
+ "Personal" : "Personal",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consells i trucs",
+ "Sync clients" : "Aplicacions per sincronitzar"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/cs.js b/lib/l10n/cs.js
index 2b83480976a..8de62521afc 100644
--- a/lib/l10n/cs.js
+++ b/lib/l10n/cs.js
@@ -1,12 +1,12 @@
OC.L10N.register(
"lib",
{
- "Cannot write into \"config\" directory!" : "Nelze zapisovat do adresáře \"config\"!",
+ "Cannot write into \"config\" directory!" : "Nelze zapisovat do složky „config“!",
"This can usually be fixed by giving the webserver write access to the config directory" : "To lze obvykle vyřešit povolením zápisu webovému serveru do konfiguračního adresáře",
"See %s" : "Viz %s",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "To lze obvykle vyřešit povolením zápisu webovému serveru do konfiguračního adresáře. Viz %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Soubory aplikace %$1s nebyly řádně nahrazeny. Ujistěte se, že je to verze kompatibilní se serverem.",
- "Sample configuration detected" : "Byla detekována vzorová konfigurace",
+ "Sample configuration detected" : "Bylo zjištěno setrvání u předváděcího nastavení",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Pravděpodobně byla zkopírována konfigurační nastavení ze vzorových souborů. Toto není podporováno a může poškodit vaši instalaci. Nahlédněte prosím do dokumentace před prováděním změn v souboru config.php",
"%1$s and %2$s" : "%1$s a %2$s",
"%1$s, %2$s and %3$s" : "%1$s, %2$s a %3$s",
@@ -27,26 +27,27 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Jsou podporovány následující systémy: %s",
"Server version %s or higher is required." : "Je potřeba verze serveru %s nebo vyšší.",
"Server version %s or lower is required." : "Je potřeba verze serveru %s nebo nižší.",
+ "Logged in user must be an admin" : "Je třeba, aby přihlášený uživatel byl správce",
"Unknown filetype" : "Neznámý typ souboru",
"Invalid image" : "Chybný obrázek",
"Avatar image is not square" : "Avatar není čtvercový",
"today" : "dnes",
"tomorrow" : "zítra",
"yesterday" : "včera",
- "_in %n day_::_in %n days_" : ["během %n dne","během %n dnů","během %n dnů"],
- "_%n day ago_::_%n days ago_" : ["včera","před %n dny","před %n dny"],
+ "_in %n day_::_in %n days_" : ["během %n dne","během %n dnů","během %n dnů","během %n dnů"],
+ "_%n day ago_::_%n days ago_" : ["včera","před %n dny","před %n dny","před %n dny"],
"next month" : "následující měsíc",
"last month" : "minulý měsíc",
- "_in %n month_::_in %n months_" : ["během %n měsíce","během %n měsíců","během %n měsíců"],
- "_%n month ago_::_%n months ago_" : ["před %n měsícem","před %n měsíci","před %n měsíci"],
+ "_in %n month_::_in %n months_" : ["během %n měsíce","během %n měsíců","během %n měsíců","během %n měsíců"],
+ "_%n month ago_::_%n months ago_" : ["před %n měsícem","před %n měsíci","před %n měsíci","před %n měsíci"],
"next year" : "následující rok",
"last year" : "minulý rok",
- "_in %n year_::_in %n years_" : ["během %n roku","během %n roků","během %n roků"],
- "_%n year ago_::_%n years ago_" : ["před rokem","před %n lety","před %n lety"],
- "_in %n hour_::_in %n hours_" : ["během %n hodiny","během %n hodin","během %n hodin"],
- "_%n hour ago_::_%n hours ago_" : ["před %n hodinou","před %n hodinami","před %n hodinami"],
- "_in %n minute_::_in %n minutes_" : ["během %n minuty","během %n minut","během %n minut"],
- "_%n minute ago_::_%n minutes ago_" : ["před %n minutou","před %n minutami","před %n minutami"],
+ "_in %n year_::_in %n years_" : ["během %n roku","během %n roků","během %n roků","během %n roků"],
+ "_%n year ago_::_%n years ago_" : ["před rokem","před %n lety","před %n lety","před %n lety"],
+ "_in %n hour_::_in %n hours_" : ["během %n hodiny","během %n hodin","během %n hodin","během %n hodin"],
+ "_%n hour ago_::_%n hours ago_" : ["před %n hodinou","před %n hodinami","před %n hodinami","před %n hodinami"],
+ "_in %n minute_::_in %n minutes_" : ["během %n minuty","během %n minut","během %n minut","během %n minut"],
+ "_%n minute ago_::_%n minutes ago_" : ["před %n minutou","před %n minutami","před %n minutami","před %n minutami"],
"in a few seconds" : "během několika sekund",
"seconds ago" : "před pár sekundami",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul s ID: %s neexistuje. Povolte ho v nastavení aplikací, nebo kontaktujte vašeho administrátora.",
@@ -57,6 +58,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Prázdné jméno souboru není povoleno",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Aplikace \"%s\" nemůže být nainstalována protože soubor appinfo nelze přečíst.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Aplikaci \"%s\" nelze nainstalovat, protože není kompatibilní s touto verzí serveru.",
+ "__language_name__" : "Česky",
"This is an automatically sent email, please do not reply." : "Toto je automaticky odesílaný e-mail, prosím, neodpovídejte.",
"Help" : "Nápověda",
"Apps" : "Aplikace",
@@ -64,18 +66,18 @@ OC.L10N.register(
"Log out" : "Odhlásit se",
"Users" : "Uživatelé",
"Unknown user" : "Neznámý uživatel",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Vytvořit",
+ "Change" : "Změnit",
+ "Delete" : "Smazat",
+ "Share" : "Sdílet",
+ "Overview" : "Přehled",
"Basic settings" : "Základní nastavení",
"Sharing" : "Sdílení",
"Security" : "Zabezpečení",
"Encryption" : "Šifrování",
"Additional settings" : "Dodatečná nastavení",
- "Tips & tricks" : "Tipy a triky",
"Personal info" : "Osobní informace",
- "Sync clients" : "Synchronizační klienti",
"Unlimited" : "Neomezeně",
- "__language_name__" : "Česky",
"Verifying" : "Ověření",
"Verifying …" : "Ověřování …",
"Verify" : "Ověřit",
@@ -227,6 +229,14 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Nekompletní konfigurace úložiště. %s",
"Storage connection error. %s" : "Chyba připojení úložiště. %s",
"Storage is temporarily not available" : "Úložiště je dočasně nedostupné",
- "Storage connection timeout. %s" : "Vypršení připojení k úložišti. %s"
+ "Storage connection timeout. %s" : "Vypršení připojení k úložišti. %s",
+ "Personal" : "Osobní",
+ "Admin" : "Správce",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tipy a triky",
+ "DB Error: \"%s\"" : "Chyba databáze: „%s“",
+ "No app name specified" : "Nezadán název aplikace",
+ "Sync clients" : "Synchronizační klienti"
},
-"nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;");
+"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;");
diff --git a/lib/l10n/cs.json b/lib/l10n/cs.json
index cd002244802..0c5c7309b03 100644
--- a/lib/l10n/cs.json
+++ b/lib/l10n/cs.json
@@ -1,10 +1,10 @@
{ "translations": {
- "Cannot write into \"config\" directory!" : "Nelze zapisovat do adresáře \"config\"!",
+ "Cannot write into \"config\" directory!" : "Nelze zapisovat do složky „config“!",
"This can usually be fixed by giving the webserver write access to the config directory" : "To lze obvykle vyřešit povolením zápisu webovému serveru do konfiguračního adresáře",
"See %s" : "Viz %s",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "To lze obvykle vyřešit povolením zápisu webovému serveru do konfiguračního adresáře. Viz %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Soubory aplikace %$1s nebyly řádně nahrazeny. Ujistěte se, že je to verze kompatibilní se serverem.",
- "Sample configuration detected" : "Byla detekována vzorová konfigurace",
+ "Sample configuration detected" : "Bylo zjištěno setrvání u předváděcího nastavení",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Pravděpodobně byla zkopírována konfigurační nastavení ze vzorových souborů. Toto není podporováno a může poškodit vaši instalaci. Nahlédněte prosím do dokumentace před prováděním změn v souboru config.php",
"%1$s and %2$s" : "%1$s a %2$s",
"%1$s, %2$s and %3$s" : "%1$s, %2$s a %3$s",
@@ -25,26 +25,27 @@
"Following platforms are supported: %s" : "Jsou podporovány následující systémy: %s",
"Server version %s or higher is required." : "Je potřeba verze serveru %s nebo vyšší.",
"Server version %s or lower is required." : "Je potřeba verze serveru %s nebo nižší.",
+ "Logged in user must be an admin" : "Je třeba, aby přihlášený uživatel byl správce",
"Unknown filetype" : "Neznámý typ souboru",
"Invalid image" : "Chybný obrázek",
"Avatar image is not square" : "Avatar není čtvercový",
"today" : "dnes",
"tomorrow" : "zítra",
"yesterday" : "včera",
- "_in %n day_::_in %n days_" : ["během %n dne","během %n dnů","během %n dnů"],
- "_%n day ago_::_%n days ago_" : ["včera","před %n dny","před %n dny"],
+ "_in %n day_::_in %n days_" : ["během %n dne","během %n dnů","během %n dnů","během %n dnů"],
+ "_%n day ago_::_%n days ago_" : ["včera","před %n dny","před %n dny","před %n dny"],
"next month" : "následující měsíc",
"last month" : "minulý měsíc",
- "_in %n month_::_in %n months_" : ["během %n měsíce","během %n měsíců","během %n měsíců"],
- "_%n month ago_::_%n months ago_" : ["před %n měsícem","před %n měsíci","před %n měsíci"],
+ "_in %n month_::_in %n months_" : ["během %n měsíce","během %n měsíců","během %n měsíců","během %n měsíců"],
+ "_%n month ago_::_%n months ago_" : ["před %n měsícem","před %n měsíci","před %n měsíci","před %n měsíci"],
"next year" : "následující rok",
"last year" : "minulý rok",
- "_in %n year_::_in %n years_" : ["během %n roku","během %n roků","během %n roků"],
- "_%n year ago_::_%n years ago_" : ["před rokem","před %n lety","před %n lety"],
- "_in %n hour_::_in %n hours_" : ["během %n hodiny","během %n hodin","během %n hodin"],
- "_%n hour ago_::_%n hours ago_" : ["před %n hodinou","před %n hodinami","před %n hodinami"],
- "_in %n minute_::_in %n minutes_" : ["během %n minuty","během %n minut","během %n minut"],
- "_%n minute ago_::_%n minutes ago_" : ["před %n minutou","před %n minutami","před %n minutami"],
+ "_in %n year_::_in %n years_" : ["během %n roku","během %n roků","během %n roků","během %n roků"],
+ "_%n year ago_::_%n years ago_" : ["před rokem","před %n lety","před %n lety","před %n lety"],
+ "_in %n hour_::_in %n hours_" : ["během %n hodiny","během %n hodin","během %n hodin","během %n hodin"],
+ "_%n hour ago_::_%n hours ago_" : ["před %n hodinou","před %n hodinami","před %n hodinami","před %n hodinami"],
+ "_in %n minute_::_in %n minutes_" : ["během %n minuty","během %n minut","během %n minut","během %n minut"],
+ "_%n minute ago_::_%n minutes ago_" : ["před %n minutou","před %n minutami","před %n minutami","před %n minutami"],
"in a few seconds" : "během několika sekund",
"seconds ago" : "před pár sekundami",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul s ID: %s neexistuje. Povolte ho v nastavení aplikací, nebo kontaktujte vašeho administrátora.",
@@ -55,6 +56,7 @@
"Empty filename is not allowed" : "Prázdné jméno souboru není povoleno",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Aplikace \"%s\" nemůže být nainstalována protože soubor appinfo nelze přečíst.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Aplikaci \"%s\" nelze nainstalovat, protože není kompatibilní s touto verzí serveru.",
+ "__language_name__" : "Česky",
"This is an automatically sent email, please do not reply." : "Toto je automaticky odesílaný e-mail, prosím, neodpovídejte.",
"Help" : "Nápověda",
"Apps" : "Aplikace",
@@ -62,18 +64,18 @@
"Log out" : "Odhlásit se",
"Users" : "Uživatelé",
"Unknown user" : "Neznámý uživatel",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Vytvořit",
+ "Change" : "Změnit",
+ "Delete" : "Smazat",
+ "Share" : "Sdílet",
+ "Overview" : "Přehled",
"Basic settings" : "Základní nastavení",
"Sharing" : "Sdílení",
"Security" : "Zabezpečení",
"Encryption" : "Šifrování",
"Additional settings" : "Dodatečná nastavení",
- "Tips & tricks" : "Tipy a triky",
"Personal info" : "Osobní informace",
- "Sync clients" : "Synchronizační klienti",
"Unlimited" : "Neomezeně",
- "__language_name__" : "Česky",
"Verifying" : "Ověření",
"Verifying …" : "Ověřování …",
"Verify" : "Ověřit",
@@ -225,6 +227,14 @@
"Storage incomplete configuration. %s" : "Nekompletní konfigurace úložiště. %s",
"Storage connection error. %s" : "Chyba připojení úložiště. %s",
"Storage is temporarily not available" : "Úložiště je dočasně nedostupné",
- "Storage connection timeout. %s" : "Vypršení připojení k úložišti. %s"
-},"pluralForm" :"nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"
+ "Storage connection timeout. %s" : "Vypršení připojení k úložišti. %s",
+ "Personal" : "Osobní",
+ "Admin" : "Správce",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tipy a triky",
+ "DB Error: \"%s\"" : "Chyba databáze: „%s“",
+ "No app name specified" : "Nezadán název aplikace",
+ "Sync clients" : "Synchronizační klienti"
+},"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;"
} \ No newline at end of file
diff --git a/lib/l10n/cy_GB.js b/lib/l10n/cy_GB.js
new file mode 100644
index 00000000000..31291c97bd7
--- /dev/null
+++ b/lib/l10n/cy_GB.js
@@ -0,0 +1,23 @@
+OC.L10N.register(
+ "lib",
+ {
+ "today" : "heddiw",
+ "yesterday" : "ddoe",
+ "last month" : "mis diwethaf",
+ "last year" : "y llynedd",
+ "seconds ago" : "eiliad yn ôl",
+ "Apps" : "Pecynnau",
+ "Users" : "Defnyddwyr",
+ "%s enter the database username." : "%s rhowch enw defnyddiwr y gronfa ddata.",
+ "%s enter the database name." : "%s rhowch enw'r gronfa ddata.",
+ "%s you may not use dots in the database name" : "%s does dim hawl defnyddio dot yn enw'r gronfa ddata",
+ "Oracle username and/or password not valid" : "Enw a/neu gyfrinair Oracle annilys",
+ "PostgreSQL username and/or password not valid" : "Enw a/neu gyfrinair PostgreSQL annilys",
+ "Set an admin username." : "Creu enw defnyddiwr i'r gweinyddwr.",
+ "Set an admin password." : "Gosod cyfrinair y gweinyddwr.",
+ "Could not find category \"%s\"" : "Methu canfod categori \"%s\"",
+ "Application is not enabled" : "Nid yw'r pecyn wedi'i alluogi",
+ "Authentication error" : "Gwall dilysu",
+ "Token expired. Please reload page." : "Tocyn wedi dod i ben. Ail-lwythwch y dudalen."
+},
+"nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;");
diff --git a/lib/l10n/cy_GB.json b/lib/l10n/cy_GB.json
new file mode 100644
index 00000000000..6e931922349
--- /dev/null
+++ b/lib/l10n/cy_GB.json
@@ -0,0 +1,21 @@
+{ "translations": {
+ "today" : "heddiw",
+ "yesterday" : "ddoe",
+ "last month" : "mis diwethaf",
+ "last year" : "y llynedd",
+ "seconds ago" : "eiliad yn ôl",
+ "Apps" : "Pecynnau",
+ "Users" : "Defnyddwyr",
+ "%s enter the database username." : "%s rhowch enw defnyddiwr y gronfa ddata.",
+ "%s enter the database name." : "%s rhowch enw'r gronfa ddata.",
+ "%s you may not use dots in the database name" : "%s does dim hawl defnyddio dot yn enw'r gronfa ddata",
+ "Oracle username and/or password not valid" : "Enw a/neu gyfrinair Oracle annilys",
+ "PostgreSQL username and/or password not valid" : "Enw a/neu gyfrinair PostgreSQL annilys",
+ "Set an admin username." : "Creu enw defnyddiwr i'r gweinyddwr.",
+ "Set an admin password." : "Gosod cyfrinair y gweinyddwr.",
+ "Could not find category \"%s\"" : "Methu canfod categori \"%s\"",
+ "Application is not enabled" : "Nid yw'r pecyn wedi'i alluogi",
+ "Authentication error" : "Gwall dilysu",
+ "Token expired. Please reload page." : "Tocyn wedi dod i ben. Ail-lwythwch y dudalen."
+},"pluralForm" :"nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;"
+} \ No newline at end of file
diff --git a/lib/l10n/da.js b/lib/l10n/da.js
new file mode 100644
index 00000000000..32de8c677cb
--- /dev/null
+++ b/lib/l10n/da.js
@@ -0,0 +1,111 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Kan ikke skrive til mappen \"config\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Dette kan som regel ordnes ved at give webserveren skrive adgang til config mappen",
+ "See %s" : "Se %s",
+ "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dette kan som regel ordnes ved at give webserveren skrive adgang til config mappen. Se %s",
+ "Sample configuration detected" : "Eksempel for konfiguration registreret",
+ "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" : "Der er registreret at eksempel for konfiguration er blevet kopieret. Dette kan ødelægge din installation og understøttes ikke. Læs venligst dokumentationen før der foretages ændringer i config.php",
+ "PHP %s or higher is required." : "Der kræves PHP %s eller nyere.",
+ "PHP with a version lower than %s is required." : "Der kræves PHP %s eller ældre.",
+ "Following databases are supported: %s" : "Følgende databaser understøttes: %s",
+ "The command line tool %s could not be found" : "Kommandolinjeværktøjet %s blev ikke fundet",
+ "The library %s is not available." : "Biblioteket %s er ikke tilgængeligt.",
+ "Library %s with a version higher than %s is required - available version %s." : "Der kræves en version af biblioteket %s, der er højere end %s - tilgængelig version er %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "Der kræves en version af biblioteket %s, der er lavere end %s - tilgængelig version er %s.",
+ "Following platforms are supported: %s" : "Følgende platforme understøttes: %s",
+ "Unknown filetype" : "Ukendt filtype",
+ "Invalid image" : "Ugyldigt billede",
+ "today" : "i dag",
+ "yesterday" : "i går",
+ "_%n day ago_::_%n days ago_" : ["%n dag siden","%n dage siden"],
+ "last month" : "sidste måned",
+ "_%n month ago_::_%n months ago_" : ["%n måned siden","%n måneder siden"],
+ "last year" : "sidste år",
+ "_%n year ago_::_%n years ago_" : ["%n år siden","%n år siden"],
+ "_%n hour ago_::_%n hours ago_" : ["%n time siden","%n timer siden"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n minut siden","%n minutter siden"],
+ "seconds ago" : "sekunder siden",
+ "File name is a reserved word" : "Filnavnet er et reserveret ord",
+ "File name contains at least one invalid character" : "Filnavnet indeholder mindst ét ugyldigt tegn",
+ "File name is too long" : "Filnavnet er for langt",
+ "Dot files are not allowed" : "Filer med punktummer er ikke tilladt",
+ "Empty filename is not allowed" : "Tomme filnavne er ikke tilladt",
+ "__language_name__" : "Dansk",
+ "Apps" : "Apps",
+ "Users" : "Brugere",
+ "Unknown user" : "Ukendt bruger",
+ "%s enter the database username." : "%s indtast database brugernavnet.",
+ "%s enter the database name." : "%s indtast database navnet.",
+ "%s you may not use dots in the database name" : "%s du må ikke bruge punktummer i databasenavnet.",
+ "Oracle connection could not be established" : "Oracle forbindelsen kunne ikke etableres",
+ "Oracle username and/or password not valid" : "Oracle brugernavn og/eller kodeord er ikke gyldigt.",
+ "PostgreSQL username and/or password not valid" : "PostgreSQL brugernavn og/eller kodeord er ikke gyldigt.",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X understøttes ikke og %s vil ikke virke optimalt på denne platform. Anvend på eget ansvar!",
+ "For the best results, please consider using a GNU/Linux server instead." : "For de bedste resultater, overvej venligst at bruge en GNU/Linux-server i stedet.",
+ "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." : "Det ser ud til, at denne %s-instans kører på et 32-bit PHP-miljø, samt at open_basedir er blevet konfigureret gennem php.ini. Dette vil føre til problemer med filer som er større end 4GB, og frarådes kraftigt.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Fjern venligst indstillingen for open_basedir inde i din php.ini eller skift til 64-bit PHP.",
+ "Set an admin username." : "Angiv et admin brugernavn.",
+ "Set an admin password." : "Angiv et admin kodeord.",
+ "Can't create or write into the data directory %s" : "Kan ikke oprette eller skrive ind i datamappen %s",
+ "Invalid Federated Cloud ID" : "Ugyldigt Federated Cloud ID",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "Deling af %s mislykkedes, fordi backenden ikke tillader delinger fra typen %i",
+ "Sharing %s failed, because the file does not exist" : "Deling af %s mislykkedes, fordi filen ikke eksisterer",
+ "You are not allowed to share %s" : "Du har ikke tilladelse til at dele %s",
+ "Sharing %s failed, because you can not share with yourself" : "Deling af %s mislykkedes, fordi du ikke kan dele med dig selv",
+ "Sharing %s failed, because the user %s does not exist" : "Der skete en fejl ved deling af %s, brugeren %s eksistere ikke",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Der skete en fejl ved deling af %s, brugeren %s er ikke medlem af nogle grupper som %s er medlem af",
+ "Sharing %s failed, because this item is already shared with %s" : "Der skete en fejl ved deling af %s, objektet er allerede delt med %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "Deling af %s mislykkedes, fordi dette element allerede er delt med brugeren %s",
+ "Sharing %s failed, because the group %s does not exist" : "Der skete en fejl ved deling af %s, gruppen %s eksistere ikke",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Der skete en fejl ved deling af %s, fordi %s ikke er medlem af gruppen %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Du skal angive et kodeord for at oprette et offentligt link - kun beskyttede links er tilladt",
+ "Sharing %s failed, because sharing with links is not allowed" : "Der skete en fejl ved deling af %s, det er ikke tilladt at dele links",
+ "Not allowed to create a federated share with the same user" : "Det er ikke tilladt at danne et datafællesskab med samme bruger",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Deling af %s mislykkedes - kunne ikke finde %s. Måske er serveren ikke tilgængelig i øjeblikket.",
+ "Share type %s is not valid for %s" : "Delingstypen %s er ikke gyldig for %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Kan ikke angive udløbsdato. Delinger kan ikke udløbe senere end %s efter at de er blevet delt",
+ "Cannot set expiration date. Expiration date is in the past" : "Kan ikke angive udløbsdato. Udløbsdato er allerede passeret",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Delingsbackend'en %s skal implementere grænsefladen OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Delingsbackend'en %s blev ikke fundet",
+ "Sharing backend for %s not found" : "Delingsbackend'en for %s blev ikke fundet",
+ "Sharing failed, because the user %s is the original sharer" : "Deling mislykkedes, fordi brugeren %s er den som delte oprindeligt",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Deling af %s mislykkedes, fordi tilladelserne overskred de tillaldelser som %s var tildelt",
+ "Sharing %s failed, because resharing is not allowed" : "Deling af %s mislykkedes, fordi videredeling ikke er tilladt",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Deling af %s mislykkedes, fordi back-enden ikke kunne finde kilden til %s",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Deling af %s mislykkedes, fordi filen ikke kunne findes i fil-cachen",
+ "Expiration date is in the past" : "Udløbsdatoen ligger tilbage i tid",
+ "%s shared »%s« with you" : "%s delte »%s« med dig",
+ "%s via %s" : "%s via %s",
+ "Could not find category \"%s\"" : "Kunne ikke finde kategorien \"%s\"",
+ "A valid username must be provided" : "Et gyldigt brugernavn skal angives",
+ "A valid password must be provided" : "En gyldig adgangskode skal angives",
+ "The username is already being used" : "Brugernavnet er allerede i brug",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "App'en \"%s\" kan ikke installeres, da følgende krav ikke er opfyldt: %s ",
+ "File is currently busy, please try again later" : "Filen er i øjeblikket optaget - forsøg igen senere",
+ "Can't read file" : "Kan ikke læse filen",
+ "Application is not enabled" : "Programmet er ikke aktiveret",
+ "Authentication error" : "Adgangsfejl",
+ "Token expired. Please reload page." : "Adgang er udløbet. Genindlæs siden.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Ingen database driver (sqlite, mysql eller postgresql) er installeret.",
+ "Cannot write into \"config\" directory" : "Kan ikke skrive til mappen \"config\"",
+ "Cannot write into \"apps\" directory" : "Kan ikke skrive til mappen \"apps\"",
+ "Setting locale to %s failed" : "Angivelse af %s for lokalitet mislykkedes",
+ "Please install one of these locales on your system and restart your webserver." : "Installér venligst én af disse lokaliteter på dit system, og genstart din webserver.",
+ "Please ask your server administrator to install the module." : "Du bedes anmode din serveradministrator om at installere modulet.",
+ "PHP module %s not installed." : "PHP-modulet %s er ikke installeret.",
+ "PHP setting \"%s\" is not set to \"%s\"." : "PHP-indstillingen \"%s\" er ikke angivet til \"%s\".",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload er angivet til \"%s\", i stedet for den forventede værdi \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "For at rette dette problem, angiv\n<code>mbstring.func_overload</code> til <code>0</code> i din php.ini",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP er tilsyneladende sat op til at fjerne indlejrede doc-blokke. Dette vil gøre adskillige kerneprogrammer utilgængelige.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dette er sansynligvis forårsaget af et accelerator eller cache som Zend OPcache eller eAccelerator",
+ "PHP modules have been installed, but they are still listed as missing?" : "Der er installeret PHP-moduler, men de fremstår stadig som fraværende?",
+ "Please ask your server administrator to restart the web server." : "Du bedes anmode din serveradministrator om at genstarte webserveren.",
+ "PostgreSQL >= 9 required" : "PostgreSQL >= 9 kræves",
+ "Please upgrade your database version" : "Opgradér venligst din databaseversion",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Tilpas venligst rettigheder til 0770, så mappen ikke fremvises for andre brugere.",
+ "Check the value of \"datadirectory\" in your configuration" : "Tjek værdien for \"databibliotek\" i din konfiguration",
+ "Could not obtain lock type %d on \"%s\"." : "Kunne ikke opnå en låsetype %d på \"%s\"."
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/da.json b/lib/l10n/da.json
new file mode 100644
index 00000000000..3225b0ffa36
--- /dev/null
+++ b/lib/l10n/da.json
@@ -0,0 +1,109 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Kan ikke skrive til mappen \"config\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Dette kan som regel ordnes ved at give webserveren skrive adgang til config mappen",
+ "See %s" : "Se %s",
+ "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dette kan som regel ordnes ved at give webserveren skrive adgang til config mappen. Se %s",
+ "Sample configuration detected" : "Eksempel for konfiguration registreret",
+ "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" : "Der er registreret at eksempel for konfiguration er blevet kopieret. Dette kan ødelægge din installation og understøttes ikke. Læs venligst dokumentationen før der foretages ændringer i config.php",
+ "PHP %s or higher is required." : "Der kræves PHP %s eller nyere.",
+ "PHP with a version lower than %s is required." : "Der kræves PHP %s eller ældre.",
+ "Following databases are supported: %s" : "Følgende databaser understøttes: %s",
+ "The command line tool %s could not be found" : "Kommandolinjeværktøjet %s blev ikke fundet",
+ "The library %s is not available." : "Biblioteket %s er ikke tilgængeligt.",
+ "Library %s with a version higher than %s is required - available version %s." : "Der kræves en version af biblioteket %s, der er højere end %s - tilgængelig version er %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "Der kræves en version af biblioteket %s, der er lavere end %s - tilgængelig version er %s.",
+ "Following platforms are supported: %s" : "Følgende platforme understøttes: %s",
+ "Unknown filetype" : "Ukendt filtype",
+ "Invalid image" : "Ugyldigt billede",
+ "today" : "i dag",
+ "yesterday" : "i går",
+ "_%n day ago_::_%n days ago_" : ["%n dag siden","%n dage siden"],
+ "last month" : "sidste måned",
+ "_%n month ago_::_%n months ago_" : ["%n måned siden","%n måneder siden"],
+ "last year" : "sidste år",
+ "_%n year ago_::_%n years ago_" : ["%n år siden","%n år siden"],
+ "_%n hour ago_::_%n hours ago_" : ["%n time siden","%n timer siden"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n minut siden","%n minutter siden"],
+ "seconds ago" : "sekunder siden",
+ "File name is a reserved word" : "Filnavnet er et reserveret ord",
+ "File name contains at least one invalid character" : "Filnavnet indeholder mindst ét ugyldigt tegn",
+ "File name is too long" : "Filnavnet er for langt",
+ "Dot files are not allowed" : "Filer med punktummer er ikke tilladt",
+ "Empty filename is not allowed" : "Tomme filnavne er ikke tilladt",
+ "__language_name__" : "Dansk",
+ "Apps" : "Apps",
+ "Users" : "Brugere",
+ "Unknown user" : "Ukendt bruger",
+ "%s enter the database username." : "%s indtast database brugernavnet.",
+ "%s enter the database name." : "%s indtast database navnet.",
+ "%s you may not use dots in the database name" : "%s du må ikke bruge punktummer i databasenavnet.",
+ "Oracle connection could not be established" : "Oracle forbindelsen kunne ikke etableres",
+ "Oracle username and/or password not valid" : "Oracle brugernavn og/eller kodeord er ikke gyldigt.",
+ "PostgreSQL username and/or password not valid" : "PostgreSQL brugernavn og/eller kodeord er ikke gyldigt.",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X understøttes ikke og %s vil ikke virke optimalt på denne platform. Anvend på eget ansvar!",
+ "For the best results, please consider using a GNU/Linux server instead." : "For de bedste resultater, overvej venligst at bruge en GNU/Linux-server i stedet.",
+ "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." : "Det ser ud til, at denne %s-instans kører på et 32-bit PHP-miljø, samt at open_basedir er blevet konfigureret gennem php.ini. Dette vil føre til problemer med filer som er større end 4GB, og frarådes kraftigt.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Fjern venligst indstillingen for open_basedir inde i din php.ini eller skift til 64-bit PHP.",
+ "Set an admin username." : "Angiv et admin brugernavn.",
+ "Set an admin password." : "Angiv et admin kodeord.",
+ "Can't create or write into the data directory %s" : "Kan ikke oprette eller skrive ind i datamappen %s",
+ "Invalid Federated Cloud ID" : "Ugyldigt Federated Cloud ID",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "Deling af %s mislykkedes, fordi backenden ikke tillader delinger fra typen %i",
+ "Sharing %s failed, because the file does not exist" : "Deling af %s mislykkedes, fordi filen ikke eksisterer",
+ "You are not allowed to share %s" : "Du har ikke tilladelse til at dele %s",
+ "Sharing %s failed, because you can not share with yourself" : "Deling af %s mislykkedes, fordi du ikke kan dele med dig selv",
+ "Sharing %s failed, because the user %s does not exist" : "Der skete en fejl ved deling af %s, brugeren %s eksistere ikke",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Der skete en fejl ved deling af %s, brugeren %s er ikke medlem af nogle grupper som %s er medlem af",
+ "Sharing %s failed, because this item is already shared with %s" : "Der skete en fejl ved deling af %s, objektet er allerede delt med %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "Deling af %s mislykkedes, fordi dette element allerede er delt med brugeren %s",
+ "Sharing %s failed, because the group %s does not exist" : "Der skete en fejl ved deling af %s, gruppen %s eksistere ikke",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Der skete en fejl ved deling af %s, fordi %s ikke er medlem af gruppen %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Du skal angive et kodeord for at oprette et offentligt link - kun beskyttede links er tilladt",
+ "Sharing %s failed, because sharing with links is not allowed" : "Der skete en fejl ved deling af %s, det er ikke tilladt at dele links",
+ "Not allowed to create a federated share with the same user" : "Det er ikke tilladt at danne et datafællesskab med samme bruger",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Deling af %s mislykkedes - kunne ikke finde %s. Måske er serveren ikke tilgængelig i øjeblikket.",
+ "Share type %s is not valid for %s" : "Delingstypen %s er ikke gyldig for %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Kan ikke angive udløbsdato. Delinger kan ikke udløbe senere end %s efter at de er blevet delt",
+ "Cannot set expiration date. Expiration date is in the past" : "Kan ikke angive udløbsdato. Udløbsdato er allerede passeret",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Delingsbackend'en %s skal implementere grænsefladen OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Delingsbackend'en %s blev ikke fundet",
+ "Sharing backend for %s not found" : "Delingsbackend'en for %s blev ikke fundet",
+ "Sharing failed, because the user %s is the original sharer" : "Deling mislykkedes, fordi brugeren %s er den som delte oprindeligt",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Deling af %s mislykkedes, fordi tilladelserne overskred de tillaldelser som %s var tildelt",
+ "Sharing %s failed, because resharing is not allowed" : "Deling af %s mislykkedes, fordi videredeling ikke er tilladt",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Deling af %s mislykkedes, fordi back-enden ikke kunne finde kilden til %s",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Deling af %s mislykkedes, fordi filen ikke kunne findes i fil-cachen",
+ "Expiration date is in the past" : "Udløbsdatoen ligger tilbage i tid",
+ "%s shared »%s« with you" : "%s delte »%s« med dig",
+ "%s via %s" : "%s via %s",
+ "Could not find category \"%s\"" : "Kunne ikke finde kategorien \"%s\"",
+ "A valid username must be provided" : "Et gyldigt brugernavn skal angives",
+ "A valid password must be provided" : "En gyldig adgangskode skal angives",
+ "The username is already being used" : "Brugernavnet er allerede i brug",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "App'en \"%s\" kan ikke installeres, da følgende krav ikke er opfyldt: %s ",
+ "File is currently busy, please try again later" : "Filen er i øjeblikket optaget - forsøg igen senere",
+ "Can't read file" : "Kan ikke læse filen",
+ "Application is not enabled" : "Programmet er ikke aktiveret",
+ "Authentication error" : "Adgangsfejl",
+ "Token expired. Please reload page." : "Adgang er udløbet. Genindlæs siden.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Ingen database driver (sqlite, mysql eller postgresql) er installeret.",
+ "Cannot write into \"config\" directory" : "Kan ikke skrive til mappen \"config\"",
+ "Cannot write into \"apps\" directory" : "Kan ikke skrive til mappen \"apps\"",
+ "Setting locale to %s failed" : "Angivelse af %s for lokalitet mislykkedes",
+ "Please install one of these locales on your system and restart your webserver." : "Installér venligst én af disse lokaliteter på dit system, og genstart din webserver.",
+ "Please ask your server administrator to install the module." : "Du bedes anmode din serveradministrator om at installere modulet.",
+ "PHP module %s not installed." : "PHP-modulet %s er ikke installeret.",
+ "PHP setting \"%s\" is not set to \"%s\"." : "PHP-indstillingen \"%s\" er ikke angivet til \"%s\".",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload er angivet til \"%s\", i stedet for den forventede værdi \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "For at rette dette problem, angiv\n<code>mbstring.func_overload</code> til <code>0</code> i din php.ini",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP er tilsyneladende sat op til at fjerne indlejrede doc-blokke. Dette vil gøre adskillige kerneprogrammer utilgængelige.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dette er sansynligvis forårsaget af et accelerator eller cache som Zend OPcache eller eAccelerator",
+ "PHP modules have been installed, but they are still listed as missing?" : "Der er installeret PHP-moduler, men de fremstår stadig som fraværende?",
+ "Please ask your server administrator to restart the web server." : "Du bedes anmode din serveradministrator om at genstarte webserveren.",
+ "PostgreSQL >= 9 required" : "PostgreSQL >= 9 kræves",
+ "Please upgrade your database version" : "Opgradér venligst din databaseversion",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Tilpas venligst rettigheder til 0770, så mappen ikke fremvises for andre brugere.",
+ "Check the value of \"datadirectory\" in your configuration" : "Tjek værdien for \"databibliotek\" i din konfiguration",
+ "Could not obtain lock type %d on \"%s\"." : "Kunne ikke opnå en låsetype %d på \"%s\"."
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/de.js b/lib/l10n/de.js
index 066f2ed5bb1..9aab5f4ad70 100644
--- a/lib/l10n/de.js
+++ b/lib/l10n/de.js
@@ -4,7 +4,9 @@ OC.L10N.register(
"Cannot write into \"config\" directory!" : "Das Schreiben in das „config“-Verzeichnis ist nicht möglich!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Dies kann normalerweise repariert werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird",
"See %s" : "Siehe %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Oder wenn Du möchtest, dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf True.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dies kann zumeist behoben werden, indem dem Web-Server Schreibzugriff auf das Konfigurationsverzeichnis eingeräumt wird. Siehe auch %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Oder wenn Du möchtest, dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf True. Siehe %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Die Dateien der App %$1s wurden nicht korrekt ersetzt. Stelle sicher, dass die Version mit dem Server kompatibel ist.",
"Sample configuration detected" : "Beispielkonfiguration gefunden",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann Deine Installation zerstören und wird nicht unterstützt. Bitte die Dokumentation lesen, bevor Änderungen an der config.php vorgenommen werden.",
@@ -27,6 +29,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Die folgenden Plattformen werden unterstützt: %s",
"Server version %s or higher is required." : "Server Version %s oder höher wird benötigt.",
"Server version %s or lower is required." : "Server Version %s oder niedriger wird benötigt.",
+ "Logged in user must be an admin" : "Der angemeldete Benutzer muss ein Administrator sein",
"Unknown filetype" : "Unbekannter Dateityp",
"Invalid image" : "Ungültiges Bild",
"Avatar image is not square" : "Benutzerbild ist nicht quadratisch",
@@ -57,6 +60,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Ein leerer Dateiname ist nicht erlaubt",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Die Anwendung \"%s\" kann nicht installiert werden, weil die Anwendungsinfodatei nicht gelesen werden kann.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Die App \"%s\" kann nicht installiert werden, da sie mit dieser Serverversion nicht kompatibel ist.",
+ "__language_name__" : "Deutsch (Persönlich: Du)",
"This is an automatically sent email, please do not reply." : "Dies ist eine automatisch versandte E-Mail, bitte nicht antworten.",
"Help" : "Hilfe",
"Apps" : "Apps",
@@ -64,18 +68,20 @@ OC.L10N.register(
"Log out" : "Abmelden",
"Users" : "Benutzer",
"Unknown user" : "Unbekannter Benutzer",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Anlegen",
+ "Change" : "Ändern",
+ "Delete" : "Löschen",
+ "Share" : "Teilen",
+ "Overview" : "Übersicht",
"Basic settings" : "Grundeinstellungen",
"Sharing" : "Teilen",
"Security" : "Sicherheit",
"Encryption" : "Verschlüsselung",
+ "Groupware" : "Groupware",
"Additional settings" : "Zusätzliche Einstellungen",
- "Tips & tricks" : "Tipps & Tricks",
"Personal info" : "Persönliche Informationen ",
- "Sync clients" : " Sync-Clients ",
+ "Mobile & desktop" : "Mobil & Desktop",
"Unlimited" : "Unbegrenzt",
- "__language_name__" : " Deutsch (Persönlich: Du) ",
"Verifying" : "Überprüfe",
"Verifying …" : " Überprüfe… ",
"Verify" : "Überprüfen",
@@ -222,6 +228,11 @@ OC.L10N.register(
"Check the value of \"datadirectory\" in your configuration" : "Überprüfe bitte die Angabe unter „datadirectory“ in Deiner Konfiguration",
"Your data directory is invalid" : "Dein Datenverzeichnis ist ungültig",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stelle sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des data-Verzeichnisses existiert.",
+ "Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.",
+ "Authentication failed, wrong token or provider ID given" : "Authentifizierung ist fehlgeschlagen. Falsches Token oder Provider-ID wurde übertragen.",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Es fehlen Parameter um die Anfrage zu bearbeiten. Fehlende Parameter: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "ID \"%s\" wird bereits von Cloud-Federation-Provider \"%s\" verwendet",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud-Federation-Provider mit ID: \"%s\" ist nicht vorhanden.",
"Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf „%s“ konnte nicht ermittelt werden.",
"Storage unauthorized. %s" : "Speicher nicht authorisiert. %s",
"Storage incomplete configuration. %s" : "Speicher-Konfiguration unvollständig. %s",
@@ -230,6 +241,9 @@ OC.L10N.register(
"Storage connection timeout. %s" : "Zeitüberschreitung der Verbindung zum Speicherplatz. %s",
"Personal" : "Persönlich",
"Admin" : "Administrator",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tipps & Tricks",
"DB Error: \"%s\"" : "DB-Fehler: \"%s“",
"Offending command was: \"%s\"" : "Fehlerhafter Befehl war: \"%s“",
"Offending command was: \"%s\", name: %s, password: %s" : "Fehlerhafter Befehl war: \"%s“, Name: %s, Passwort: %s",
@@ -241,6 +255,7 @@ OC.L10N.register(
"Files can't be shared with create permissions" : "Dateien mit Erstell-Berechtigungen können nicht geteilt werden",
"Cannot set expiration date more than %s days in the future" : "Das Ablaufdatum kann nicht mehr als %s Tage in die Zukunft liegen",
"No app name specified" : "Es wurde kein App-Name angegeben",
- "App '%s' could not be installed!" : "App '%s' konnte nicht installiert werden!"
+ "App '%s' could not be installed!" : "App '%s' konnte nicht installiert werden!",
+ "Sync clients" : " Sync-Clients "
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/de.json b/lib/l10n/de.json
index 78cc16371b5..9b2858d2a8c 100644
--- a/lib/l10n/de.json
+++ b/lib/l10n/de.json
@@ -2,7 +2,9 @@
"Cannot write into \"config\" directory!" : "Das Schreiben in das „config“-Verzeichnis ist nicht möglich!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Dies kann normalerweise repariert werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird",
"See %s" : "Siehe %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Oder wenn Du möchtest, dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf True.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dies kann zumeist behoben werden, indem dem Web-Server Schreibzugriff auf das Konfigurationsverzeichnis eingeräumt wird. Siehe auch %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Oder wenn Du möchtest, dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf True. Siehe %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Die Dateien der App %$1s wurden nicht korrekt ersetzt. Stelle sicher, dass die Version mit dem Server kompatibel ist.",
"Sample configuration detected" : "Beispielkonfiguration gefunden",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann Deine Installation zerstören und wird nicht unterstützt. Bitte die Dokumentation lesen, bevor Änderungen an der config.php vorgenommen werden.",
@@ -25,6 +27,7 @@
"Following platforms are supported: %s" : "Die folgenden Plattformen werden unterstützt: %s",
"Server version %s or higher is required." : "Server Version %s oder höher wird benötigt.",
"Server version %s or lower is required." : "Server Version %s oder niedriger wird benötigt.",
+ "Logged in user must be an admin" : "Der angemeldete Benutzer muss ein Administrator sein",
"Unknown filetype" : "Unbekannter Dateityp",
"Invalid image" : "Ungültiges Bild",
"Avatar image is not square" : "Benutzerbild ist nicht quadratisch",
@@ -55,6 +58,7 @@
"Empty filename is not allowed" : "Ein leerer Dateiname ist nicht erlaubt",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Die Anwendung \"%s\" kann nicht installiert werden, weil die Anwendungsinfodatei nicht gelesen werden kann.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Die App \"%s\" kann nicht installiert werden, da sie mit dieser Serverversion nicht kompatibel ist.",
+ "__language_name__" : "Deutsch (Persönlich: Du)",
"This is an automatically sent email, please do not reply." : "Dies ist eine automatisch versandte E-Mail, bitte nicht antworten.",
"Help" : "Hilfe",
"Apps" : "Apps",
@@ -62,18 +66,20 @@
"Log out" : "Abmelden",
"Users" : "Benutzer",
"Unknown user" : "Unbekannter Benutzer",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Anlegen",
+ "Change" : "Ändern",
+ "Delete" : "Löschen",
+ "Share" : "Teilen",
+ "Overview" : "Übersicht",
"Basic settings" : "Grundeinstellungen",
"Sharing" : "Teilen",
"Security" : "Sicherheit",
"Encryption" : "Verschlüsselung",
+ "Groupware" : "Groupware",
"Additional settings" : "Zusätzliche Einstellungen",
- "Tips & tricks" : "Tipps & Tricks",
"Personal info" : "Persönliche Informationen ",
- "Sync clients" : " Sync-Clients ",
+ "Mobile & desktop" : "Mobil & Desktop",
"Unlimited" : "Unbegrenzt",
- "__language_name__" : " Deutsch (Persönlich: Du) ",
"Verifying" : "Überprüfe",
"Verifying …" : " Überprüfe… ",
"Verify" : "Überprüfen",
@@ -220,6 +226,11 @@
"Check the value of \"datadirectory\" in your configuration" : "Überprüfe bitte die Angabe unter „datadirectory“ in Deiner Konfiguration",
"Your data directory is invalid" : "Dein Datenverzeichnis ist ungültig",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stelle sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des data-Verzeichnisses existiert.",
+ "Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.",
+ "Authentication failed, wrong token or provider ID given" : "Authentifizierung ist fehlgeschlagen. Falsches Token oder Provider-ID wurde übertragen.",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Es fehlen Parameter um die Anfrage zu bearbeiten. Fehlende Parameter: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "ID \"%s\" wird bereits von Cloud-Federation-Provider \"%s\" verwendet",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud-Federation-Provider mit ID: \"%s\" ist nicht vorhanden.",
"Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf „%s“ konnte nicht ermittelt werden.",
"Storage unauthorized. %s" : "Speicher nicht authorisiert. %s",
"Storage incomplete configuration. %s" : "Speicher-Konfiguration unvollständig. %s",
@@ -228,6 +239,9 @@
"Storage connection timeout. %s" : "Zeitüberschreitung der Verbindung zum Speicherplatz. %s",
"Personal" : "Persönlich",
"Admin" : "Administrator",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tipps & Tricks",
"DB Error: \"%s\"" : "DB-Fehler: \"%s“",
"Offending command was: \"%s\"" : "Fehlerhafter Befehl war: \"%s“",
"Offending command was: \"%s\", name: %s, password: %s" : "Fehlerhafter Befehl war: \"%s“, Name: %s, Passwort: %s",
@@ -239,6 +253,7 @@
"Files can't be shared with create permissions" : "Dateien mit Erstell-Berechtigungen können nicht geteilt werden",
"Cannot set expiration date more than %s days in the future" : "Das Ablaufdatum kann nicht mehr als %s Tage in die Zukunft liegen",
"No app name specified" : "Es wurde kein App-Name angegeben",
- "App '%s' could not be installed!" : "App '%s' konnte nicht installiert werden!"
+ "App '%s' could not be installed!" : "App '%s' konnte nicht installiert werden!",
+ "Sync clients" : " Sync-Clients "
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/de_DE.js b/lib/l10n/de_DE.js
index bc2f0923577..35914a3da10 100644
--- a/lib/l10n/de_DE.js
+++ b/lib/l10n/de_DE.js
@@ -4,7 +4,9 @@ OC.L10N.register(
"Cannot write into \"config\" directory!" : "Das Schreiben in das „config“-Verzeichnis ist nicht möglich!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Dies kann normalerweise repariert werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird",
"See %s" : "Siehe %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Oder wenn Sie möchten, dass die Datei config.php schreibgeschützt bleiben soll, dann setzen Sie die Option \"config_is_read_only\" in der Datei auf True.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dies kann zumeist behoben werden, indem dem Web-Server Schreibzugriff auf das Konfigurationsverzeichnis eingeräumt wird. Siehe auch %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Oder wenn Sie möchten, dass die Datei config.php schreibgeschützt bleiben soll, dann setzen Sie die Option \"config_is_read_only\" in der Datei auf True. Siehe %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Die Dateien der App %$1s wurden nicht korrekt ersetzt. Stellen Sie sicher, dass die Version mit dem Server kompatibel ist.",
"Sample configuration detected" : "Beispielkonfiguration gefunden",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann Ihre Installation zerstören und wird nicht unterstützt. Bitte die Dokumentation lesen, bevor Änderungen an der config.php vorgenommen werden.",
@@ -27,6 +29,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Die folgenden Plattformen werden unterstützt: %s",
"Server version %s or higher is required." : "Server Version %s oder höher wird benötigt.",
"Server version %s or lower is required." : "Server Version %s oder niedriger wird benötigt.",
+ "Logged in user must be an admin" : "Der angemeldete Benutzer muss ein Administrator sein",
"Unknown filetype" : "Unbekannter Dateityp",
"Invalid image" : "Ungültiges Bild",
"Avatar image is not square" : "Benutzerbild ist nicht quadratisch",
@@ -57,6 +60,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Ein leerer Dateiname ist nicht erlaubt",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Die Anwendung \"%s\" kann nicht installiert werden, weil die Anwendungsinfodatei nicht gelesen werden kann.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Die App \"%s\" kann nicht installiert werden, da sie mit dieser Serverversion nicht kompatibel ist.",
+ "__language_name__" : "Deutsch (Förmlich: Sie)",
"This is an automatically sent email, please do not reply." : "Dies ist eine automatisch versandte E-Mail, bitte nicht antworten.",
"Help" : "Hilfe",
"Apps" : "Apps",
@@ -64,18 +68,20 @@ OC.L10N.register(
"Log out" : "Abmelden",
"Users" : "Benutzer",
"Unknown user" : "Unbekannter Benutzer",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Erstellen",
+ "Change" : "Ändern",
+ "Delete" : "Löschen",
+ "Share" : "Teilen",
+ "Overview" : "Übersicht",
"Basic settings" : "Grundeinstellungen",
"Sharing" : "Teilen",
"Security" : "Sicherheit",
"Encryption" : "Verschlüsselung",
+ "Groupware" : "Groupware",
"Additional settings" : "Zusätzliche Einstellungen",
- "Tips & tricks" : "Tipps & Tricks",
"Personal info" : "Persönliche Informationen ",
- "Sync clients" : " Sync-Clients ",
+ "Mobile & desktop" : "Mobil & Desktop",
"Unlimited" : "Unbegrenzt",
- "__language_name__" : " Deutsch (Förmlich: Sie) ",
"Verifying" : "Überprüfe",
"Verifying …" : " Überprüfe… ",
"Verify" : "Überprüfen",
@@ -222,6 +228,11 @@ OC.L10N.register(
"Check the value of \"datadirectory\" in your configuration" : "Überprüfen Sie bitte die Angabe unter „datadirectory“ in Ihrer Konfiguration",
"Your data directory is invalid" : "Dein Datenverzeichnis ist ungültig.",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stellen Sie sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des data-Verzeichnisses existiert.",
+ "Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.",
+ "Authentication failed, wrong token or provider ID given" : "Authentifizierung ist fehlgeschlagen. Falsches Token oder Provider-ID wurde übertragen.",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Es fehlen Parameter um die Anfrage zu bearbeiten. Fehlende Parameter: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "ID \"%s\" wird bereits von Cloud-Federation-Provider \"%s\" verwendet.",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud-Federation-Provider mit ID: \"%s\" ist nicht vorhanden.",
"Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf „%s“ konnte nicht ermittelt werden.",
"Storage unauthorized. %s" : "Speicher nicht authorisiert. %s",
"Storage incomplete configuration. %s" : "Speicher-Konfiguration unvollständig. %s",
@@ -230,6 +241,9 @@ OC.L10N.register(
"Storage connection timeout. %s" : "Zeitüberschreitung der Verbindung zum Speicherplatz. %s",
"Personal" : "Persönlich",
"Admin" : "Administrator",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tipps & Tricks",
"DB Error: \"%s\"" : "DB-Fehler: \"%s“",
"Offending command was: \"%s\"" : "Fehlerhafter Befehl war: \"%s“",
"Offending command was: \"%s\", name: %s, password: %s" : "Fehlerhafter Befehl war: \"%s“, Name: %s, Passwort: %s",
@@ -241,6 +255,7 @@ OC.L10N.register(
"Files can't be shared with create permissions" : "Dateien mit Erstell-Berechtigungen können nicht geteilt werden",
"Cannot set expiration date more than %s days in the future" : "Das Ablaufdatum kann nicht mehr als %s Tage in die Zukunft liegen",
"No app name specified" : "Es wurde kein App-Name angegeben",
- "App '%s' could not be installed!" : "App '%s' konnte nicht installiert werden!"
+ "App '%s' could not be installed!" : "App '%s' konnte nicht installiert werden!",
+ "Sync clients" : " Sync-Clients "
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/de_DE.json b/lib/l10n/de_DE.json
index 03a790e58ec..95fedd309f3 100644
--- a/lib/l10n/de_DE.json
+++ b/lib/l10n/de_DE.json
@@ -2,7 +2,9 @@
"Cannot write into \"config\" directory!" : "Das Schreiben in das „config“-Verzeichnis ist nicht möglich!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Dies kann normalerweise repariert werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird",
"See %s" : "Siehe %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Oder wenn Sie möchten, dass die Datei config.php schreibgeschützt bleiben soll, dann setzen Sie die Option \"config_is_read_only\" in der Datei auf True.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Dies kann zumeist behoben werden, indem dem Web-Server Schreibzugriff auf das Konfigurationsverzeichnis eingeräumt wird. Siehe auch %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Oder wenn Sie möchten, dass die Datei config.php schreibgeschützt bleiben soll, dann setzen Sie die Option \"config_is_read_only\" in der Datei auf True. Siehe %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Die Dateien der App %$1s wurden nicht korrekt ersetzt. Stellen Sie sicher, dass die Version mit dem Server kompatibel ist.",
"Sample configuration detected" : "Beispielkonfiguration gefunden",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann Ihre Installation zerstören und wird nicht unterstützt. Bitte die Dokumentation lesen, bevor Änderungen an der config.php vorgenommen werden.",
@@ -25,6 +27,7 @@
"Following platforms are supported: %s" : "Die folgenden Plattformen werden unterstützt: %s",
"Server version %s or higher is required." : "Server Version %s oder höher wird benötigt.",
"Server version %s or lower is required." : "Server Version %s oder niedriger wird benötigt.",
+ "Logged in user must be an admin" : "Der angemeldete Benutzer muss ein Administrator sein",
"Unknown filetype" : "Unbekannter Dateityp",
"Invalid image" : "Ungültiges Bild",
"Avatar image is not square" : "Benutzerbild ist nicht quadratisch",
@@ -55,6 +58,7 @@
"Empty filename is not allowed" : "Ein leerer Dateiname ist nicht erlaubt",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Die Anwendung \"%s\" kann nicht installiert werden, weil die Anwendungsinfodatei nicht gelesen werden kann.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Die App \"%s\" kann nicht installiert werden, da sie mit dieser Serverversion nicht kompatibel ist.",
+ "__language_name__" : "Deutsch (Förmlich: Sie)",
"This is an automatically sent email, please do not reply." : "Dies ist eine automatisch versandte E-Mail, bitte nicht antworten.",
"Help" : "Hilfe",
"Apps" : "Apps",
@@ -62,18 +66,20 @@
"Log out" : "Abmelden",
"Users" : "Benutzer",
"Unknown user" : "Unbekannter Benutzer",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Erstellen",
+ "Change" : "Ändern",
+ "Delete" : "Löschen",
+ "Share" : "Teilen",
+ "Overview" : "Übersicht",
"Basic settings" : "Grundeinstellungen",
"Sharing" : "Teilen",
"Security" : "Sicherheit",
"Encryption" : "Verschlüsselung",
+ "Groupware" : "Groupware",
"Additional settings" : "Zusätzliche Einstellungen",
- "Tips & tricks" : "Tipps & Tricks",
"Personal info" : "Persönliche Informationen ",
- "Sync clients" : " Sync-Clients ",
+ "Mobile & desktop" : "Mobil & Desktop",
"Unlimited" : "Unbegrenzt",
- "__language_name__" : " Deutsch (Förmlich: Sie) ",
"Verifying" : "Überprüfe",
"Verifying …" : " Überprüfe… ",
"Verify" : "Überprüfen",
@@ -220,6 +226,11 @@
"Check the value of \"datadirectory\" in your configuration" : "Überprüfen Sie bitte die Angabe unter „datadirectory“ in Ihrer Konfiguration",
"Your data directory is invalid" : "Dein Datenverzeichnis ist ungültig.",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stellen Sie sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des data-Verzeichnisses existiert.",
+ "Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.",
+ "Authentication failed, wrong token or provider ID given" : "Authentifizierung ist fehlgeschlagen. Falsches Token oder Provider-ID wurde übertragen.",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Es fehlen Parameter um die Anfrage zu bearbeiten. Fehlende Parameter: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "ID \"%s\" wird bereits von Cloud-Federation-Provider \"%s\" verwendet.",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud-Federation-Provider mit ID: \"%s\" ist nicht vorhanden.",
"Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf „%s“ konnte nicht ermittelt werden.",
"Storage unauthorized. %s" : "Speicher nicht authorisiert. %s",
"Storage incomplete configuration. %s" : "Speicher-Konfiguration unvollständig. %s",
@@ -228,6 +239,9 @@
"Storage connection timeout. %s" : "Zeitüberschreitung der Verbindung zum Speicherplatz. %s",
"Personal" : "Persönlich",
"Admin" : "Administrator",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tipps & Tricks",
"DB Error: \"%s\"" : "DB-Fehler: \"%s“",
"Offending command was: \"%s\"" : "Fehlerhafter Befehl war: \"%s“",
"Offending command was: \"%s\", name: %s, password: %s" : "Fehlerhafter Befehl war: \"%s“, Name: %s, Passwort: %s",
@@ -239,6 +253,7 @@
"Files can't be shared with create permissions" : "Dateien mit Erstell-Berechtigungen können nicht geteilt werden",
"Cannot set expiration date more than %s days in the future" : "Das Ablaufdatum kann nicht mehr als %s Tage in die Zukunft liegen",
"No app name specified" : "Es wurde kein App-Name angegeben",
- "App '%s' could not be installed!" : "App '%s' konnte nicht installiert werden!"
+ "App '%s' could not be installed!" : "App '%s' konnte nicht installiert werden!",
+ "Sync clients" : " Sync-Clients "
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/el.js b/lib/l10n/el.js
index 54b12068750..8bc15fb9c32 100644
--- a/lib/l10n/el.js
+++ b/lib/l10n/el.js
@@ -31,10 +31,15 @@ OC.L10N.register(
"Invalid image" : "Μη έγκυρη εικόνα",
"Avatar image is not square" : "Η εικόνα του άβαταρ δεν είναι τετράγωνη",
"today" : "σήμερα",
+ "tomorrow" : "αύριο",
"yesterday" : "χτες",
+ "_in %n day_::_in %n days_" : ["σε %n ημέρα","σε %n ημέρες"],
"_%n day ago_::_%n days ago_" : ["%n ημέρα πριν","%n ημέρες πριν"],
+ "next month" : "επόμενος μήνας",
"last month" : "τελευταίο μήνα",
+ "_in %n month_::_in %n months_" : ["σε %n μήνα","σε %n μήνες"],
"_%n month ago_::_%n months ago_" : ["πριν %n μήνα","πριν %n μήνες"],
+ "next year" : "επόμενος χρόνος",
"last year" : "τελευταίο χρόνο",
"_%n year ago_::_%n years ago_" : ["%n χρόνο πριν","%n χρόνια πριν"],
"_%n hour ago_::_%n hours ago_" : ["%nώρα πριν","%nώρες πριν"],
@@ -48,6 +53,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Δεν επιτρέπεται άδειο όνομα αρχείου",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Η εφαρμογή \"%s\" δεν μπορεί να εγκατασταθεί διότι δεν είναι δυνατή η ανάγνωση του αρχείου appinfo.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Η εφαρμογή \"%s\" δεν μπορεί να εγκατασταθεί διότι δεν είναι συμβατή με την έκδοση του διακομιστή.",
+ "__language_name__" : "Ελληνικά",
"This is an automatically sent email, please do not reply." : "Αυτό είναι ένα μήνυμα ηλεκτρονικού ταχυδρομείου που στάλθηκε αυτόματα, παρακαλούμε μην απαντήσετε.",
"Help" : "Βοήθεια",
"Apps" : "Εφαρμογές",
@@ -55,18 +61,15 @@ OC.L10N.register(
"Log out" : "Έξοδος",
"Users" : "Χρήστες",
"Unknown user" : "Άγνωστος χρήστης",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Δημιουργία",
+ "Delete" : "Διαγραφή",
"Basic settings" : "Βασικές ρυθμίσεις",
"Sharing" : "Διαμοιρασμός",
"Security" : "Ασφάλεια",
"Encryption" : "Κρυπτογράφηση",
"Additional settings" : "Επιπρόσθετες ρυθμίσεις",
- "Tips & tricks" : "Συμβουλές & κόλπα",
"Personal info" : "Προσωπικές πληροφορίες",
- "Sync clients" : "Εφαρμογές συγχρονισμού",
"Unlimited" : "Απεριόριστα",
- "__language_name__" : "__language_name__",
"Verifying" : "Γίνεται επαλήθευση",
"Verifying …" : "Γίνεται επαλήθευση ...",
"Verify" : "Επαλήθευση",
@@ -214,6 +217,13 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Ελλιπής διαμόρφωση αποθηκευτικού χώρου. %s",
"Storage connection error. %s" : "Σφάλμα σύνδεσης με αποθηκευτικό χώρο. %s",
"Storage is temporarily not available" : "Μη διαθέσιμος χώρος αποθήκευσης προσωρινά",
- "Storage connection timeout. %s" : "Λήξη χρονικού ορίου σύνδεσης με αποθηκευτικό χώρο.%s"
+ "Storage connection timeout. %s" : "Λήξη χρονικού ορίου σύνδεσης με αποθηκευτικό χώρο.%s",
+ "Personal" : "Προσωπικά",
+ "Admin" : "Διαχειριστής",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Συμβουλές & κόλπα",
+ "DB Error: \"%s\"" : "Σφάλμα βάσης δεδομένων: \"%s\"",
+ "Sync clients" : "Εφαρμογές συγχρονισμού"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/el.json b/lib/l10n/el.json
index 65dc96d7a68..cbb22cd33bc 100644
--- a/lib/l10n/el.json
+++ b/lib/l10n/el.json
@@ -29,10 +29,15 @@
"Invalid image" : "Μη έγκυρη εικόνα",
"Avatar image is not square" : "Η εικόνα του άβαταρ δεν είναι τετράγωνη",
"today" : "σήμερα",
+ "tomorrow" : "αύριο",
"yesterday" : "χτες",
+ "_in %n day_::_in %n days_" : ["σε %n ημέρα","σε %n ημέρες"],
"_%n day ago_::_%n days ago_" : ["%n ημέρα πριν","%n ημέρες πριν"],
+ "next month" : "επόμενος μήνας",
"last month" : "τελευταίο μήνα",
+ "_in %n month_::_in %n months_" : ["σε %n μήνα","σε %n μήνες"],
"_%n month ago_::_%n months ago_" : ["πριν %n μήνα","πριν %n μήνες"],
+ "next year" : "επόμενος χρόνος",
"last year" : "τελευταίο χρόνο",
"_%n year ago_::_%n years ago_" : ["%n χρόνο πριν","%n χρόνια πριν"],
"_%n hour ago_::_%n hours ago_" : ["%nώρα πριν","%nώρες πριν"],
@@ -46,6 +51,7 @@
"Empty filename is not allowed" : "Δεν επιτρέπεται άδειο όνομα αρχείου",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Η εφαρμογή \"%s\" δεν μπορεί να εγκατασταθεί διότι δεν είναι δυνατή η ανάγνωση του αρχείου appinfo.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Η εφαρμογή \"%s\" δεν μπορεί να εγκατασταθεί διότι δεν είναι συμβατή με την έκδοση του διακομιστή.",
+ "__language_name__" : "Ελληνικά",
"This is an automatically sent email, please do not reply." : "Αυτό είναι ένα μήνυμα ηλεκτρονικού ταχυδρομείου που στάλθηκε αυτόματα, παρακαλούμε μην απαντήσετε.",
"Help" : "Βοήθεια",
"Apps" : "Εφαρμογές",
@@ -53,18 +59,15 @@
"Log out" : "Έξοδος",
"Users" : "Χρήστες",
"Unknown user" : "Άγνωστος χρήστης",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Δημιουργία",
+ "Delete" : "Διαγραφή",
"Basic settings" : "Βασικές ρυθμίσεις",
"Sharing" : "Διαμοιρασμός",
"Security" : "Ασφάλεια",
"Encryption" : "Κρυπτογράφηση",
"Additional settings" : "Επιπρόσθετες ρυθμίσεις",
- "Tips & tricks" : "Συμβουλές & κόλπα",
"Personal info" : "Προσωπικές πληροφορίες",
- "Sync clients" : "Εφαρμογές συγχρονισμού",
"Unlimited" : "Απεριόριστα",
- "__language_name__" : "__language_name__",
"Verifying" : "Γίνεται επαλήθευση",
"Verifying …" : "Γίνεται επαλήθευση ...",
"Verify" : "Επαλήθευση",
@@ -212,6 +215,13 @@
"Storage incomplete configuration. %s" : "Ελλιπής διαμόρφωση αποθηκευτικού χώρου. %s",
"Storage connection error. %s" : "Σφάλμα σύνδεσης με αποθηκευτικό χώρο. %s",
"Storage is temporarily not available" : "Μη διαθέσιμος χώρος αποθήκευσης προσωρινά",
- "Storage connection timeout. %s" : "Λήξη χρονικού ορίου σύνδεσης με αποθηκευτικό χώρο.%s"
+ "Storage connection timeout. %s" : "Λήξη χρονικού ορίου σύνδεσης με αποθηκευτικό χώρο.%s",
+ "Personal" : "Προσωπικά",
+ "Admin" : "Διαχειριστής",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Συμβουλές & κόλπα",
+ "DB Error: \"%s\"" : "Σφάλμα βάσης δεδομένων: \"%s\"",
+ "Sync clients" : "Εφαρμογές συγχρονισμού"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/en_GB.js b/lib/l10n/en_GB.js
index 16f1fe98ed3..431f865465a 100644
--- a/lib/l10n/en_GB.js
+++ b/lib/l10n/en_GB.js
@@ -27,6 +27,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Following platforms are supported: %s",
"Server version %s or higher is required." : "Server version %s or higher is required.",
"Server version %s or lower is required." : "Server version %s or lower is required.",
+ "Logged in user must be an admin" : "Logged in user must be an admin",
"Unknown filetype" : "Unknown filetype",
"Invalid image" : "Invalid image",
"Avatar image is not square" : "Avatar image is not square",
@@ -57,6 +58,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Empty filename is not allowed",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "App \"%s\" cannot be installed because appinfo file cannot be read.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "App \"%s\" cannot be installed. It is not compatible with this version of the server.",
+ "__language_name__" : "English (British English)",
"This is an automatically sent email, please do not reply." : "This is an automatically sent email, please do not reply.",
"Help" : "Help",
"Apps" : "Apps",
@@ -64,18 +66,19 @@ OC.L10N.register(
"Log out" : "Log out",
"Users" : "Users",
"Unknown user" : "Unknown user",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Create",
+ "Change" : "Change",
+ "Delete" : "Delete",
+ "Share" : "Share",
+ "Overview" : "Overview",
"Basic settings" : "Basic settings",
"Sharing" : "Sharing",
"Security" : "Security",
"Encryption" : "Encryption",
"Additional settings" : "Additional settings",
- "Tips & tricks" : "Tips & tricks",
"Personal info" : "Personal info",
- "Sync clients" : "Sync clients",
+ "Mobile & desktop" : "Mobile & desktop",
"Unlimited" : "Unlimited",
- "__language_name__" : "__language_name__",
"Verifying" : "Verifying",
"Verifying …" : "Verifying …",
"Verify" : "Verify",
@@ -227,6 +230,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Storage incomplete configuration. %s",
"Storage connection error. %s" : "Storage connection error. %s",
"Storage is temporarily not available" : "Storage is temporarily not available",
- "Storage connection timeout. %s" : "Storage connection timeout. %s"
+ "Storage connection timeout. %s" : "Storage connection timeout. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tips & tricks",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "Offending command was: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "Offending command was: \"%s\", name: %s, password: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Setting permissions for %s failed, because the permissions exceed permissions granted to %s",
+ "Setting permissions for %s failed, because the item was not found" : "Setting permissions for %s failed, because the item was not found",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Cannot clear expiration date. Shares are required to have an expiration date.",
+ "Cannot increase permissions of %s" : "Cannot increase permissions of %s",
+ "Files can't be shared with delete permissions" : "Files can't be shared with delete permissions",
+ "Files can't be shared with create permissions" : "Files can't be shared with create permissions",
+ "Cannot set expiration date more than %s days in the future" : "Cannot set expiration date more than %s days in the future",
+ "No app name specified" : "No app name specified",
+ "App '%s' could not be installed!" : "App '%s' could not be installed!",
+ "Sync clients" : "Sync clients"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/en_GB.json b/lib/l10n/en_GB.json
index dcf615eee6e..c681b7da04a 100644
--- a/lib/l10n/en_GB.json
+++ b/lib/l10n/en_GB.json
@@ -25,6 +25,7 @@
"Following platforms are supported: %s" : "Following platforms are supported: %s",
"Server version %s or higher is required." : "Server version %s or higher is required.",
"Server version %s or lower is required." : "Server version %s or lower is required.",
+ "Logged in user must be an admin" : "Logged in user must be an admin",
"Unknown filetype" : "Unknown filetype",
"Invalid image" : "Invalid image",
"Avatar image is not square" : "Avatar image is not square",
@@ -55,6 +56,7 @@
"Empty filename is not allowed" : "Empty filename is not allowed",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "App \"%s\" cannot be installed because appinfo file cannot be read.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "App \"%s\" cannot be installed. It is not compatible with this version of the server.",
+ "__language_name__" : "English (British English)",
"This is an automatically sent email, please do not reply." : "This is an automatically sent email, please do not reply.",
"Help" : "Help",
"Apps" : "Apps",
@@ -62,18 +64,19 @@
"Log out" : "Log out",
"Users" : "Users",
"Unknown user" : "Unknown user",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Create",
+ "Change" : "Change",
+ "Delete" : "Delete",
+ "Share" : "Share",
+ "Overview" : "Overview",
"Basic settings" : "Basic settings",
"Sharing" : "Sharing",
"Security" : "Security",
"Encryption" : "Encryption",
"Additional settings" : "Additional settings",
- "Tips & tricks" : "Tips & tricks",
"Personal info" : "Personal info",
- "Sync clients" : "Sync clients",
+ "Mobile & desktop" : "Mobile & desktop",
"Unlimited" : "Unlimited",
- "__language_name__" : "__language_name__",
"Verifying" : "Verifying",
"Verifying …" : "Verifying …",
"Verify" : "Verify",
@@ -225,6 +228,24 @@
"Storage incomplete configuration. %s" : "Storage incomplete configuration. %s",
"Storage connection error. %s" : "Storage connection error. %s",
"Storage is temporarily not available" : "Storage is temporarily not available",
- "Storage connection timeout. %s" : "Storage connection timeout. %s"
+ "Storage connection timeout. %s" : "Storage connection timeout. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tips & tricks",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "Offending command was: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "Offending command was: \"%s\", name: %s, password: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Setting permissions for %s failed, because the permissions exceed permissions granted to %s",
+ "Setting permissions for %s failed, because the item was not found" : "Setting permissions for %s failed, because the item was not found",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Cannot clear expiration date. Shares are required to have an expiration date.",
+ "Cannot increase permissions of %s" : "Cannot increase permissions of %s",
+ "Files can't be shared with delete permissions" : "Files can't be shared with delete permissions",
+ "Files can't be shared with create permissions" : "Files can't be shared with create permissions",
+ "Cannot set expiration date more than %s days in the future" : "Cannot set expiration date more than %s days in the future",
+ "No app name specified" : "No app name specified",
+ "App '%s' could not be installed!" : "App '%s' could not be installed!",
+ "Sync clients" : "Sync clients"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/eo.js b/lib/l10n/eo.js
new file mode 100644
index 00000000000..46310229b86
--- /dev/null
+++ b/lib/l10n/eo.js
@@ -0,0 +1,141 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Ne skribeblas la dosierujo “config”!",
+ "See %s" : "Vidi %s",
+ "%1$s and %2$s" : "%1$s kaj %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s kaj %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s kaj %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s kaj %5$s",
+ "PHP %s or higher is required." : "PHP %s aŭ pli alta necesas.",
+ "PHP with a version lower than %s is required." : "Necesas pli malalta eldono de PHP ol %s.",
+ "Following databases are supported: %s" : "La jenan datumbazoj kongruas: %s",
+ "The command line tool %s could not be found" : "La komandolinia ilo %s ne troviĝis",
+ "The library %s is not available." : "La biblioteko %s ne haveblas.",
+ "Unknown filetype" : "Ne konatas dosiertipo",
+ "Invalid image" : "Ne validas bildo",
+ "today" : "hodiaŭ",
+ "tomorrow" : "morgaŭ",
+ "yesterday" : "hieraŭ",
+ "_%n day ago_::_%n days ago_" : ["antaŭ %n tago","antaŭ %n tagoj"],
+ "last month" : "lastamonate",
+ "last year" : "lastajare",
+ "_%n year ago_::_%n years ago_" : ["antaŭ %n jaro","antaŭ %n jaroj"],
+ "seconds ago" : "sekundoj antaŭe",
+ "File name contains at least one invalid character" : "Dosiernomo enhavas almenaŭ unu nevalidan signon",
+ "File name is too long" : "La dosiernomo tro longas",
+ "Empty filename is not allowed" : "Malplena dosiernomo ne permesatas",
+ "__language_name__" : "Esperanto",
+ "Help" : "Helpo",
+ "Apps" : "Aplikaĵoj",
+ "Settings" : "Agordo",
+ "Log out" : "Elsaluti",
+ "Users" : "Uzantoj",
+ "Unknown user" : "Nekonata uzanto",
+ "Create" : "Krei",
+ "Change" : "Ŝanĝi",
+ "Delete" : "Forigi",
+ "Share" : "Kunhavigi",
+ "Sharing" : "Kunhavigo",
+ "Security" : "Sekurigo",
+ "Additional settings" : "Plia agordo",
+ "%s enter the database username." : "%s enigu la uzantonomon de la datumbazo.",
+ "%s enter the database name." : "%s enigu la nomon de la datumbazo.",
+ "%s you may not use dots in the database name" : "%s vi ne povas uzi punktojn en la nomo de la datumbazo",
+ "Oracle connection could not be established" : "Konekto al Oracle ne povas stariĝi",
+ "Oracle username and/or password not valid" : "La uzantonomo de Oracle aŭ la pasvorto ne validas",
+ "PostgreSQL username and/or password not valid" : "La uzantonomo de PostgreSQL aŭ la pasvorto ne validas",
+ "Set an admin username." : "Starigi administran uzantonomon.",
+ "Set an admin password." : "Starigi administran pasvorton.",
+ "Can't create or write into the data directory %s" : "Ne kreeblas aŭ ne skribeblas la dosierujo de datumoj %s",
+ "Invalid Federated Cloud ID" : "Ne validas identigilo de federa nubo",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "Kunhavigo de %s malsukcesis, ĉar la motoro ne permesas kunhavojn el tipo %i",
+ "Sharing %s failed, because the file does not exist" : "Kunhavigo de %s malsukcesis, ĉar la dosiero ne ekzistas",
+ "You are not allowed to share %s" : "Vi ne permesatas kunhavigi %s",
+ "Sharing %s failed, because the user %s does not exist" : "Kunhavigo de %s malsukcesis, ĉar la uzanto %s ne ekzistas",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Kunhavigo de %s malsukcesis, ĉar la uzanto %s estas ano de neniu grupo, de kiu %s estas ano",
+ "Sharing %s failed, because this item is already shared with %s" : "Kunhavigo de %s malsukcesis, ĉar la ero jam kunhavatas kun %s",
+ "Sharing %s failed, because the group %s does not exist" : "Kunhavigo de %s malsukcesis, ĉar la grupo %s ne ekzistas",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Kunhavigo de %s malsukcesis, ĉar %s ne estas ano de la grupo %s",
+ "Sharing %s failed, because sharing with links is not allowed" : "Kunhavo de %s malsukcesis, ĉar kunhavo per ligiloj ne permesatas",
+ "Not allowed to create a federated share with the same user" : "Vi ne permesas krei federan kunhavon kun la sama uzanto",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Kunhavmotoro %s devas realigi la interfacon “OCP\\Share_Backend”",
+ "Sharing backend %s not found" : "Kunhavmotoro %s ne troviĝas",
+ "Sharing backend for %s not found" : "Kunhavmotoro por %s ne troviĝas",
+ "Sharing %s failed, because resharing is not allowed" : "Kunhavigo de %s malsukcesis, ĉar rekunhavigo ne permesatas",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Kunhavigo de %s malsukcesis, ĉar la kunhavmotoro por %s ne povis trovi ĝian fonton",
+ "Expiration date is in the past" : "Senvalidiĝa dato estintas",
+ "%s shared »%s« with you" : "%s kunhavigis “%s” kun vi",
+ "Open »%s«" : "Malfermi »%s«",
+ "%s via %s" : "%s per %s",
+ "Could not find category \"%s\"" : "Ne troviĝis kategorio “%s”",
+ "Sunday" : "dimanĉo",
+ "Monday" : "lundo",
+ "Tuesday" : "mardo",
+ "Wednesday" : "merkredo",
+ "Thursday" : "ĵaŭdo",
+ "Friday" : "vendredo",
+ "Saturday" : "sabato",
+ "Sun." : "dim.",
+ "Mon." : "lun.",
+ "Tue." : "mar.",
+ "Wed." : "mer.",
+ "Thu." : "ĵaŭ.",
+ "Fri." : "ven.",
+ "Sat." : "sab.",
+ "Su" : "Di",
+ "Mo" : "Lu",
+ "Tu" : "Ma",
+ "We" : "Me",
+ "Th" : "Ĵa",
+ "Fr" : "Ve",
+ "Sa" : "Sa",
+ "January" : "Januaro",
+ "February" : "Februaro",
+ "March" : "Marto",
+ "April" : "Aprilo",
+ "May" : "Majo",
+ "June" : "Junio",
+ "July" : "Julio",
+ "August" : "Aŭgusto",
+ "September" : "Septembro",
+ "October" : "Oktobro",
+ "November" : "Novembro",
+ "December" : "Decembro",
+ "Jan." : "Jan.",
+ "Feb." : "Feb.",
+ "Mar." : "Mar.",
+ "Apr." : "Apr.",
+ "May." : "Maj.",
+ "Jun." : "Jun.",
+ "Jul." : "Jul.",
+ "Aug." : "Aŭg.",
+ "Sep." : "Sep.",
+ "Oct." : "Okt.",
+ "Nov." : "Nov.",
+ "Dec." : "Dec.",
+ "A valid username must be provided" : "Valida uzantonomo devas proviziĝi",
+ "Username contains whitespace at the beginning or at the end" : "Uzantonomo enhavas blankospacon eke aŭ maleke",
+ "A valid password must be provided" : "Valida pasvorto devas proviziĝi",
+ "The username is already being used" : "La uzantonomo jam uzatas",
+ "Could not create user" : "Ne povis kreiĝi uzanton",
+ "User disabled" : "Uzanto estas malkapabligita",
+ "a safe home for all your data" : "sekura hejmo por ĉion vian datumon",
+ "Can't read file" : "Ne legeblas dosiero",
+ "Application is not enabled" : "La aplikaĵo ne estas kapabligita",
+ "Authentication error" : "Aŭtentiga eraro",
+ "Token expired. Please reload page." : "Ĵetono eksvalidiĝis. Bonvolu reŝargi la paĝon.",
+ "Cannot write into \"config\" directory" : "Ne skribeblas la dosierujo “config”",
+ "Cannot write into \"apps\" directory" : "Ne skribeblas la dosierujo “apps”",
+ "Cannot create \"data\" directory" : "Ne kreeblas la dosierujo “data”",
+ "Please ask your server administrator to install the module." : "Bonvolu peti vian sistemadministranton, ke ĝi instalu la modulon.",
+ "PHP module %s not installed." : "La PHP-modulo %s ne instalitas.",
+ "Please ask your server administrator to restart the web server." : "Bonvolu peti viajn serviladministranton, ke ŝi/li reekfunkciigu la TTT-servilon.",
+ "PostgreSQL >= 9 required" : "PostgreSQL >= 9 necesas",
+ "Please upgrade your database version" : "Bonvolu ĝisdatigi la eldonon de via datumbazo",
+ "Storage connection error. %s" : "Memorokonekta eraro. %s",
+ "Personal" : "Persona",
+ "Admin" : "Administranto",
+ "DB Error: \"%s\"" : "Datumbaza eraro: “%s”"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/eo.json b/lib/l10n/eo.json
new file mode 100644
index 00000000000..e4629daeca5
--- /dev/null
+++ b/lib/l10n/eo.json
@@ -0,0 +1,139 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Ne skribeblas la dosierujo “config”!",
+ "See %s" : "Vidi %s",
+ "%1$s and %2$s" : "%1$s kaj %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s kaj %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s kaj %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s kaj %5$s",
+ "PHP %s or higher is required." : "PHP %s aŭ pli alta necesas.",
+ "PHP with a version lower than %s is required." : "Necesas pli malalta eldono de PHP ol %s.",
+ "Following databases are supported: %s" : "La jenan datumbazoj kongruas: %s",
+ "The command line tool %s could not be found" : "La komandolinia ilo %s ne troviĝis",
+ "The library %s is not available." : "La biblioteko %s ne haveblas.",
+ "Unknown filetype" : "Ne konatas dosiertipo",
+ "Invalid image" : "Ne validas bildo",
+ "today" : "hodiaŭ",
+ "tomorrow" : "morgaŭ",
+ "yesterday" : "hieraŭ",
+ "_%n day ago_::_%n days ago_" : ["antaŭ %n tago","antaŭ %n tagoj"],
+ "last month" : "lastamonate",
+ "last year" : "lastajare",
+ "_%n year ago_::_%n years ago_" : ["antaŭ %n jaro","antaŭ %n jaroj"],
+ "seconds ago" : "sekundoj antaŭe",
+ "File name contains at least one invalid character" : "Dosiernomo enhavas almenaŭ unu nevalidan signon",
+ "File name is too long" : "La dosiernomo tro longas",
+ "Empty filename is not allowed" : "Malplena dosiernomo ne permesatas",
+ "__language_name__" : "Esperanto",
+ "Help" : "Helpo",
+ "Apps" : "Aplikaĵoj",
+ "Settings" : "Agordo",
+ "Log out" : "Elsaluti",
+ "Users" : "Uzantoj",
+ "Unknown user" : "Nekonata uzanto",
+ "Create" : "Krei",
+ "Change" : "Ŝanĝi",
+ "Delete" : "Forigi",
+ "Share" : "Kunhavigi",
+ "Sharing" : "Kunhavigo",
+ "Security" : "Sekurigo",
+ "Additional settings" : "Plia agordo",
+ "%s enter the database username." : "%s enigu la uzantonomon de la datumbazo.",
+ "%s enter the database name." : "%s enigu la nomon de la datumbazo.",
+ "%s you may not use dots in the database name" : "%s vi ne povas uzi punktojn en la nomo de la datumbazo",
+ "Oracle connection could not be established" : "Konekto al Oracle ne povas stariĝi",
+ "Oracle username and/or password not valid" : "La uzantonomo de Oracle aŭ la pasvorto ne validas",
+ "PostgreSQL username and/or password not valid" : "La uzantonomo de PostgreSQL aŭ la pasvorto ne validas",
+ "Set an admin username." : "Starigi administran uzantonomon.",
+ "Set an admin password." : "Starigi administran pasvorton.",
+ "Can't create or write into the data directory %s" : "Ne kreeblas aŭ ne skribeblas la dosierujo de datumoj %s",
+ "Invalid Federated Cloud ID" : "Ne validas identigilo de federa nubo",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "Kunhavigo de %s malsukcesis, ĉar la motoro ne permesas kunhavojn el tipo %i",
+ "Sharing %s failed, because the file does not exist" : "Kunhavigo de %s malsukcesis, ĉar la dosiero ne ekzistas",
+ "You are not allowed to share %s" : "Vi ne permesatas kunhavigi %s",
+ "Sharing %s failed, because the user %s does not exist" : "Kunhavigo de %s malsukcesis, ĉar la uzanto %s ne ekzistas",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Kunhavigo de %s malsukcesis, ĉar la uzanto %s estas ano de neniu grupo, de kiu %s estas ano",
+ "Sharing %s failed, because this item is already shared with %s" : "Kunhavigo de %s malsukcesis, ĉar la ero jam kunhavatas kun %s",
+ "Sharing %s failed, because the group %s does not exist" : "Kunhavigo de %s malsukcesis, ĉar la grupo %s ne ekzistas",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Kunhavigo de %s malsukcesis, ĉar %s ne estas ano de la grupo %s",
+ "Sharing %s failed, because sharing with links is not allowed" : "Kunhavo de %s malsukcesis, ĉar kunhavo per ligiloj ne permesatas",
+ "Not allowed to create a federated share with the same user" : "Vi ne permesas krei federan kunhavon kun la sama uzanto",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Kunhavmotoro %s devas realigi la interfacon “OCP\\Share_Backend”",
+ "Sharing backend %s not found" : "Kunhavmotoro %s ne troviĝas",
+ "Sharing backend for %s not found" : "Kunhavmotoro por %s ne troviĝas",
+ "Sharing %s failed, because resharing is not allowed" : "Kunhavigo de %s malsukcesis, ĉar rekunhavigo ne permesatas",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Kunhavigo de %s malsukcesis, ĉar la kunhavmotoro por %s ne povis trovi ĝian fonton",
+ "Expiration date is in the past" : "Senvalidiĝa dato estintas",
+ "%s shared »%s« with you" : "%s kunhavigis “%s” kun vi",
+ "Open »%s«" : "Malfermi »%s«",
+ "%s via %s" : "%s per %s",
+ "Could not find category \"%s\"" : "Ne troviĝis kategorio “%s”",
+ "Sunday" : "dimanĉo",
+ "Monday" : "lundo",
+ "Tuesday" : "mardo",
+ "Wednesday" : "merkredo",
+ "Thursday" : "ĵaŭdo",
+ "Friday" : "vendredo",
+ "Saturday" : "sabato",
+ "Sun." : "dim.",
+ "Mon." : "lun.",
+ "Tue." : "mar.",
+ "Wed." : "mer.",
+ "Thu." : "ĵaŭ.",
+ "Fri." : "ven.",
+ "Sat." : "sab.",
+ "Su" : "Di",
+ "Mo" : "Lu",
+ "Tu" : "Ma",
+ "We" : "Me",
+ "Th" : "Ĵa",
+ "Fr" : "Ve",
+ "Sa" : "Sa",
+ "January" : "Januaro",
+ "February" : "Februaro",
+ "March" : "Marto",
+ "April" : "Aprilo",
+ "May" : "Majo",
+ "June" : "Junio",
+ "July" : "Julio",
+ "August" : "Aŭgusto",
+ "September" : "Septembro",
+ "October" : "Oktobro",
+ "November" : "Novembro",
+ "December" : "Decembro",
+ "Jan." : "Jan.",
+ "Feb." : "Feb.",
+ "Mar." : "Mar.",
+ "Apr." : "Apr.",
+ "May." : "Maj.",
+ "Jun." : "Jun.",
+ "Jul." : "Jul.",
+ "Aug." : "Aŭg.",
+ "Sep." : "Sep.",
+ "Oct." : "Okt.",
+ "Nov." : "Nov.",
+ "Dec." : "Dec.",
+ "A valid username must be provided" : "Valida uzantonomo devas proviziĝi",
+ "Username contains whitespace at the beginning or at the end" : "Uzantonomo enhavas blankospacon eke aŭ maleke",
+ "A valid password must be provided" : "Valida pasvorto devas proviziĝi",
+ "The username is already being used" : "La uzantonomo jam uzatas",
+ "Could not create user" : "Ne povis kreiĝi uzanton",
+ "User disabled" : "Uzanto estas malkapabligita",
+ "a safe home for all your data" : "sekura hejmo por ĉion vian datumon",
+ "Can't read file" : "Ne legeblas dosiero",
+ "Application is not enabled" : "La aplikaĵo ne estas kapabligita",
+ "Authentication error" : "Aŭtentiga eraro",
+ "Token expired. Please reload page." : "Ĵetono eksvalidiĝis. Bonvolu reŝargi la paĝon.",
+ "Cannot write into \"config\" directory" : "Ne skribeblas la dosierujo “config”",
+ "Cannot write into \"apps\" directory" : "Ne skribeblas la dosierujo “apps”",
+ "Cannot create \"data\" directory" : "Ne kreeblas la dosierujo “data”",
+ "Please ask your server administrator to install the module." : "Bonvolu peti vian sistemadministranton, ke ĝi instalu la modulon.",
+ "PHP module %s not installed." : "La PHP-modulo %s ne instalitas.",
+ "Please ask your server administrator to restart the web server." : "Bonvolu peti viajn serviladministranton, ke ŝi/li reekfunkciigu la TTT-servilon.",
+ "PostgreSQL >= 9 required" : "PostgreSQL >= 9 necesas",
+ "Please upgrade your database version" : "Bonvolu ĝisdatigi la eldonon de via datumbazo",
+ "Storage connection error. %s" : "Memorokonekta eraro. %s",
+ "Personal" : "Persona",
+ "Admin" : "Administranto",
+ "DB Error: \"%s\"" : "Datumbaza eraro: “%s”"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/es.js b/lib/l10n/es.js
index 69dd8aaebeb..59f28b1bb3b 100644
--- a/lib/l10n/es.js
+++ b/lib/l10n/es.js
@@ -4,7 +4,9 @@ OC.L10N.register(
"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" : "Se podría solucionar esto dándole al servidor permisos de escritura del directorio de configuración",
"See %s" : "Ver %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "O, si prefieres mantener el archivo config.php como de solo lectura, marca la opción \"config_is_read_only\" a 'true' en él.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Se podría solucionar esto dándole al servidor permisos de escritura del directorio de configuración. Ver %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "O, si prefieres mantener el archivo config.php como de solo lectura, marca la opción \"config_is_read_only\" a 'true' en él. 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" : "Configuración de ejemplo detectada",
"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",
@@ -27,6 +29,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se necesita la versión %s o superior del servidor.",
"Server version %s or lower is required." : "Se necesita la versión %s o inferior del servidor. ",
+ "Logged in user must be an admin" : "El usuario registrado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen de avatar no es cuadrada",
@@ -57,36 +60,39 @@ OC.L10N.register(
"Empty filename is not allowed" : "No se puede dejar el nombre en blanco.",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "No se puede instalar la app \"%s\" debido a que no se puede leer la información de la app.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "No se puede instalar la aplicación \"%s\" porque no es compatible con esta versión del servidor.",
+ "__language_name__" : "Castellano",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no responda.",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuración",
- "Log out" : "Desconectar",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Usuario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Eliminar",
+ "Share" : "Compartir",
+ "Overview" : "Vista general",
"Basic settings" : "Ajustes básicos",
"Sharing" : "Compartir",
"Security" : "Seguridad",
"Encryption" : "Cifrado",
+ "Groupware" : "Groupware",
"Additional settings" : "Configuración adicional",
- "Tips & tricks" : "Sugerencias y trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Clientes de sincronización",
+ "Mobile & desktop" : "Móvil y escritorio",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español",
"Verifying" : "Verificando",
"Verifying …" : "Verificando...",
"Verify" : "Verificar",
"%s enter the database username and name." : "%s introduzca el nombre de usuario y la contraseña de la BBDD.",
- "%s enter the database username." : "%s ingresar el usuario de la base de datos.",
- "%s enter the database name." : "%s ingresar el nombre de la base de datos",
+ "%s enter the database username." : "%s introduzca el usuario de la base de datos.",
+ "%s enter the database name." : "%s introduzca el nombre de la base de datos",
"%s you may not use dots in the database name" : "%s puede utilizar puntos en el nombre de la base de datos",
"Oracle connection could not be established" : "No se pudo establecer la conexión a Oracle",
"Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle no válidos",
"PostgreSQL username and/or password not valid" : "Usuario y/o contraseña de PostgreSQL no válidos",
- "You need to enter details of an existing account." : "Necesita ingresar detalles de una cuenta existente.",
+ "You need to enter details of an existing account." : "Tienes que introducir los datos de una cuenta existente.",
"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X no está soportado y %s no funcionará bien en esta plataforma. ¡Úsela bajo su propio riesgo! ",
"For the best results, please consider using a GNU/Linux server instead." : "Para obtener los mejores resultados, considera utilizar un servidor GNU/Linux.",
"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." : "Parece que esta instancia %s está funcionando en un entorno PHP de 32-bits y el open_basedir se ha configurado en php.ini. Esto acarreará problemas con arhivos de tamaño superior a 4GB y resulta totalmente desaconsejado.",
@@ -98,15 +104,15 @@ OC.L10N.register(
"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",
"You are not allowed to share %s" : "Usted no está autorizado para compartir %s",
- "Sharing %s failed, because you can not share with yourself" : "Se falló al compartir %s, porque no puedes compartir contigo mismo",
+ "Sharing %s failed, because you can not share with yourself" : "Fallo al compartir %s, porque no puedes compartir contigo mismo",
"Sharing %s failed, because the user %s does not exist" : "Se ha fallado al compartir %s, ya que el usuario %s no existe",
"Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Se ha fallado al compartir %s, ya que el usuario %s no es miembro de ningún grupo del que %s sea miembro",
- "Sharing %s failed, because this item is already shared with %s" : "Se falló al compartir %s, ya que este elemento ya está compartido con %s",
- "Sharing %s failed, because this item is already shared with user %s" : "Compartiendo %s falló, porque este objeto ya se comparte con el usuario %s",
- "Sharing %s failed, because the group %s does not exist" : "Se falló al compartir %s, ya que el grupo %s no existe",
- "Sharing %s failed, because %s is not a member of the group %s" : "Se falló al compartir %s, ya que %s no es miembro del grupo %s",
+ "Sharing %s failed, because this item is already shared with %s" : "Fallo al compartir %s, ya que este elemento ya está compartido con %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "Fallo al compartir %s, porque este objeto ya se comparte con el usuario %s",
+ "Sharing %s failed, because the group %s does not exist" : "Fallo al compartir %s, ya que el grupo %s no existe",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Fallo al compartir %s, ya que %s no es miembro del grupo %s",
"You need to provide a password to create a public link, only protected links are allowed" : "Es necesario definir una contraseña para crear un enlace publico. Solo los enlaces protegidos están permitidos",
- "Sharing %s failed, because sharing with links is not allowed" : "Se falló al compartir %s, ya que no está permitida la compartición con enlaces",
+ "Sharing %s failed, because sharing with links is not allowed" : "Fallo al compartir %s, ya que no se permite compartir con enlaces",
"Not allowed to create a federated share with the same user" : "No se permite crear un recurso compartido federado con el mismo usuario",
"Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Fallo al compartir %s. No se ha podido encontrar %s, quizás haya un problema de conexión con el servidor.",
"Share type %s is not valid for %s" : "El tipo de recurso compartido %s no es válido para %s",
@@ -119,7 +125,7 @@ OC.L10N.register(
"Sharing %s failed, because the permissions exceed permissions granted to %s" : "Se ha fallado al compartir %s, ya que los permisos superan los permisos otorgados a %s",
"Sharing %s failed, because resharing is not allowed" : "Fallo al compartir %s, ya que no está permitido volverlo a compartir",
"Sharing %s failed, because the sharing backend for %s could not find its source" : "Se ha fallado al compartir %s porque el motor compartido para %s podría no encontrar su origen",
- "Sharing %s failed, because the file could not be found in the file cache" : "Se ha fallado al compartir %s, ya que el archivo no pudo ser encontrado en el cache de archivo",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Fallo al compartir %s, ya que el archivo no se ha encontrado en el caché de archivo",
"Can’t increase permissions of %s" : "No se pueden aumentar los permisos de %s",
"Files can’t be shared with delete permissions" : "Los archivos no se pueden compartir con permisos de borrado",
"Files can’t be shared with create permissions" : "Los archivos no se pueden compartir con permisos de creación",
@@ -200,7 +206,7 @@ OC.L10N.register(
"Cannot create \"data\" directory" : "No se puede crear el directorio \"data\"",
"This can usually be fixed by giving the webserver write access to the root directory. See %s" : "Habitualmente, esto puede arreglarse dando al servidor web acceso de escritura al directorio raíz. Véase %s",
"Permissions can usually be fixed by giving the webserver write access to the root directory. See %s." : "Habitualmente, los permisos pueden arreglarse dando al servidor web acceso de escritura al directorio raíz. Véase %s",
- "Setting locale to %s failed" : "Falló la activación del idioma %s ",
+ "Setting locale to %s failed" : "Ha fallado la activación del idioma %s ",
"Please install one of these locales on your system and restart your webserver." : "Instale uno de estos idiomas en su sistema y reinicie su servidor web.",
"Please ask your server administrator to install the module." : "Consulte al administrador de su servidor para instalar el módulo.",
"PHP module %s not installed." : "El módulo PHP %s no está instalado.",
@@ -222,11 +228,34 @@ OC.L10N.register(
"Check the value of \"datadirectory\" in your configuration" : "Compruebe el valor de \"datadirectory\" en su configuración.",
"Your data directory is invalid" : "Tu directorio de datos es inválido",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegúrate de que existe un archivo llamado \".ocdata\" en la raíz del directorio de datos.",
+ "Action \"%s\" not supported or implemented." : "La acción \"%s\" no está soportada o implementada.",
+ "Authentication failed, wrong token or provider ID given" : "La autenticación ha fallado. Se ha dado un token o una ID de proveedor erróneos.",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Faltan parámetros para completar la petición. Parámetros que faltan: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "La Id \"%s\" ya es usada por el proveedor de nube federada \"%s\"",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "El proveedor de nube federada con ID \"%s\" no existe.",
"Could not obtain lock type %d on \"%s\"." : "No se pudo realizar el bloqueo %d en \"%s\".",
"Storage unauthorized. %s" : "Almacenamiento no autorizado. %s",
"Storage incomplete configuration. %s" : "Configuración de almacenamiento incompleta. %s",
"Storage connection error. %s" : "Error de conexión de almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamiento no esta disponible temporalmente",
- "Storage connection timeout. %s" : "Tiempo de conexión de almacenamiento agotado. %s"
+ "Storage connection timeout. %s" : "Tiempo de conexión de almacenamiento agotado. %s",
+ "Personal" : "Personal",
+ "Admin" : "Administración",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Sugerencias y trucos",
+ "DB Error: \"%s\"" : "Error de BD: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando ofensivo fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando ofensivo fue: \"%s\", nombre: %s, contraseña: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Ha fallado la configuración de permisos para %s porque los permisos exceden los permisos concedidos a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Ha fallado la configuración de permisos para %s porque no se ha encontrado el objeto",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede eliminar la fecha de expiración. Se requiere que los recursos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden aumentar los permisos de %s",
+ "Files can't be shared with delete permissions" : "Los archivos no se pueden compartir con permisos de borrado",
+ "Files can't be shared with create permissions" : "Los archivos no se pueden compartir con permisos de creación",
+ "Cannot set expiration date more than %s days in the future" : "No se puede marcar la fecha de expiración a más de %s días en el futuro",
+ "No app name specified" : "No se ha especificado ningún nombre de app",
+ "App '%s' could not be installed!" : "¡No se ha podido instalar la app '%s'!",
+ "Sync clients" : "Clientes de sincronización"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es.json b/lib/l10n/es.json
index ac2a24ef317..1c0914fcd66 100644
--- a/lib/l10n/es.json
+++ b/lib/l10n/es.json
@@ -2,7 +2,9 @@
"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" : "Se podría solucionar esto dándole al servidor permisos de escritura del directorio de configuración",
"See %s" : "Ver %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "O, si prefieres mantener el archivo config.php como de solo lectura, marca la opción \"config_is_read_only\" a 'true' en él.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Se podría solucionar esto dándole al servidor permisos de escritura del directorio de configuración. Ver %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "O, si prefieres mantener el archivo config.php como de solo lectura, marca la opción \"config_is_read_only\" a 'true' en él. 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" : "Configuración de ejemplo detectada",
"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",
@@ -25,6 +27,7 @@
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se necesita la versión %s o superior del servidor.",
"Server version %s or lower is required." : "Se necesita la versión %s o inferior del servidor. ",
+ "Logged in user must be an admin" : "El usuario registrado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen de avatar no es cuadrada",
@@ -55,36 +58,39 @@
"Empty filename is not allowed" : "No se puede dejar el nombre en blanco.",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "No se puede instalar la app \"%s\" debido a que no se puede leer la información de la app.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "No se puede instalar la aplicación \"%s\" porque no es compatible con esta versión del servidor.",
+ "__language_name__" : "Castellano",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no responda.",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuración",
- "Log out" : "Desconectar",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Usuario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Eliminar",
+ "Share" : "Compartir",
+ "Overview" : "Vista general",
"Basic settings" : "Ajustes básicos",
"Sharing" : "Compartir",
"Security" : "Seguridad",
"Encryption" : "Cifrado",
+ "Groupware" : "Groupware",
"Additional settings" : "Configuración adicional",
- "Tips & tricks" : "Sugerencias y trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Clientes de sincronización",
+ "Mobile & desktop" : "Móvil y escritorio",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español",
"Verifying" : "Verificando",
"Verifying …" : "Verificando...",
"Verify" : "Verificar",
"%s enter the database username and name." : "%s introduzca el nombre de usuario y la contraseña de la BBDD.",
- "%s enter the database username." : "%s ingresar el usuario de la base de datos.",
- "%s enter the database name." : "%s ingresar el nombre de la base de datos",
+ "%s enter the database username." : "%s introduzca el usuario de la base de datos.",
+ "%s enter the database name." : "%s introduzca el nombre de la base de datos",
"%s you may not use dots in the database name" : "%s puede utilizar puntos en el nombre de la base de datos",
"Oracle connection could not be established" : "No se pudo establecer la conexión a Oracle",
"Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle no válidos",
"PostgreSQL username and/or password not valid" : "Usuario y/o contraseña de PostgreSQL no válidos",
- "You need to enter details of an existing account." : "Necesita ingresar detalles de una cuenta existente.",
+ "You need to enter details of an existing account." : "Tienes que introducir los datos de una cuenta existente.",
"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X no está soportado y %s no funcionará bien en esta plataforma. ¡Úsela bajo su propio riesgo! ",
"For the best results, please consider using a GNU/Linux server instead." : "Para obtener los mejores resultados, considera utilizar un servidor GNU/Linux.",
"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." : "Parece que esta instancia %s está funcionando en un entorno PHP de 32-bits y el open_basedir se ha configurado en php.ini. Esto acarreará problemas con arhivos de tamaño superior a 4GB y resulta totalmente desaconsejado.",
@@ -96,15 +102,15 @@
"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",
"You are not allowed to share %s" : "Usted no está autorizado para compartir %s",
- "Sharing %s failed, because you can not share with yourself" : "Se falló al compartir %s, porque no puedes compartir contigo mismo",
+ "Sharing %s failed, because you can not share with yourself" : "Fallo al compartir %s, porque no puedes compartir contigo mismo",
"Sharing %s failed, because the user %s does not exist" : "Se ha fallado al compartir %s, ya que el usuario %s no existe",
"Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Se ha fallado al compartir %s, ya que el usuario %s no es miembro de ningún grupo del que %s sea miembro",
- "Sharing %s failed, because this item is already shared with %s" : "Se falló al compartir %s, ya que este elemento ya está compartido con %s",
- "Sharing %s failed, because this item is already shared with user %s" : "Compartiendo %s falló, porque este objeto ya se comparte con el usuario %s",
- "Sharing %s failed, because the group %s does not exist" : "Se falló al compartir %s, ya que el grupo %s no existe",
- "Sharing %s failed, because %s is not a member of the group %s" : "Se falló al compartir %s, ya que %s no es miembro del grupo %s",
+ "Sharing %s failed, because this item is already shared with %s" : "Fallo al compartir %s, ya que este elemento ya está compartido con %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "Fallo al compartir %s, porque este objeto ya se comparte con el usuario %s",
+ "Sharing %s failed, because the group %s does not exist" : "Fallo al compartir %s, ya que el grupo %s no existe",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Fallo al compartir %s, ya que %s no es miembro del grupo %s",
"You need to provide a password to create a public link, only protected links are allowed" : "Es necesario definir una contraseña para crear un enlace publico. Solo los enlaces protegidos están permitidos",
- "Sharing %s failed, because sharing with links is not allowed" : "Se falló al compartir %s, ya que no está permitida la compartición con enlaces",
+ "Sharing %s failed, because sharing with links is not allowed" : "Fallo al compartir %s, ya que no se permite compartir con enlaces",
"Not allowed to create a federated share with the same user" : "No se permite crear un recurso compartido federado con el mismo usuario",
"Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Fallo al compartir %s. No se ha podido encontrar %s, quizás haya un problema de conexión con el servidor.",
"Share type %s is not valid for %s" : "El tipo de recurso compartido %s no es válido para %s",
@@ -117,7 +123,7 @@
"Sharing %s failed, because the permissions exceed permissions granted to %s" : "Se ha fallado al compartir %s, ya que los permisos superan los permisos otorgados a %s",
"Sharing %s failed, because resharing is not allowed" : "Fallo al compartir %s, ya que no está permitido volverlo a compartir",
"Sharing %s failed, because the sharing backend for %s could not find its source" : "Se ha fallado al compartir %s porque el motor compartido para %s podría no encontrar su origen",
- "Sharing %s failed, because the file could not be found in the file cache" : "Se ha fallado al compartir %s, ya que el archivo no pudo ser encontrado en el cache de archivo",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Fallo al compartir %s, ya que el archivo no se ha encontrado en el caché de archivo",
"Can’t increase permissions of %s" : "No se pueden aumentar los permisos de %s",
"Files can’t be shared with delete permissions" : "Los archivos no se pueden compartir con permisos de borrado",
"Files can’t be shared with create permissions" : "Los archivos no se pueden compartir con permisos de creación",
@@ -198,7 +204,7 @@
"Cannot create \"data\" directory" : "No se puede crear el directorio \"data\"",
"This can usually be fixed by giving the webserver write access to the root directory. See %s" : "Habitualmente, esto puede arreglarse dando al servidor web acceso de escritura al directorio raíz. Véase %s",
"Permissions can usually be fixed by giving the webserver write access to the root directory. See %s." : "Habitualmente, los permisos pueden arreglarse dando al servidor web acceso de escritura al directorio raíz. Véase %s",
- "Setting locale to %s failed" : "Falló la activación del idioma %s ",
+ "Setting locale to %s failed" : "Ha fallado la activación del idioma %s ",
"Please install one of these locales on your system and restart your webserver." : "Instale uno de estos idiomas en su sistema y reinicie su servidor web.",
"Please ask your server administrator to install the module." : "Consulte al administrador de su servidor para instalar el módulo.",
"PHP module %s not installed." : "El módulo PHP %s no está instalado.",
@@ -220,11 +226,34 @@
"Check the value of \"datadirectory\" in your configuration" : "Compruebe el valor de \"datadirectory\" en su configuración.",
"Your data directory is invalid" : "Tu directorio de datos es inválido",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegúrate de que existe un archivo llamado \".ocdata\" en la raíz del directorio de datos.",
+ "Action \"%s\" not supported or implemented." : "La acción \"%s\" no está soportada o implementada.",
+ "Authentication failed, wrong token or provider ID given" : "La autenticación ha fallado. Se ha dado un token o una ID de proveedor erróneos.",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Faltan parámetros para completar la petición. Parámetros que faltan: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "La Id \"%s\" ya es usada por el proveedor de nube federada \"%s\"",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "El proveedor de nube federada con ID \"%s\" no existe.",
"Could not obtain lock type %d on \"%s\"." : "No se pudo realizar el bloqueo %d en \"%s\".",
"Storage unauthorized. %s" : "Almacenamiento no autorizado. %s",
"Storage incomplete configuration. %s" : "Configuración de almacenamiento incompleta. %s",
"Storage connection error. %s" : "Error de conexión de almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamiento no esta disponible temporalmente",
- "Storage connection timeout. %s" : "Tiempo de conexión de almacenamiento agotado. %s"
+ "Storage connection timeout. %s" : "Tiempo de conexión de almacenamiento agotado. %s",
+ "Personal" : "Personal",
+ "Admin" : "Administración",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Sugerencias y trucos",
+ "DB Error: \"%s\"" : "Error de BD: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando ofensivo fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando ofensivo fue: \"%s\", nombre: %s, contraseña: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Ha fallado la configuración de permisos para %s porque los permisos exceden los permisos concedidos a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Ha fallado la configuración de permisos para %s porque no se ha encontrado el objeto",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede eliminar la fecha de expiración. Se requiere que los recursos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden aumentar los permisos de %s",
+ "Files can't be shared with delete permissions" : "Los archivos no se pueden compartir con permisos de borrado",
+ "Files can't be shared with create permissions" : "Los archivos no se pueden compartir con permisos de creación",
+ "Cannot set expiration date more than %s days in the future" : "No se puede marcar la fecha de expiración a más de %s días en el futuro",
+ "No app name specified" : "No se ha especificado ningún nombre de app",
+ "App '%s' could not be installed!" : "¡No se ha podido instalar la app '%s'!",
+ "Sync clients" : "Clientes de sincronización"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_419.js b/lib/l10n/es_419.js
index 0ee9825cf65..d1b7f54eae2 100644
--- a/lib/l10n/es_419.js
+++ b/lib/l10n/es_419.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Latin America)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -64,18 +65,13 @@ OC.L10N.register(
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Latin America)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +223,10 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_419.json b/lib/l10n/es_419.json
index 1218704aea4..0d19207cb80 100644
--- a/lib/l10n/es_419.json
+++ b/lib/l10n/es_419.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Latin America)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -62,18 +63,13 @@
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Latin America)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +221,10 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_AR.js b/lib/l10n/es_AR.js
index 0190d3e0a7e..d5cb6aebed6 100644
--- a/lib/l10n/es_AR.js
+++ b/lib/l10n/es_AR.js
@@ -47,21 +47,18 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Argentina)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, favor de no contestarlo. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos y trucos",
- "__language_name__" : "Español (Argentina)",
"%s enter the database username and name." : "%s ingrese el nombre del usuario y nombre de la base de datos",
"%s enter the database username." : "%s ingresar el nombre de usuario de la base de datos.",
"%s enter the database name." : "%s ingresar el nombre de la base de datos",
@@ -200,6 +197,9 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "Se agotó el tiempo de conexión del almacenamiento. %s"
+ "Storage connection timeout. %s" : "Se agotó el tiempo de conexión del almacenamiento. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos y trucos"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_AR.json b/lib/l10n/es_AR.json
index cfe5f41a676..5100beeb414 100644
--- a/lib/l10n/es_AR.json
+++ b/lib/l10n/es_AR.json
@@ -45,21 +45,18 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Argentina)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, favor de no contestarlo. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos y trucos",
- "__language_name__" : "Español (Argentina)",
"%s enter the database username and name." : "%s ingrese el nombre del usuario y nombre de la base de datos",
"%s enter the database username." : "%s ingresar el nombre de usuario de la base de datos.",
"%s enter the database name." : "%s ingresar el nombre de la base de datos",
@@ -198,6 +195,9 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "Se agotó el tiempo de conexión del almacenamiento. %s"
+ "Storage connection timeout. %s" : "Se agotó el tiempo de conexión del almacenamiento. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos y trucos"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_CL.js b/lib/l10n/es_CL.js
index 965ad53dbb1..1002b064857 100644
--- a/lib/l10n/es_CL.js
+++ b/lib/l10n/es_CL.js
@@ -27,6 +27,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -57,25 +58,26 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Chile)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +229,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_CL.json b/lib/l10n/es_CL.json
index 3caf34bd6ed..f29877d6b0b 100644
--- a/lib/l10n/es_CL.json
+++ b/lib/l10n/es_CL.json
@@ -25,6 +25,7 @@
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -55,25 +56,26 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Chile)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +227,24 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_CO.js b/lib/l10n/es_CO.js
index 47037e0f919..1002b064857 100644
--- a/lib/l10n/es_CO.js
+++ b/lib/l10n/es_CO.js
@@ -27,6 +27,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -57,25 +58,26 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Colombia)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +229,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_CO.json b/lib/l10n/es_CO.json
index e7bf27285e6..f29877d6b0b 100644
--- a/lib/l10n/es_CO.json
+++ b/lib/l10n/es_CO.json
@@ -25,6 +25,7 @@
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -55,25 +56,26 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Colombia)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +227,24 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_CR.js b/lib/l10n/es_CR.js
index 47b67fe2cb9..1002b064857 100644
--- a/lib/l10n/es_CR.js
+++ b/lib/l10n/es_CR.js
@@ -27,6 +27,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -57,25 +58,26 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Costa Rica)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +229,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_CR.json b/lib/l10n/es_CR.json
index c8b5a408b98..f29877d6b0b 100644
--- a/lib/l10n/es_CR.json
+++ b/lib/l10n/es_CR.json
@@ -25,6 +25,7 @@
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -55,25 +56,26 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Costa Rica)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +227,24 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_DO.js b/lib/l10n/es_DO.js
index 431353e1bd1..1002b064857 100644
--- a/lib/l10n/es_DO.js
+++ b/lib/l10n/es_DO.js
@@ -27,6 +27,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -57,25 +58,26 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Dominican Republic)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +229,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_DO.json b/lib/l10n/es_DO.json
index 478cef39f2c..f29877d6b0b 100644
--- a/lib/l10n/es_DO.json
+++ b/lib/l10n/es_DO.json
@@ -25,6 +25,7 @@
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -55,25 +56,26 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Dominican Republic)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +227,24 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_EC.js b/lib/l10n/es_EC.js
index 47ee73f292b..1002b064857 100644
--- a/lib/l10n/es_EC.js
+++ b/lib/l10n/es_EC.js
@@ -27,6 +27,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -57,25 +58,26 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Ecuador)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +229,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_EC.json b/lib/l10n/es_EC.json
index e1a2954e06d..f29877d6b0b 100644
--- a/lib/l10n/es_EC.json
+++ b/lib/l10n/es_EC.json
@@ -25,6 +25,7 @@
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -55,25 +56,26 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Ecuador)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +227,24 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_GT.js b/lib/l10n/es_GT.js
index da138c865bb..1002b064857 100644
--- a/lib/l10n/es_GT.js
+++ b/lib/l10n/es_GT.js
@@ -27,6 +27,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -57,25 +58,26 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Guatemala)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +229,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_GT.json b/lib/l10n/es_GT.json
index 943bd570d0f..f29877d6b0b 100644
--- a/lib/l10n/es_GT.json
+++ b/lib/l10n/es_GT.json
@@ -25,6 +25,7 @@
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -55,25 +56,26 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Guatemala)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +227,24 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_HN.js b/lib/l10n/es_HN.js
index 09bdb26fe4c..4f46d2cd040 100644
--- a/lib/l10n/es_HN.js
+++ b/lib/l10n/es_HN.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Honduras)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -64,18 +65,13 @@ OC.L10N.register(
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Honduras)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +223,10 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_HN.json b/lib/l10n/es_HN.json
index 4c2fbdfef19..ab057a17c9a 100644
--- a/lib/l10n/es_HN.json
+++ b/lib/l10n/es_HN.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Honduras)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -62,18 +63,13 @@
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Honduras)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +221,10 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_MX.js b/lib/l10n/es_MX.js
index cdcda60123a..575d11b5e70 100644
--- a/lib/l10n/es_MX.js
+++ b/lib/l10n/es_MX.js
@@ -27,6 +27,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -57,25 +58,27 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
+ "Mobile & desktop" : "Móvil & escritorio",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (México)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +230,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_MX.json b/lib/l10n/es_MX.json
index 124bfc2de32..83dbe76dac0 100644
--- a/lib/l10n/es_MX.json
+++ b/lib/l10n/es_MX.json
@@ -25,6 +25,7 @@
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -55,25 +56,27 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
+ "Mobile & desktop" : "Móvil & escritorio",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (México)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +228,24 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_NI.js b/lib/l10n/es_NI.js
index 5419d0ee17a..1b6cf810e71 100644
--- a/lib/l10n/es_NI.js
+++ b/lib/l10n/es_NI.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Nicaragua)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -64,18 +65,13 @@ OC.L10N.register(
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Nicaragua)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +223,10 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_NI.json b/lib/l10n/es_NI.json
index da491ca9da5..a787ebe2d03 100644
--- a/lib/l10n/es_NI.json
+++ b/lib/l10n/es_NI.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Nicaragua)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -62,18 +63,13 @@
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Nicaragua)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +221,10 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_PA.js b/lib/l10n/es_PA.js
index 2a459b1b89a..c16f549a918 100644
--- a/lib/l10n/es_PA.js
+++ b/lib/l10n/es_PA.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Panama)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -64,18 +65,13 @@ OC.L10N.register(
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Panama)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +223,10 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_PA.json b/lib/l10n/es_PA.json
index 444e91a82a5..63558bdd6c7 100644
--- a/lib/l10n/es_PA.json
+++ b/lib/l10n/es_PA.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Panama)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -62,18 +63,13 @@
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Panama)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +221,10 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_PE.js b/lib/l10n/es_PE.js
index 7cd144dd88a..0364835f324 100644
--- a/lib/l10n/es_PE.js
+++ b/lib/l10n/es_PE.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Peru)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -64,18 +65,13 @@ OC.L10N.register(
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Peru)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +223,10 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_PE.json b/lib/l10n/es_PE.json
index 3e52e90a534..86aa71cf7c3 100644
--- a/lib/l10n/es_PE.json
+++ b/lib/l10n/es_PE.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Peru)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -62,18 +63,13 @@
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Peru)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +221,10 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_PR.js b/lib/l10n/es_PR.js
index 1f8bc98c5ef..d317aa8c90b 100644
--- a/lib/l10n/es_PR.js
+++ b/lib/l10n/es_PR.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Puerto Rico)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -64,18 +65,13 @@ OC.L10N.register(
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Puerto Rico)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +223,10 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_PR.json b/lib/l10n/es_PR.json
index bfb103e2dbe..72bc8e46e87 100644
--- a/lib/l10n/es_PR.json
+++ b/lib/l10n/es_PR.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Puerto Rico)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -62,18 +63,13 @@
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Puerto Rico)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +221,10 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_PY.js b/lib/l10n/es_PY.js
index 72fb5e4e749..23080660d7b 100644
--- a/lib/l10n/es_PY.js
+++ b/lib/l10n/es_PY.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Paraguay)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -64,18 +65,13 @@ OC.L10N.register(
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Paraguay)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +223,10 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_PY.json b/lib/l10n/es_PY.json
index f8d35c94712..3f877acbac6 100644
--- a/lib/l10n/es_PY.json
+++ b/lib/l10n/es_PY.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Paraguay)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -62,18 +63,13 @@
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Paraguay)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +221,10 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_SV.js b/lib/l10n/es_SV.js
index 085ba148c53..1002b064857 100644
--- a/lib/l10n/es_SV.js
+++ b/lib/l10n/es_SV.js
@@ -27,6 +27,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -57,25 +58,26 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (El Salvador)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +229,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_SV.json b/lib/l10n/es_SV.json
index 925c6d54591..f29877d6b0b 100644
--- a/lib/l10n/es_SV.json
+++ b/lib/l10n/es_SV.json
@@ -25,6 +25,7 @@
"Following platforms are supported: %s" : "Las siguientes plataformas están soportadas: %s",
"Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ",
"Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ",
+ "Logged in user must be an admin" : "El usuario firmado debe ser un administrador",
"Unknown filetype" : "Tipo de archivo desconocido",
"Invalid image" : "Imagen inválida",
"Avatar image is not square" : "La imagen del avatar no es un cuadrado",
@@ -55,25 +56,26 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (México)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
"Settings" : "Configuraciones",
- "Log out" : "Salir",
+ "Log out" : "Cerrar sesión",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crear",
+ "Change" : "Cambiar",
+ "Delete" : "Borrar",
+ "Share" : "Compartir",
+ "Overview" : "Generalidades",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (El Salvador)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +227,24 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "Personal" : "Personal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "DB Error: \"%s\"" : "DB Error: \"%s\"",
+ "Offending command was: \"%s\"" : "El comando infractor fue: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "El comando infractor fue: \"%s\", nombre:%s, contraseña:%s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Se presentó una falla al establecer los permisos de %s, porque los permisos excenden los permisos otorgados a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Se presentó una falla al establecer los permisos de %s, porque no se encontró el elemento",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "No se puede limpíar la fecha de expiración. Se requiere que los elementos compartidos tengan una fecha de expiración.",
+ "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s",
+ "Files can't be shared with delete permissions" : "No se pueden compartir archivos con privilegios para borrar",
+ "Files can't be shared with create permissions" : "No se pueden compartir archivos con privilegios para crear",
+ "Cannot set expiration date more than %s days in the future" : "No se puede establecer la fecha de expiración más alla de %s días en el futuro",
+ "No app name specified" : "No se especificó el nombre de la aplicación",
+ "App '%s' could not be installed!" : "¡No se pudo instalar la aplciación '%s'!",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/es_UY.js b/lib/l10n/es_UY.js
index 404dc0652a7..ec07e1fdc14 100644
--- a/lib/l10n/es_UY.js
+++ b/lib/l10n/es_UY.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Uruguay)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -64,18 +65,13 @@ OC.L10N.register(
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Uruguay)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -227,6 +223,10 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/es_UY.json b/lib/l10n/es_UY.json
index 246a5ef228f..a9f65b90d7c 100644
--- a/lib/l10n/es_UY.json
+++ b/lib/l10n/es_UY.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "El uso de nombres de archivo vacíos no está permitido",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "La aplicación \"%s\" no puede ser instalada porque el archivo appinfo no se puede leer. ",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión del servidor. ",
+ "__language_name__" : "Español (Uruguay)",
"This is an automatically sent email, please do not reply." : "Este es un correo enviado automáticamente, por favor no lo contestes. ",
"Help" : "Ayuda",
"Apps" : "Aplicaciones",
@@ -62,18 +63,13 @@
"Log out" : "Salir",
"Users" : "Usuarios",
"Unknown user" : "Ususario desconocido",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Configuraciones básicas",
"Sharing" : "Compartiendo",
"Security" : "Seguridad",
"Encryption" : "Encripción",
"Additional settings" : "Configuraciones adicionales",
- "Tips & tricks" : "Consejos & trucos",
"Personal info" : "Información personal",
- "Sync clients" : "Sincronizar clientes",
"Unlimited" : "Ilimitado",
- "__language_name__" : "Español (Uruguay)",
"Verifying" : "Verficando",
"Verifying …" : "Verficando ...",
"Verify" : "Verificar",
@@ -225,6 +221,10 @@
"Storage incomplete configuration. %s" : "Configuración incompleta del almacenamiento. %s",
"Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s",
"Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible",
- "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s"
+ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Consejos & trucos",
+ "Sync clients" : "Sincronizar clientes"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/et_EE.js b/lib/l10n/et_EE.js
index d56683daa2e..c322c6342ff 100644
--- a/lib/l10n/et_EE.js
+++ b/lib/l10n/et_EE.js
@@ -37,6 +37,7 @@ OC.L10N.register(
"File name is too long" : "Faili nimi on liiga pikk",
"Dot files are not allowed" : "Punktiga failid pole lubatud",
"Empty filename is not allowed" : "Tühi failinimi pole lubatud",
+ "__language_name__" : "Eesti",
"This is an automatically sent email, please do not reply." : "See on automaatselt saadetud e-kiri, palun ära vasta.",
"Help" : "Abi",
"Apps" : "Rakendused",
@@ -49,11 +50,8 @@ OC.L10N.register(
"Security" : "Turvalisus",
"Encryption" : "Krüpteerimine",
"Additional settings" : "Lisaseaded",
- "Tips & tricks" : "Nõuanded ja trikid",
"Personal info" : "Isiklik info",
- "Sync clients" : "Klientide sünkroniseerimine",
"Unlimited" : "Piiramatult",
- "__language_name__" : "Eesti",
"Verifying" : "Kontrollin",
"Verifying …" : "Kontrollin ...",
"Verify" : "Kontrolli",
@@ -182,6 +180,8 @@ OC.L10N.register(
"PostgreSQL >= 9 required" : "PostgreSQL >= 9 on nõutav",
"Please upgrade your database version" : "Palun uuenda oma andmebaasi versiooni",
"Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Palun muuda kataloogi õigused 0770-ks, et kataloogi sisu poleks teistele kasutajatele nähtav",
- "Could not obtain lock type %d on \"%s\"." : "Ei suutnud hankida %d tüüpi lukustust \"%s\"."
+ "Could not obtain lock type %d on \"%s\"." : "Ei suutnud hankida %d tüüpi lukustust \"%s\".",
+ "Tips & tricks" : "Nõuanded ja trikid",
+ "Sync clients" : "Klientide sünkroniseerimine"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/et_EE.json b/lib/l10n/et_EE.json
index 93f0d85ccf3..d94732acdba 100644
--- a/lib/l10n/et_EE.json
+++ b/lib/l10n/et_EE.json
@@ -35,6 +35,7 @@
"File name is too long" : "Faili nimi on liiga pikk",
"Dot files are not allowed" : "Punktiga failid pole lubatud",
"Empty filename is not allowed" : "Tühi failinimi pole lubatud",
+ "__language_name__" : "Eesti",
"This is an automatically sent email, please do not reply." : "See on automaatselt saadetud e-kiri, palun ära vasta.",
"Help" : "Abi",
"Apps" : "Rakendused",
@@ -47,11 +48,8 @@
"Security" : "Turvalisus",
"Encryption" : "Krüpteerimine",
"Additional settings" : "Lisaseaded",
- "Tips & tricks" : "Nõuanded ja trikid",
"Personal info" : "Isiklik info",
- "Sync clients" : "Klientide sünkroniseerimine",
"Unlimited" : "Piiramatult",
- "__language_name__" : "Eesti",
"Verifying" : "Kontrollin",
"Verifying …" : "Kontrollin ...",
"Verify" : "Kontrolli",
@@ -180,6 +178,8 @@
"PostgreSQL >= 9 required" : "PostgreSQL >= 9 on nõutav",
"Please upgrade your database version" : "Palun uuenda oma andmebaasi versiooni",
"Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Palun muuda kataloogi õigused 0770-ks, et kataloogi sisu poleks teistele kasutajatele nähtav",
- "Could not obtain lock type %d on \"%s\"." : "Ei suutnud hankida %d tüüpi lukustust \"%s\"."
+ "Could not obtain lock type %d on \"%s\"." : "Ei suutnud hankida %d tüüpi lukustust \"%s\".",
+ "Tips & tricks" : "Nõuanded ja trikid",
+ "Sync clients" : "Klientide sünkroniseerimine"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/eu.js b/lib/l10n/eu.js
new file mode 100644
index 00000000000..baafa10dda4
--- /dev/null
+++ b/lib/l10n/eu.js
@@ -0,0 +1,154 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Ezin da idatzi \"config\" karpetan!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Hau normalean konpondu daitekesweb zerbitzarira config karpetan idazteko baimenak emanez",
+ "See %s" : "Ikusi %s",
+ "Sample configuration detected" : "Adibide-ezarpena detektatua",
+ "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" : "Detektatu da adibide-ezarpena kopiatu dela. Honek zure instalazioa apur dezake eta ez da onartzen. Irakurri dokumentazioa config.php fitxategia aldatu aurretik.",
+ "%1$s and %2$s" : "%1$s eta %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s eta %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s eta %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s eta %5$s",
+ "PHP %s or higher is required." : "PHP %s edo berriagoa behar da.",
+ "PHP with a version lower than %s is required." : "PHPren bertsioa %s baino txikiagoa izan behar da.",
+ "Following databases are supported: %s" : "Hurrengo datubaseak onartzen dira: %s",
+ "The command line tool %s could not be found" : "Komando lerroko %s tresna ezin da aurkitu",
+ "The library %s is not available." : "%s liburutegia ez dago eskuragarri.",
+ "Library %s with a version higher than %s is required - available version %s." : "%s liburutegiak %s baino bertsio handiagoa izan behar du - dagoen bertsioa %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "%s liburutegiak %s baino bertsio txikiagoa izan behar du - dagoen bertsioa %s.",
+ "Following platforms are supported: %s" : "Hurrengo plataformak onartzen dira: %s",
+ "Unknown filetype" : "Fitxategi mota ezezaguna",
+ "Invalid image" : "Baliogabeko irudia",
+ "Avatar image is not square" : "Abatarreko irudia ez da karratua",
+ "today" : "gaur",
+ "yesterday" : "atzo",
+ "_%n day ago_::_%n days ago_" : ["orain dela egun %n","orain dela %n egun"],
+ "last month" : "joan den hilabetean",
+ "_%n month ago_::_%n months ago_" : ["orain dela hilabete %n","orain dela %n hilabete"],
+ "last year" : "joan den urtean",
+ "_%n year ago_::_%n years ago_" : ["orain dela urte %n","orain dela %n urte"],
+ "_%n hour ago_::_%n hours ago_" : ["orain dela ordu %n","orain dela %n ordu"],
+ "_%n minute ago_::_%n minutes ago_" : ["orain dela minutu %n","orain dela %n minutu"],
+ "seconds ago" : "duela segundu batzuk",
+ "File name is a reserved word" : "Fitxategi izena hitz erreserbatua da",
+ "File name contains at least one invalid character" : "Fitxategi izenak behintzat baliogabeko karaktere bat du",
+ "File name is too long" : "Fitxategi-izena luzeegia da",
+ "Dot files are not allowed" : "Dot fitxategiak ez dira onartzen",
+ "Empty filename is not allowed" : "Fitxategiaren izena izin da hutsa izan",
+ "__language_name__" : "Euskara",
+ "Help" : "Laguntza",
+ "Apps" : "Aplikazioak",
+ "Users" : "Erabiltzaileak",
+ "Unknown user" : "Erabiltzaile ezezaguna",
+ "Sharing" : "Partekatze",
+ "Encryption" : "Enkriptazio",
+ "Additional settings" : "Ezarpen gehiago",
+ "%s enter the database username and name." : "%s sartu datu-basearen erabiltzaile-izena eta izena.",
+ "%s enter the database username." : "%s sartu datu basearen erabiltzaile izena.",
+ "%s enter the database name." : "%s sartu datu basearen izena.",
+ "%s you may not use dots in the database name" : "%s ezin duzu punturik erabili datu basearen izenean.",
+ "Oracle connection could not be established" : "Ezin da Oracle konexioa sortu",
+ "Oracle username and/or password not valid" : "Oracle erabiltzaile edota pasahitza ez dira egokiak.",
+ "PostgreSQL username and/or password not valid" : "PostgreSQL erabiltzaile edota pasahitza ez dira egokiak.",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X-ek ez du sostengurik eta %s gaizki ibili daiteke plataforma honetan. Erabiltzekotan, zure ardurapean.",
+ "For the best results, please consider using a GNU/Linux server instead." : "Emaitza hobeak izateko, mesedez gogoan hartu GNU/Linux zerbitzari bat erabiltzea.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Mesedez ezabatu open_basedir ezarpena zure php.ini-tik edo aldatu 64-biteko PHPra.",
+ "Set an admin username." : "Ezarri administraziorako erabiltzaile izena.",
+ "Set an admin password." : "Ezarri administraziorako pasahitza.",
+ "Can't create or write into the data directory %s" : "Ezin da %s datu karpeta sortu edo bertan idatzi ",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "%s partekatzeak huts egin du, motorrak %i motako partekatzeak baimentzen ez dituelako",
+ "Sharing %s failed, because the file does not exist" : "%s elkarbanatzeak huts egin du, fitxategia ez delako existitzen",
+ "You are not allowed to share %s" : "Ez zadue %s elkarbanatzeko baimendua",
+ "Sharing %s failed, because the user %s does not exist" : "%s elkarbanatzeak huts egin du, %s erabiltzailea existitzen ez delako",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "%s elkarbanatzeak huts egin du, %s erabiltzailea ez delako %s partaide den talderen bateko partaidea",
+ "Sharing %s failed, because this item is already shared with %s" : "%s elkarbanatzeak huts egin du, dagoeneko %s erabiltzailearekin elkarbanatuta dagoelako",
+ "Sharing %s failed, because the group %s does not exist" : "%s elkarbanatzeak huts egin du, %s taldea ez delako existitzen",
+ "Sharing %s failed, because %s is not a member of the group %s" : "%s elkarbanatzeak huts egin du, %s ez delako %s taldearen partaidea",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Lotura publiko bat sortzeko pasahitza idatzi behar duzu, bakarrik babestutako loturak baimenduta daude",
+ "Sharing %s failed, because sharing with links is not allowed" : "%s elkarbanatzeak huts egin du, lotura bidezko elkarbanatzea baimendua ez dagoelako",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "%s partekatzeak huts egin du, ezin da %s aurkitu, agian zerbitzaria orain ez dago eskuragarri.",
+ "Share type %s is not valid for %s" : "%s elkarbanaketa mota ez da %srentzako egokia",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Ezin izan da jarri iraungitze data. Konpartitzea ezin da iraungi konpartitu eta %s ondoren.",
+ "Cannot set expiration date. Expiration date is in the past" : "Ezin da jarri iraungitze data. Iraungitze data iragan da.",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "%s elkarbanaketa motorra OCP\\Share_Backend interfazea inplementatu behar du ",
+ "Sharing backend %s not found" : "Ez da %s elkarbanaketa motorra aurkitu",
+ "Sharing backend for %s not found" : "Ez da %srako elkarbanaketa motorrik aurkitu",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "%s elkarbanatzeak huts egin du, baimenak %sri emandakoak baino gehiago direlako",
+ "Sharing %s failed, because resharing is not allowed" : "%s elkarbanatzeak huts egin du, ber-elkarbanatzea baimenduta ez dagoelako",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "%s elkarbanatzeak huts egin du, %sren elkarbanaketa motorrak bere iturria aurkitu ezin duelako",
+ "Sharing %s failed, because the file could not be found in the file cache" : "%s elkarbanatzeak huts egin du, fitxategia katxean aurkitu ez delako",
+ "%s shared »%s« with you" : "%s-ek »%s« zurekin partekatu du",
+ "Could not find category \"%s\"" : "Ezin da \"%s\" kategoria aurkitu",
+ "Sunday" : "Igandea",
+ "Monday" : "Astelehena",
+ "Tuesday" : "Asteartea",
+ "Wednesday" : "Asteazkena",
+ "Thursday" : "Osteguna",
+ "Friday" : "Ostirala",
+ "Saturday" : "Larunbata",
+ "Sun." : "Ig.",
+ "Mon." : "Al.",
+ "Tue." : "Ar.",
+ "Wed." : "Az.",
+ "Thu." : "Og.",
+ "Fri." : "Ol.",
+ "Sat." : "Lr.",
+ "Su" : "Ig",
+ "Mo" : "Al",
+ "Tu" : "Ar",
+ "We" : "Az",
+ "Th" : "Og",
+ "Fr" : "Ol",
+ "Sa" : "Lr",
+ "January" : "Urtarrila",
+ "February" : "Otsaila",
+ "March" : "Martxoa",
+ "April" : "Apirila",
+ "May" : "Maiatza",
+ "June" : "Ekaina",
+ "July" : "Uztaila",
+ "August" : "Abuztua",
+ "September" : "Iraila",
+ "October" : "Urria",
+ "November" : "Azaroa",
+ "December" : "Abendua",
+ "Jan." : "Urt.",
+ "Feb." : "Ots.",
+ "Mar." : "Mar.",
+ "Apr." : "Api.",
+ "May." : "Mai.",
+ "Jun." : "Eka.",
+ "Jul." : "Uzt.",
+ "Aug." : "Abu.",
+ "Sep." : "Ira.",
+ "Oct." : "Urr.",
+ "Nov." : "Aza.",
+ "Dec." : "Abe.",
+ "A valid username must be provided" : "Baliozko erabiltzaile izena eman behar da",
+ "A valid password must be provided" : "Baliozko pasahitza eman behar da",
+ "The username is already being used" : "Erabiltzaile izena dagoeneko erabiltzen ari da",
+ "User disabled" : "Erabiltzaile desgaituta",
+ "Login canceled by app" : "Aplikazioa saioa bertan behera utzi du",
+ "Application is not enabled" : "Aplikazioa ez dago gaituta",
+ "Authentication error" : "Autentifikazio errorea",
+ "Token expired. Please reload page." : "Tokena iraungitu da. Mesedez birkargatu orria.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Ez dago datubaseen (sqlite, mysql edo postgresql) driverrik instalatuta.",
+ "Cannot write into \"config\" directory" : "Ezin da idatzi \"config\" karpetan",
+ "Cannot write into \"apps\" directory" : "Ezin da idatzi \"apps\" karpetan",
+ "Setting locale to %s failed" : "Lokala %sra ezartzeak huts egin du",
+ "Please install one of these locales on your system and restart your webserver." : "Instalatu hauetako lokal bat zure sisteman eta berrabiarazi zure web zerbitzaria.",
+ "Please ask your server administrator to install the module." : "Mesedez eskatu zure zerbitzariaren kudeatzaileari modulua instala dezan.",
+ "PHP module %s not installed." : "PHPren %s modulua ez dago instalaturik.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Hau ziur aski cache/accelerator batek eragin du, hala nola Zend OPcache edo eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "PHP moduluak instalatu dira, baina oraindik faltan bezala markatuta daude?",
+ "Please ask your server administrator to restart the web server." : "Mesedez eskatu zerbitzariaren kudeatzaileari web zerbitzaria berrabiarazteko.",
+ "PostgreSQL >= 9 required" : "PostgreSQL >= 9 behar da",
+ "Please upgrade your database version" : "Mesedez eguneratu zure datu basearen bertsioa",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Mesedez aldatu baimenak 0770ra beste erabiltzaileek karpetan sartu ezin izateko.",
+ "Could not obtain lock type %d on \"%s\"." : "Ezin da lortu sarraia mota %d \"%s\"-an.",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Aholkuak eta trikimailuak"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/eu.json b/lib/l10n/eu.json
new file mode 100644
index 00000000000..685f7469c59
--- /dev/null
+++ b/lib/l10n/eu.json
@@ -0,0 +1,152 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Ezin da idatzi \"config\" karpetan!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Hau normalean konpondu daitekesweb zerbitzarira config karpetan idazteko baimenak emanez",
+ "See %s" : "Ikusi %s",
+ "Sample configuration detected" : "Adibide-ezarpena detektatua",
+ "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" : "Detektatu da adibide-ezarpena kopiatu dela. Honek zure instalazioa apur dezake eta ez da onartzen. Irakurri dokumentazioa config.php fitxategia aldatu aurretik.",
+ "%1$s and %2$s" : "%1$s eta %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s eta %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s eta %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s eta %5$s",
+ "PHP %s or higher is required." : "PHP %s edo berriagoa behar da.",
+ "PHP with a version lower than %s is required." : "PHPren bertsioa %s baino txikiagoa izan behar da.",
+ "Following databases are supported: %s" : "Hurrengo datubaseak onartzen dira: %s",
+ "The command line tool %s could not be found" : "Komando lerroko %s tresna ezin da aurkitu",
+ "The library %s is not available." : "%s liburutegia ez dago eskuragarri.",
+ "Library %s with a version higher than %s is required - available version %s." : "%s liburutegiak %s baino bertsio handiagoa izan behar du - dagoen bertsioa %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "%s liburutegiak %s baino bertsio txikiagoa izan behar du - dagoen bertsioa %s.",
+ "Following platforms are supported: %s" : "Hurrengo plataformak onartzen dira: %s",
+ "Unknown filetype" : "Fitxategi mota ezezaguna",
+ "Invalid image" : "Baliogabeko irudia",
+ "Avatar image is not square" : "Abatarreko irudia ez da karratua",
+ "today" : "gaur",
+ "yesterday" : "atzo",
+ "_%n day ago_::_%n days ago_" : ["orain dela egun %n","orain dela %n egun"],
+ "last month" : "joan den hilabetean",
+ "_%n month ago_::_%n months ago_" : ["orain dela hilabete %n","orain dela %n hilabete"],
+ "last year" : "joan den urtean",
+ "_%n year ago_::_%n years ago_" : ["orain dela urte %n","orain dela %n urte"],
+ "_%n hour ago_::_%n hours ago_" : ["orain dela ordu %n","orain dela %n ordu"],
+ "_%n minute ago_::_%n minutes ago_" : ["orain dela minutu %n","orain dela %n minutu"],
+ "seconds ago" : "duela segundu batzuk",
+ "File name is a reserved word" : "Fitxategi izena hitz erreserbatua da",
+ "File name contains at least one invalid character" : "Fitxategi izenak behintzat baliogabeko karaktere bat du",
+ "File name is too long" : "Fitxategi-izena luzeegia da",
+ "Dot files are not allowed" : "Dot fitxategiak ez dira onartzen",
+ "Empty filename is not allowed" : "Fitxategiaren izena izin da hutsa izan",
+ "__language_name__" : "Euskara",
+ "Help" : "Laguntza",
+ "Apps" : "Aplikazioak",
+ "Users" : "Erabiltzaileak",
+ "Unknown user" : "Erabiltzaile ezezaguna",
+ "Sharing" : "Partekatze",
+ "Encryption" : "Enkriptazio",
+ "Additional settings" : "Ezarpen gehiago",
+ "%s enter the database username and name." : "%s sartu datu-basearen erabiltzaile-izena eta izena.",
+ "%s enter the database username." : "%s sartu datu basearen erabiltzaile izena.",
+ "%s enter the database name." : "%s sartu datu basearen izena.",
+ "%s you may not use dots in the database name" : "%s ezin duzu punturik erabili datu basearen izenean.",
+ "Oracle connection could not be established" : "Ezin da Oracle konexioa sortu",
+ "Oracle username and/or password not valid" : "Oracle erabiltzaile edota pasahitza ez dira egokiak.",
+ "PostgreSQL username and/or password not valid" : "PostgreSQL erabiltzaile edota pasahitza ez dira egokiak.",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X-ek ez du sostengurik eta %s gaizki ibili daiteke plataforma honetan. Erabiltzekotan, zure ardurapean.",
+ "For the best results, please consider using a GNU/Linux server instead." : "Emaitza hobeak izateko, mesedez gogoan hartu GNU/Linux zerbitzari bat erabiltzea.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Mesedez ezabatu open_basedir ezarpena zure php.ini-tik edo aldatu 64-biteko PHPra.",
+ "Set an admin username." : "Ezarri administraziorako erabiltzaile izena.",
+ "Set an admin password." : "Ezarri administraziorako pasahitza.",
+ "Can't create or write into the data directory %s" : "Ezin da %s datu karpeta sortu edo bertan idatzi ",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "%s partekatzeak huts egin du, motorrak %i motako partekatzeak baimentzen ez dituelako",
+ "Sharing %s failed, because the file does not exist" : "%s elkarbanatzeak huts egin du, fitxategia ez delako existitzen",
+ "You are not allowed to share %s" : "Ez zadue %s elkarbanatzeko baimendua",
+ "Sharing %s failed, because the user %s does not exist" : "%s elkarbanatzeak huts egin du, %s erabiltzailea existitzen ez delako",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "%s elkarbanatzeak huts egin du, %s erabiltzailea ez delako %s partaide den talderen bateko partaidea",
+ "Sharing %s failed, because this item is already shared with %s" : "%s elkarbanatzeak huts egin du, dagoeneko %s erabiltzailearekin elkarbanatuta dagoelako",
+ "Sharing %s failed, because the group %s does not exist" : "%s elkarbanatzeak huts egin du, %s taldea ez delako existitzen",
+ "Sharing %s failed, because %s is not a member of the group %s" : "%s elkarbanatzeak huts egin du, %s ez delako %s taldearen partaidea",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Lotura publiko bat sortzeko pasahitza idatzi behar duzu, bakarrik babestutako loturak baimenduta daude",
+ "Sharing %s failed, because sharing with links is not allowed" : "%s elkarbanatzeak huts egin du, lotura bidezko elkarbanatzea baimendua ez dagoelako",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "%s partekatzeak huts egin du, ezin da %s aurkitu, agian zerbitzaria orain ez dago eskuragarri.",
+ "Share type %s is not valid for %s" : "%s elkarbanaketa mota ez da %srentzako egokia",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Ezin izan da jarri iraungitze data. Konpartitzea ezin da iraungi konpartitu eta %s ondoren.",
+ "Cannot set expiration date. Expiration date is in the past" : "Ezin da jarri iraungitze data. Iraungitze data iragan da.",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "%s elkarbanaketa motorra OCP\\Share_Backend interfazea inplementatu behar du ",
+ "Sharing backend %s not found" : "Ez da %s elkarbanaketa motorra aurkitu",
+ "Sharing backend for %s not found" : "Ez da %srako elkarbanaketa motorrik aurkitu",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "%s elkarbanatzeak huts egin du, baimenak %sri emandakoak baino gehiago direlako",
+ "Sharing %s failed, because resharing is not allowed" : "%s elkarbanatzeak huts egin du, ber-elkarbanatzea baimenduta ez dagoelako",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "%s elkarbanatzeak huts egin du, %sren elkarbanaketa motorrak bere iturria aurkitu ezin duelako",
+ "Sharing %s failed, because the file could not be found in the file cache" : "%s elkarbanatzeak huts egin du, fitxategia katxean aurkitu ez delako",
+ "%s shared »%s« with you" : "%s-ek »%s« zurekin partekatu du",
+ "Could not find category \"%s\"" : "Ezin da \"%s\" kategoria aurkitu",
+ "Sunday" : "Igandea",
+ "Monday" : "Astelehena",
+ "Tuesday" : "Asteartea",
+ "Wednesday" : "Asteazkena",
+ "Thursday" : "Osteguna",
+ "Friday" : "Ostirala",
+ "Saturday" : "Larunbata",
+ "Sun." : "Ig.",
+ "Mon." : "Al.",
+ "Tue." : "Ar.",
+ "Wed." : "Az.",
+ "Thu." : "Og.",
+ "Fri." : "Ol.",
+ "Sat." : "Lr.",
+ "Su" : "Ig",
+ "Mo" : "Al",
+ "Tu" : "Ar",
+ "We" : "Az",
+ "Th" : "Og",
+ "Fr" : "Ol",
+ "Sa" : "Lr",
+ "January" : "Urtarrila",
+ "February" : "Otsaila",
+ "March" : "Martxoa",
+ "April" : "Apirila",
+ "May" : "Maiatza",
+ "June" : "Ekaina",
+ "July" : "Uztaila",
+ "August" : "Abuztua",
+ "September" : "Iraila",
+ "October" : "Urria",
+ "November" : "Azaroa",
+ "December" : "Abendua",
+ "Jan." : "Urt.",
+ "Feb." : "Ots.",
+ "Mar." : "Mar.",
+ "Apr." : "Api.",
+ "May." : "Mai.",
+ "Jun." : "Eka.",
+ "Jul." : "Uzt.",
+ "Aug." : "Abu.",
+ "Sep." : "Ira.",
+ "Oct." : "Urr.",
+ "Nov." : "Aza.",
+ "Dec." : "Abe.",
+ "A valid username must be provided" : "Baliozko erabiltzaile izena eman behar da",
+ "A valid password must be provided" : "Baliozko pasahitza eman behar da",
+ "The username is already being used" : "Erabiltzaile izena dagoeneko erabiltzen ari da",
+ "User disabled" : "Erabiltzaile desgaituta",
+ "Login canceled by app" : "Aplikazioa saioa bertan behera utzi du",
+ "Application is not enabled" : "Aplikazioa ez dago gaituta",
+ "Authentication error" : "Autentifikazio errorea",
+ "Token expired. Please reload page." : "Tokena iraungitu da. Mesedez birkargatu orria.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Ez dago datubaseen (sqlite, mysql edo postgresql) driverrik instalatuta.",
+ "Cannot write into \"config\" directory" : "Ezin da idatzi \"config\" karpetan",
+ "Cannot write into \"apps\" directory" : "Ezin da idatzi \"apps\" karpetan",
+ "Setting locale to %s failed" : "Lokala %sra ezartzeak huts egin du",
+ "Please install one of these locales on your system and restart your webserver." : "Instalatu hauetako lokal bat zure sisteman eta berrabiarazi zure web zerbitzaria.",
+ "Please ask your server administrator to install the module." : "Mesedez eskatu zure zerbitzariaren kudeatzaileari modulua instala dezan.",
+ "PHP module %s not installed." : "PHPren %s modulua ez dago instalaturik.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Hau ziur aski cache/accelerator batek eragin du, hala nola Zend OPcache edo eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "PHP moduluak instalatu dira, baina oraindik faltan bezala markatuta daude?",
+ "Please ask your server administrator to restart the web server." : "Mesedez eskatu zerbitzariaren kudeatzaileari web zerbitzaria berrabiarazteko.",
+ "PostgreSQL >= 9 required" : "PostgreSQL >= 9 behar da",
+ "Please upgrade your database version" : "Mesedez eguneratu zure datu basearen bertsioa",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Mesedez aldatu baimenak 0770ra beste erabiltzaileek karpetan sartu ezin izateko.",
+ "Could not obtain lock type %d on \"%s\"." : "Ezin da lortu sarraia mota %d \"%s\"-an.",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Aholkuak eta trikimailuak"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/fa.js b/lib/l10n/fa.js
new file mode 100644
index 00000000000..a161e22a0b0
--- /dev/null
+++ b/lib/l10n/fa.js
@@ -0,0 +1,58 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "نمیتوانید داخل دایرکتوری \"config\" تغییراتی ایجاد کنید",
+ "See %s" : "مشاهده %s",
+ "Sample configuration detected" : "فایل پیکربندی نمونه پیدا شد",
+ "PHP %s or higher is required." : "PHP نسخه‌ی %s یا بالاتر نیاز است.",
+ "Following databases are supported: %s" : "پایگاه‌داده‌ های ذکر شده مورد نیاز است: %s",
+ "The command line tool %s could not be found" : "ابزار کامندلاین %s پیدا نشد",
+ "The library %s is not available." : "کتابخانه‌ی %s در دسترس نیست.",
+ "Library %s with a version higher than %s is required - available version %s." : "کتابخانه %s با نسخه‎‌ی بالاتر از %s نیاز است - نسخه‎ی موجود %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "کتابخانه %s با نسخه‎‌ی پایین‌تر از %s نیاز است - نسخه‎ی موجود %s.",
+ "Unknown filetype" : "نوع فایل ناشناخته",
+ "Invalid image" : "عکس نامعتبر",
+ "today" : "امروز",
+ "yesterday" : "دیروز",
+ "_%n day ago_::_%n days ago_" : ["%n روز پیش","%n روز پیش"],
+ "last month" : "ماه قبل",
+ "_%n month ago_::_%n months ago_" : ["%n ماه قبل","%n ماه قبل"],
+ "last year" : "سال قبل",
+ "_%n year ago_::_%n years ago_" : ["%n سال پیش","%n سال پیش"],
+ "_%n hour ago_::_%n hours ago_" : ["%n ساعت قبل","%n ساعت قبل"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n دقیقه قبل","%n دقیقه قبل"],
+ "seconds ago" : "ثانیه‌ها پیش",
+ "File name is a reserved word" : "این نام فایل جزو کلمات رزرو می‌باشد",
+ "File name contains at least one invalid character" : "نام فایل دارای حداقل یک کاراکتر نامعتبر است",
+ "File name is too long" : "نام فایل خیلی بزرگ است",
+ "Empty filename is not allowed" : "نام فایل نمی‌تواند خالی باشد",
+ "__language_name__" : "فارسى",
+ "Apps" : " برنامه ها",
+ "Users" : "کاربران",
+ "Unknown user" : "کاربر نامعلوم",
+ "%s enter the database username." : "%s نام کاربری پایگاه داده را وارد نمایید.",
+ "%s enter the database name." : "%s نام پایگاه داده را وارد نمایید.",
+ "%s you may not use dots in the database name" : "%s شما نباید از نقطه در نام پایگاه داده استفاده نمایید.",
+ "Oracle connection could not be established" : "ارتباط اراکل نمیتواند برقرار باشد.",
+ "Oracle username and/or password not valid" : "نام کاربری و / یا رمزعبور اراکل معتبر نیست.",
+ "PostgreSQL username and/or password not valid" : "PostgreSQL نام کاربری و / یا رمزعبور معتبر نیست.",
+ "Set an admin username." : "یک نام کاربری برای مدیر تنظیم نمایید.",
+ "Set an admin password." : "یک رمزعبور برای مدیر تنظیم نمایید.",
+ "%s shared »%s« with you" : "%s به اشتراک گذاشته شده است »%s« توسط شما",
+ "Could not find category \"%s\"" : "دسته بندی %s یافت نشد",
+ "A valid username must be provided" : "نام کاربری صحیح باید وارد شود",
+ "A valid password must be provided" : "رمز عبور صحیح باید وارد شود",
+ "The username is already being used" : "نام‌کاربری قبلا استفاده شده است",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "امکان نصب برنامه \"%s\" با توجه به برآورده نکردن نیازمندی زیر وجود ندارد: %s",
+ "File is currently busy, please try again later" : "فایل در حال حاضر مشغول است، لطفا مجددا تلاش کنید",
+ "Can't read file" : "امکان خواندن فایل وجود ندارد",
+ "Application is not enabled" : "برنامه فعال نشده است",
+ "Authentication error" : "خطا در اعتبار سنجی",
+ "Token expired. Please reload page." : "Token منقضی شده است. لطفا دوباره صفحه را بارگذاری نمایید.",
+ "Cannot write into \"config\" directory" : "امکان نوشتن درون شاخه‌ی \"config\" وجود ندارد",
+ "Please ask your server administrator to install the module." : "لطفا از مدیر سیستم بخواهید تا ماژول را نصب کند.",
+ "PHP module %s not installed." : "ماژول PHP %s نصب نشده است.",
+ "PostgreSQL >= 9 required" : "PostgreSQL >= 9 نیاز است",
+ "Please upgrade your database version" : "لطفا نسخه‌ی پایگاه‌داده‌ی خود را بروز کنید"
+},
+"nplurals=2; plural=(n > 1);");
diff --git a/lib/l10n/fa.json b/lib/l10n/fa.json
new file mode 100644
index 00000000000..1981773ea9d
--- /dev/null
+++ b/lib/l10n/fa.json
@@ -0,0 +1,56 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "نمیتوانید داخل دایرکتوری \"config\" تغییراتی ایجاد کنید",
+ "See %s" : "مشاهده %s",
+ "Sample configuration detected" : "فایل پیکربندی نمونه پیدا شد",
+ "PHP %s or higher is required." : "PHP نسخه‌ی %s یا بالاتر نیاز است.",
+ "Following databases are supported: %s" : "پایگاه‌داده‌ های ذکر شده مورد نیاز است: %s",
+ "The command line tool %s could not be found" : "ابزار کامندلاین %s پیدا نشد",
+ "The library %s is not available." : "کتابخانه‌ی %s در دسترس نیست.",
+ "Library %s with a version higher than %s is required - available version %s." : "کتابخانه %s با نسخه‎‌ی بالاتر از %s نیاز است - نسخه‎ی موجود %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "کتابخانه %s با نسخه‎‌ی پایین‌تر از %s نیاز است - نسخه‎ی موجود %s.",
+ "Unknown filetype" : "نوع فایل ناشناخته",
+ "Invalid image" : "عکس نامعتبر",
+ "today" : "امروز",
+ "yesterday" : "دیروز",
+ "_%n day ago_::_%n days ago_" : ["%n روز پیش","%n روز پیش"],
+ "last month" : "ماه قبل",
+ "_%n month ago_::_%n months ago_" : ["%n ماه قبل","%n ماه قبل"],
+ "last year" : "سال قبل",
+ "_%n year ago_::_%n years ago_" : ["%n سال پیش","%n سال پیش"],
+ "_%n hour ago_::_%n hours ago_" : ["%n ساعت قبل","%n ساعت قبل"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n دقیقه قبل","%n دقیقه قبل"],
+ "seconds ago" : "ثانیه‌ها پیش",
+ "File name is a reserved word" : "این نام فایل جزو کلمات رزرو می‌باشد",
+ "File name contains at least one invalid character" : "نام فایل دارای حداقل یک کاراکتر نامعتبر است",
+ "File name is too long" : "نام فایل خیلی بزرگ است",
+ "Empty filename is not allowed" : "نام فایل نمی‌تواند خالی باشد",
+ "__language_name__" : "فارسى",
+ "Apps" : " برنامه ها",
+ "Users" : "کاربران",
+ "Unknown user" : "کاربر نامعلوم",
+ "%s enter the database username." : "%s نام کاربری پایگاه داده را وارد نمایید.",
+ "%s enter the database name." : "%s نام پایگاه داده را وارد نمایید.",
+ "%s you may not use dots in the database name" : "%s شما نباید از نقطه در نام پایگاه داده استفاده نمایید.",
+ "Oracle connection could not be established" : "ارتباط اراکل نمیتواند برقرار باشد.",
+ "Oracle username and/or password not valid" : "نام کاربری و / یا رمزعبور اراکل معتبر نیست.",
+ "PostgreSQL username and/or password not valid" : "PostgreSQL نام کاربری و / یا رمزعبور معتبر نیست.",
+ "Set an admin username." : "یک نام کاربری برای مدیر تنظیم نمایید.",
+ "Set an admin password." : "یک رمزعبور برای مدیر تنظیم نمایید.",
+ "%s shared »%s« with you" : "%s به اشتراک گذاشته شده است »%s« توسط شما",
+ "Could not find category \"%s\"" : "دسته بندی %s یافت نشد",
+ "A valid username must be provided" : "نام کاربری صحیح باید وارد شود",
+ "A valid password must be provided" : "رمز عبور صحیح باید وارد شود",
+ "The username is already being used" : "نام‌کاربری قبلا استفاده شده است",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "امکان نصب برنامه \"%s\" با توجه به برآورده نکردن نیازمندی زیر وجود ندارد: %s",
+ "File is currently busy, please try again later" : "فایل در حال حاضر مشغول است، لطفا مجددا تلاش کنید",
+ "Can't read file" : "امکان خواندن فایل وجود ندارد",
+ "Application is not enabled" : "برنامه فعال نشده است",
+ "Authentication error" : "خطا در اعتبار سنجی",
+ "Token expired. Please reload page." : "Token منقضی شده است. لطفا دوباره صفحه را بارگذاری نمایید.",
+ "Cannot write into \"config\" directory" : "امکان نوشتن درون شاخه‌ی \"config\" وجود ندارد",
+ "Please ask your server administrator to install the module." : "لطفا از مدیر سیستم بخواهید تا ماژول را نصب کند.",
+ "PHP module %s not installed." : "ماژول PHP %s نصب نشده است.",
+ "PostgreSQL >= 9 required" : "PostgreSQL >= 9 نیاز است",
+ "Please upgrade your database version" : "لطفا نسخه‌ی پایگاه‌داده‌ی خود را بروز کنید"
+},"pluralForm" :"nplurals=2; plural=(n > 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/fi.js b/lib/l10n/fi.js
index 72810d345f1..0a5aeb15b95 100644
--- a/lib/l10n/fi.js
+++ b/lib/l10n/fi.js
@@ -22,18 +22,28 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Seuraavat alustat ovat tuettuja: %s",
"Server version %s or higher is required." : "Palvelinversio %s tai sitä uudempi vaaditaan.",
"Server version %s or lower is required." : "Palvelinversio %s tai alhaisempi vaaditaan.",
+ "Logged in user must be an admin" : "Sisäänkirjautuneen käyttäjän tulee olla ylläpitäjä",
"Unknown filetype" : "Tuntematon tiedostotyyppi",
"Invalid image" : "Virheellinen kuva",
"Avatar image is not square" : "Avatar-kuva ei ole neliö",
"today" : "tänään",
+ "tomorrow" : "huomenna",
"yesterday" : "eilen",
+ "_in %n day_::_in %n days_" : ["%n päivän päästä","%n päivän päästä"],
"_%n day ago_::_%n days ago_" : ["%n päivä sitten","%n päivää sitten"],
+ "next month" : "ensi kuussa",
"last month" : "viime kuussa",
+ "_in %n month_::_in %n months_" : ["%n kuukauden päästä","%n kuukauden päästä"],
"_%n month ago_::_%n months ago_" : ["%n kuukausi sitten","%n kuukautta sitten"],
+ "next year" : "ensi vuonna",
"last year" : "viime vuonna",
+ "_in %n year_::_in %n years_" : ["%n vuoden päästä","%n vuoden päästä"],
"_%n year ago_::_%n years ago_" : ["%n vuosi sitten","%n vuotta sitten"],
+ "_in %n hour_::_in %n hours_" : ["%n tunnin päästä","%n tunnin päästä"],
"_%n hour ago_::_%n hours ago_" : ["%n tunti sitten","%n tuntia sitten"],
+ "_in %n minute_::_in %n minutes_" : ["%n minuutin päästä","%n minuutin päästä"],
"_%n minute ago_::_%n minutes ago_" : ["%n minuutti sitten","%n minuuttia sitten"],
+ "in a few seconds" : "muutaman sekunnin päästä",
"seconds ago" : "sekunteja sitten",
"File name is a reserved word" : "Tiedoston nimi on varattu sana",
"File name contains at least one invalid character" : "Tiedoston nimi sisältää ainakin yhden virheellisen merkin",
@@ -42,6 +52,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Tiedostonimi ei voi olla tyhjä",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Sovellusta \"%s\" ei voi asentaa, koska appinfo-tiedostoa ei voi loi lukea.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Sovellusta \"%s\" ei voi asentaa, koska se ei ole yhteensopiva tämän palvelinversion kanssa.",
+ "__language_name__" : "suomi",
"This is an automatically sent email, please do not reply." : "Tämä on automaattisesti lähetetty viesti. Älä vastaa tähän viestiin.",
"Help" : "Ohje",
"Apps" : "Sovellukset",
@@ -49,18 +60,18 @@ OC.L10N.register(
"Log out" : "Kirjaudu ulos",
"Users" : "Käyttäjät",
"Unknown user" : "Tuntematon käyttäjä",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Luo",
+ "Change" : "Muuta",
+ "Delete" : "Poista",
+ "Share" : "Jaa",
"Basic settings" : "Perusasetukset",
"Sharing" : "Jakaminen",
"Security" : "Turvallisuus",
"Encryption" : "Salaus",
"Additional settings" : "Lisäasetukset",
- "Tips & tricks" : "Vinkkejä",
"Personal info" : "Henkilökohtaiset tiedot",
- "Sync clients" : "Synkronointisovellukset",
+ "Mobile & desktop" : "Mobiili ja työpöytä",
"Unlimited" : "Rajoittamaton",
- "__language_name__" : "suomi",
"Verifying" : "Vahvistetaan",
"Verifying …" : "Vahvistetaan…",
"Verify" : "Vahvista",
@@ -194,6 +205,13 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Tallennustilan puutteellinen määritys. %s",
"Storage connection error. %s" : "Tallennustilan yhteysvirhe. %s",
"Storage is temporarily not available" : "Tallennustila on tilapäisesti pois käytöstä",
- "Storage connection timeout. %s" : "Tallennustilan yhteyden aikakatkaisu. %s"
+ "Storage connection timeout. %s" : "Tallennustilan yhteyden aikakatkaisu. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Vinkkejä",
+ "DB Error: \"%s\"" : "Tietokantavirhe: \"%s\"",
+ "Cannot increase permissions of %s" : "Kohteen %s käyttöoikeuksien lisääminen ei onnistu",
+ "App '%s' could not be installed!" : "Sovellusta '%s' ei voitu asentaa!",
+ "Sync clients" : "Synkronointisovellukset"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/fi.json b/lib/l10n/fi.json
index e79bbdf77da..e48bedcefd5 100644
--- a/lib/l10n/fi.json
+++ b/lib/l10n/fi.json
@@ -20,18 +20,28 @@
"Following platforms are supported: %s" : "Seuraavat alustat ovat tuettuja: %s",
"Server version %s or higher is required." : "Palvelinversio %s tai sitä uudempi vaaditaan.",
"Server version %s or lower is required." : "Palvelinversio %s tai alhaisempi vaaditaan.",
+ "Logged in user must be an admin" : "Sisäänkirjautuneen käyttäjän tulee olla ylläpitäjä",
"Unknown filetype" : "Tuntematon tiedostotyyppi",
"Invalid image" : "Virheellinen kuva",
"Avatar image is not square" : "Avatar-kuva ei ole neliö",
"today" : "tänään",
+ "tomorrow" : "huomenna",
"yesterday" : "eilen",
+ "_in %n day_::_in %n days_" : ["%n päivän päästä","%n päivän päästä"],
"_%n day ago_::_%n days ago_" : ["%n päivä sitten","%n päivää sitten"],
+ "next month" : "ensi kuussa",
"last month" : "viime kuussa",
+ "_in %n month_::_in %n months_" : ["%n kuukauden päästä","%n kuukauden päästä"],
"_%n month ago_::_%n months ago_" : ["%n kuukausi sitten","%n kuukautta sitten"],
+ "next year" : "ensi vuonna",
"last year" : "viime vuonna",
+ "_in %n year_::_in %n years_" : ["%n vuoden päästä","%n vuoden päästä"],
"_%n year ago_::_%n years ago_" : ["%n vuosi sitten","%n vuotta sitten"],
+ "_in %n hour_::_in %n hours_" : ["%n tunnin päästä","%n tunnin päästä"],
"_%n hour ago_::_%n hours ago_" : ["%n tunti sitten","%n tuntia sitten"],
+ "_in %n minute_::_in %n minutes_" : ["%n minuutin päästä","%n minuutin päästä"],
"_%n minute ago_::_%n minutes ago_" : ["%n minuutti sitten","%n minuuttia sitten"],
+ "in a few seconds" : "muutaman sekunnin päästä",
"seconds ago" : "sekunteja sitten",
"File name is a reserved word" : "Tiedoston nimi on varattu sana",
"File name contains at least one invalid character" : "Tiedoston nimi sisältää ainakin yhden virheellisen merkin",
@@ -40,6 +50,7 @@
"Empty filename is not allowed" : "Tiedostonimi ei voi olla tyhjä",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Sovellusta \"%s\" ei voi asentaa, koska appinfo-tiedostoa ei voi loi lukea.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Sovellusta \"%s\" ei voi asentaa, koska se ei ole yhteensopiva tämän palvelinversion kanssa.",
+ "__language_name__" : "suomi",
"This is an automatically sent email, please do not reply." : "Tämä on automaattisesti lähetetty viesti. Älä vastaa tähän viestiin.",
"Help" : "Ohje",
"Apps" : "Sovellukset",
@@ -47,18 +58,18 @@
"Log out" : "Kirjaudu ulos",
"Users" : "Käyttäjät",
"Unknown user" : "Tuntematon käyttäjä",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Luo",
+ "Change" : "Muuta",
+ "Delete" : "Poista",
+ "Share" : "Jaa",
"Basic settings" : "Perusasetukset",
"Sharing" : "Jakaminen",
"Security" : "Turvallisuus",
"Encryption" : "Salaus",
"Additional settings" : "Lisäasetukset",
- "Tips & tricks" : "Vinkkejä",
"Personal info" : "Henkilökohtaiset tiedot",
- "Sync clients" : "Synkronointisovellukset",
+ "Mobile & desktop" : "Mobiili ja työpöytä",
"Unlimited" : "Rajoittamaton",
- "__language_name__" : "suomi",
"Verifying" : "Vahvistetaan",
"Verifying …" : "Vahvistetaan…",
"Verify" : "Vahvista",
@@ -192,6 +203,13 @@
"Storage incomplete configuration. %s" : "Tallennustilan puutteellinen määritys. %s",
"Storage connection error. %s" : "Tallennustilan yhteysvirhe. %s",
"Storage is temporarily not available" : "Tallennustila on tilapäisesti pois käytöstä",
- "Storage connection timeout. %s" : "Tallennustilan yhteyden aikakatkaisu. %s"
+ "Storage connection timeout. %s" : "Tallennustilan yhteyden aikakatkaisu. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Vinkkejä",
+ "DB Error: \"%s\"" : "Tietokantavirhe: \"%s\"",
+ "Cannot increase permissions of %s" : "Kohteen %s käyttöoikeuksien lisääminen ei onnistu",
+ "App '%s' could not be installed!" : "Sovellusta '%s' ei voitu asentaa!",
+ "Sync clients" : "Synkronointisovellukset"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/fr.js b/lib/l10n/fr.js
index 61d35224fd0..eaeb1f50b1e 100644
--- a/lib/l10n/fr.js
+++ b/lib/l10n/fr.js
@@ -4,7 +4,9 @@ OC.L10N.register(
"Cannot write into \"config\" directory!" : "Impossible d’écrire dans le répertoire « config » !",
"This can usually be fixed by giving the webserver write access to the config directory" : "Ce problème est généralement résolu en donnant au serveur web un accès en écriture au répertoire \"config\"",
"See %s" : "Voir %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Ou, si vous préférez conserver le fichier config.php en lecture seule, définissez l'option \"config_is_read_only\" sur true.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ce problème est généralement résolu en donnant au serveur web un accès en écriture au répertoire \"config\". Voir %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Ou, si vous préférez conserver le fichier config.php en lecture seule, définissez l'option \"config_is_read_only\" sur true. Voir %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Les fichiers de l'application %$1s n'ont pas été remplacés correctement. Veuillez vérifier que c'est une version compatible avec le serveur.",
"Sample configuration detected" : "Configuration d'exemple détectée",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Il a été détecté que la configuration donnée à titre d'exemple a été copiée. Cela peut rendre votre installation inopérante et n'est pas pris en charge. Veuillez lire la documentation avant d'effectuer des modifications dans config.php",
@@ -27,6 +29,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Les plateformes suivantes sont prises en charge : %s",
"Server version %s or higher is required." : "Un serveur de version %s ou supérieure est requis.",
"Server version %s or lower is required." : "Un serveur de version %s ou inférieure est requis.",
+ "Logged in user must be an admin" : "L'utilisateur connecté doit être un administrateur",
"Unknown filetype" : "Type de fichier inconnu",
"Invalid image" : "Image non valable",
"Avatar image is not square" : "L'image d'avatar n'est pas carré",
@@ -57,6 +60,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Le nom de fichier ne peut pas être vide",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "L'application \"%s\" ne peut pas être installée car le fichier appinfo ne peut pas être lu.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "L'application \"%s\" ne peut être installée car elle n'est pas compatible avec cette version du serveur",
+ "__language_name__" : "Français",
"This is an automatically sent email, please do not reply." : "Ceci est un e-mail envoyé automatiquement, veuillez ne pas y répondre.",
"Help" : "Aide",
"Apps" : "Applications",
@@ -64,18 +68,20 @@ OC.L10N.register(
"Log out" : "Se déconnecter",
"Users" : "Utilisateurs",
"Unknown user" : "Utilisateur inconnu",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Créer",
+ "Change" : "Modifier",
+ "Delete" : "Supprimer",
+ "Share" : "Partager",
+ "Overview" : "Vue d'ensemble",
"Basic settings" : "Paramètres de base",
"Sharing" : "Partage",
"Security" : "Sécurité",
"Encryption" : "Chiffrement",
+ "Groupware" : "Travail collaboratif",
"Additional settings" : "Paramètres supplémentaires",
- "Tips & tricks" : "Trucs et astuces",
"Personal info" : "Informations personnelles",
- "Sync clients" : "Clients de synchronisation",
+ "Mobile & desktop" : "Mobile & bureau",
"Unlimited" : "Illimité",
- "__language_name__" : "Français",
"Verifying" : "Vérification en cours",
"Verifying …" : "Vérification en cours...",
"Verify" : "Vérifié",
@@ -222,6 +228,7 @@ OC.L10N.register(
"Check the value of \"datadirectory\" in your configuration" : "Verifiez la valeur de \"datadirectory\" dans votre configuration",
"Your data directory is invalid" : "Votre répertoire n'est pas valide",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assurez-vous que le répertoire de données contient un fichier \".ocdata\" à sa racine.",
+ "Action \"%s\" not supported or implemented." : "Action \"%s\" non supportée ou implémentée.",
"Could not obtain lock type %d on \"%s\"." : "Impossible d'obtenir le verrouillage de type %d sur \"%s\".",
"Storage unauthorized. %s" : "Espace de stockage non autorisé. %s",
"Storage incomplete configuration. %s" : "Configuration de l'espace de stockage incomplète. %s",
@@ -230,6 +237,9 @@ OC.L10N.register(
"Storage connection timeout. %s" : "Le délai d'attente pour la connexion à l'espace de stockage a été dépassé. %s",
"Personal" : "Personnel",
"Admin" : "Administration",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Trucs et astuces",
"DB Error: \"%s\"" : "Erreur de la base de données : \"%s\"",
"Offending command was: \"%s\"" : "La requête en cause est : \"%s\"",
"Offending command was: \"%s\", name: %s, password: %s" : "La requête en cause est : \"%s\", nom : %s, mot de passe : %s",
@@ -241,6 +251,7 @@ OC.L10N.register(
"Files can't be shared with create permissions" : "Les fichiers ne peuvent pas être partagés avec les autorisations de création",
"Cannot set expiration date more than %s days in the future" : "Impossible de définir la date d'expiration à plus de %s jours dans le futur",
"No app name specified" : "Aucun nom d'application spécifié",
- "App '%s' could not be installed!" : "L'application \"%s\" ne peut pas être installée !"
+ "App '%s' could not be installed!" : "L'application \"%s\" ne peut pas être installée !",
+ "Sync clients" : "Clients de synchronisation"
},
"nplurals=2; plural=(n > 1);");
diff --git a/lib/l10n/fr.json b/lib/l10n/fr.json
index 25801b27ac7..50416a619a8 100644
--- a/lib/l10n/fr.json
+++ b/lib/l10n/fr.json
@@ -2,7 +2,9 @@
"Cannot write into \"config\" directory!" : "Impossible d’écrire dans le répertoire « config » !",
"This can usually be fixed by giving the webserver write access to the config directory" : "Ce problème est généralement résolu en donnant au serveur web un accès en écriture au répertoire \"config\"",
"See %s" : "Voir %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Ou, si vous préférez conserver le fichier config.php en lecture seule, définissez l'option \"config_is_read_only\" sur true.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ce problème est généralement résolu en donnant au serveur web un accès en écriture au répertoire \"config\". Voir %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Ou, si vous préférez conserver le fichier config.php en lecture seule, définissez l'option \"config_is_read_only\" sur true. Voir %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Les fichiers de l'application %$1s n'ont pas été remplacés correctement. Veuillez vérifier que c'est une version compatible avec le serveur.",
"Sample configuration detected" : "Configuration d'exemple détectée",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Il a été détecté que la configuration donnée à titre d'exemple a été copiée. Cela peut rendre votre installation inopérante et n'est pas pris en charge. Veuillez lire la documentation avant d'effectuer des modifications dans config.php",
@@ -25,6 +27,7 @@
"Following platforms are supported: %s" : "Les plateformes suivantes sont prises en charge : %s",
"Server version %s or higher is required." : "Un serveur de version %s ou supérieure est requis.",
"Server version %s or lower is required." : "Un serveur de version %s ou inférieure est requis.",
+ "Logged in user must be an admin" : "L'utilisateur connecté doit être un administrateur",
"Unknown filetype" : "Type de fichier inconnu",
"Invalid image" : "Image non valable",
"Avatar image is not square" : "L'image d'avatar n'est pas carré",
@@ -55,6 +58,7 @@
"Empty filename is not allowed" : "Le nom de fichier ne peut pas être vide",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "L'application \"%s\" ne peut pas être installée car le fichier appinfo ne peut pas être lu.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "L'application \"%s\" ne peut être installée car elle n'est pas compatible avec cette version du serveur",
+ "__language_name__" : "Français",
"This is an automatically sent email, please do not reply." : "Ceci est un e-mail envoyé automatiquement, veuillez ne pas y répondre.",
"Help" : "Aide",
"Apps" : "Applications",
@@ -62,18 +66,20 @@
"Log out" : "Se déconnecter",
"Users" : "Utilisateurs",
"Unknown user" : "Utilisateur inconnu",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Créer",
+ "Change" : "Modifier",
+ "Delete" : "Supprimer",
+ "Share" : "Partager",
+ "Overview" : "Vue d'ensemble",
"Basic settings" : "Paramètres de base",
"Sharing" : "Partage",
"Security" : "Sécurité",
"Encryption" : "Chiffrement",
+ "Groupware" : "Travail collaboratif",
"Additional settings" : "Paramètres supplémentaires",
- "Tips & tricks" : "Trucs et astuces",
"Personal info" : "Informations personnelles",
- "Sync clients" : "Clients de synchronisation",
+ "Mobile & desktop" : "Mobile & bureau",
"Unlimited" : "Illimité",
- "__language_name__" : "Français",
"Verifying" : "Vérification en cours",
"Verifying …" : "Vérification en cours...",
"Verify" : "Vérifié",
@@ -220,6 +226,7 @@
"Check the value of \"datadirectory\" in your configuration" : "Verifiez la valeur de \"datadirectory\" dans votre configuration",
"Your data directory is invalid" : "Votre répertoire n'est pas valide",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assurez-vous que le répertoire de données contient un fichier \".ocdata\" à sa racine.",
+ "Action \"%s\" not supported or implemented." : "Action \"%s\" non supportée ou implémentée.",
"Could not obtain lock type %d on \"%s\"." : "Impossible d'obtenir le verrouillage de type %d sur \"%s\".",
"Storage unauthorized. %s" : "Espace de stockage non autorisé. %s",
"Storage incomplete configuration. %s" : "Configuration de l'espace de stockage incomplète. %s",
@@ -228,6 +235,9 @@
"Storage connection timeout. %s" : "Le délai d'attente pour la connexion à l'espace de stockage a été dépassé. %s",
"Personal" : "Personnel",
"Admin" : "Administration",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Trucs et astuces",
"DB Error: \"%s\"" : "Erreur de la base de données : \"%s\"",
"Offending command was: \"%s\"" : "La requête en cause est : \"%s\"",
"Offending command was: \"%s\", name: %s, password: %s" : "La requête en cause est : \"%s\", nom : %s, mot de passe : %s",
@@ -239,6 +249,7 @@
"Files can't be shared with create permissions" : "Les fichiers ne peuvent pas être partagés avec les autorisations de création",
"Cannot set expiration date more than %s days in the future" : "Impossible de définir la date d'expiration à plus de %s jours dans le futur",
"No app name specified" : "Aucun nom d'application spécifié",
- "App '%s' could not be installed!" : "L'application \"%s\" ne peut pas être installée !"
+ "App '%s' could not be installed!" : "L'application \"%s\" ne peut pas être installée !",
+ "Sync clients" : "Clients de synchronisation"
},"pluralForm" :"nplurals=2; plural=(n > 1);"
} \ No newline at end of file
diff --git a/lib/l10n/gl.js b/lib/l10n/gl.js
new file mode 100644
index 00000000000..bf92b4db0f2
--- /dev/null
+++ b/lib/l10n/gl.js
@@ -0,0 +1,7 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Non é posíbel escribir no directorio «config»!",
+ "__language_name__" : "Galego"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/gl.json b/lib/l10n/gl.json
new file mode 100644
index 00000000000..30c4cdd34a7
--- /dev/null
+++ b/lib/l10n/gl.json
@@ -0,0 +1,5 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Non é posíbel escribir no directorio «config»!",
+ "__language_name__" : "Galego"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/he.js b/lib/l10n/he.js
new file mode 100644
index 00000000000..a424d3b6e86
--- /dev/null
+++ b/lib/l10n/he.js
@@ -0,0 +1,254 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "לא ניתן לכתוב לתיקיית „config”!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "בדרך כלל ניתן לפתור את הבעיה על ידי כך שנותנים לתכנית השרת הרשאות כתיבה לתיקיית config",
+ "See %s" : "יש לעיין ב־%s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "או, אם עדיף לך לשמור על config.php לקריאה בלבד, ניתן להגדיר את האפשרות „config_is_read_only” לערך true.",
+ "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "בדרך כלל ניתן לתקן זאת על ידי הענקת גישה לשרת לכתוב לתיקיית ההגדרות. נא לעיין ב־%s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "או, אם עדיף לך לשמור על config.php לקריאה בלבד, ניתן להגדיר את האפשרות „config_is_read_only” לערך true. נא לעיין ב־%s",
+ "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "הקבצים של היישומון %$1s לא הוחלפו כראוי. נא לוודא שגרסה זו תואמת לזו של השרת.",
+ "Sample configuration detected" : "התגלתה דוגמת תצורה",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "התגלה שדוגמת התצורה הועתקה. דבר זה עלול לשבור את ההתקנה ולא נתמך.יש לקרוא את מסמכי התיעוד לפני שמבצעים שינויים ב- config.php",
+ "Education Edition" : "מהדורה חינוכית",
+ "Enterprise bundle" : "מהדורה מסחרית",
+ "Groupware bundle" : "מהדורה קבוצתית",
+ "Social sharing bundle" : "מאגד שיתוף חברתי",
+ "PHP %s or higher is required." : "נדרש PHP בגרסת %s ומעלה.",
+ "PHP with a version lower than %s is required." : "נדרש PHP בגרסה נמוכה מ- %s.",
+ "%sbit or higher PHP required." : "נדרש PHP בגרסת %s ומעלה.",
+ "Following databases are supported: %s" : "מסדי הנתונים הבאים נתמכים: %s",
+ "The command line tool %s could not be found" : "כלי שורת הפקודה %s לא אותר",
+ "The library %s is not available." : "הספריה %s אינה זמינה.",
+ "Library %s with a version higher than %s is required - available version %s." : "ספריה %s בגרסה גבוהה מ- %s נדרשת - גרסה זמינה %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "ספריה %s בגרסה נמוכה מ- %s נדרשת - גרסה זמינה %s.",
+ "Following platforms are supported: %s" : "הפלטפורמות הבאות נתמכות: %s",
+ "Server version %s or higher is required." : "נדרשת גרסה שרת %s ומעלה.",
+ "Server version %s or lower is required." : "נדרשת גרסה שרת %s ומטה.",
+ "Logged in user must be an admin" : "על המשתמש שנכנס להיות מנהל",
+ "Unknown filetype" : "סוג קובץ לא מוכר",
+ "Invalid image" : "תמונה לא חוקית",
+ "Avatar image is not square" : "התמונה המייצגת אינה מרובעת",
+ "today" : "היום",
+ "tomorrow" : "מחר",
+ "yesterday" : "אתמול",
+ "_in %n day_::_in %n days_" : ["בעוד יום","בעוד יומיים","בעוד %n ימים","בעוד %n ימים"],
+ "_%n day ago_::_%n days ago_" : ["לפני %n יום","לפני %n ימים","לפני %n ימים","לפני %n ימים"],
+ "next month" : "בחודש הבא",
+ "last month" : "חודש שעבר",
+ "_in %n month_::_in %n months_" : ["בעוד חודש","בעוד חודשיים","בעוד %n חודשים","בעוד %n חודשים"],
+ "_%n month ago_::_%n months ago_" : ["לפני חודש","לפני חודשיים","לפני %n חודשים","לפני %n חודשים"],
+ "next year" : "בשנה הבאה",
+ "last year" : "שנה שעברה",
+ "_in %n year_::_in %n years_" : ["בעוד שנה","בעוד שנתיים","בעוד %n שנים","בעוד %n שנים"],
+ "_%n year ago_::_%n years ago_" : ["לפני %n שנה","לפני %n שנים","לפני %n שנים","לפני %n שנים"],
+ "_in %n hour_::_in %n hours_" : ["בעוד שעה","בעוד שעתיים","בעוד %n שעות","בעוד %n שעות"],
+ "_%n hour ago_::_%n hours ago_" : ["לפני שעה","לפני שעתיים","לפני %n שעות","לפני %n שעות"],
+ "_in %n minute_::_in %n minutes_" : ["בעוד דקה","בעוד 2 דקות","בעוד %n דקות","בעוד %n דקות"],
+ "_%n minute ago_::_%n minutes ago_" : ["לפני דקה","לפני 2 דקות","לפני %n דקות","לפני %n דקות"],
+ "in a few seconds" : "בעוד מספר שניות",
+ "seconds ago" : "שניות",
+ "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "המודול עם המזהה: %s לא קיים. נא להפעיל אותו בהגדרות היישומונים שלך או ליצור קשר עם מנהל המערכת.",
+ "File name is a reserved word" : "שם קובץ הוא מילה שמורה",
+ "File name contains at least one invalid character" : "שם הקובץ כולל לפחות תו אחד לא חוקי",
+ "File name is too long" : "שם קובץ ארוך מדי",
+ "Dot files are not allowed" : "אסור ששמות קבצים יתחילו בנקודה",
+ "Empty filename is not allowed" : "שם קובץ ריק אינו מאושר",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "יישום \"%s\" לא ניתן להתקנה כיוון שקובץ appinfo לא ניתן לקריאה.",
+ "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "לא ניתן להתקין את היישומון „%s” כיוון שאין לו תמיכה בגרסה זו של השרת.",
+ "__language_name__" : "עברית",
+ "This is an automatically sent email, please do not reply." : "זו הודעת דוא״ל שנשלחה אוטומטית, נא לא להגיב.",
+ "Help" : "עזרה",
+ "Apps" : "יישומים",
+ "Settings" : "הגדרות",
+ "Log out" : "התנתק",
+ "Users" : "משתמשים",
+ "Unknown user" : "משתמש לא ידוע",
+ "Create" : "יצירה",
+ "Change" : "שינוי",
+ "Delete" : "מחיקה",
+ "Share" : "שיתוף",
+ "Overview" : "סקירה",
+ "Basic settings" : "הגדרות בסיסיות",
+ "Sharing" : "שיתוף",
+ "Security" : "אבטחה",
+ "Encryption" : "הצפנה",
+ "Groupware" : "קבוצתי",
+ "Additional settings" : "הגדרות נוספות",
+ "Personal info" : "פרטים אישיים",
+ "Mobile & desktop" : "נייד ושולחן עבודה",
+ "Unlimited" : "ללא הגבלה",
+ "Verifying" : "מתבצע אימות",
+ "Verifying …" : "מתבצע אימות…",
+ "Verify" : "אימות",
+ "%s enter the database username and name." : "%s יש להכניס את שם המשתמש ושם מסד הנתונים.",
+ "%s enter the database username." : "%s נכנס למסד נתוני שמות המשתמשים.",
+ "%s enter the database name." : "%s נכנס למסד נתוני השמות.",
+ "%s you may not use dots in the database name" : "%s לא ניתן להשתמש בנקודות בשם מסד הנתונים",
+ "Oracle connection could not be established" : "לא ניתן היה ליצור חיבור Oracle",
+ "Oracle username and/or password not valid" : "שם משתמש ו/או סיסמת Oracle אינם תקפים",
+ "PostgreSQL username and/or password not valid" : "שם משתמש ו/או סיסמת PostgreSQL אינם תקפים",
+ "You need to enter details of an existing account." : "עליך להקליד פרטים של חשבון קיים.",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X אינו נתמך ו- %s לא יעבוד כשורה בפלטפורמה זו. ניתן לקחת סיכון ולהשתמש באחריותך! ",
+ "For the best results, please consider using a GNU/Linux server instead." : "לתוצאות הכי טובות, יש לשקול שימוש בשרת GNU/Linux במקום.",
+ "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." : "נראה ש- %s עובד על בסיס סביבת 32-bit PHP ושה- open_basedir הוגדר בקובץ php.ini. מצב זה יוביל לבעיות עם קבצים הגדולים מ- 4 GB ואינו מומלץ לחלוטין.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "יש להסיר את הגדרת open_basedir מתוך קובץ php.ini או להחליף לסביבת 64-bit PHP.",
+ "Set an admin username." : "קביעת שם משתמש מנהל",
+ "Set an admin password." : "קביעת סיסמת מנהל",
+ "Can't create or write into the data directory %s" : "לא ניתן ליצור או לכתוב לתוך תיקיית הנתונים %s",
+ "Invalid Federated Cloud 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 נכשל, כיוון שהקובץ אינו קיים",
+ "You are not allowed to share %s" : "אינך רשאי/ת לשתף %s",
+ "Sharing %s failed, because you can not share with yourself" : "השיתוף %s נכשל, כיוון שלא ניתן לשתף עם עצמך",
+ "Sharing %s failed, because the user %s does not exist" : "השיתוף %s נכשל, כיוון שהמשתמש %s אינו קיים",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "השיתוף %s נכשל, כיוון שהמשתמש %s אינו חבר בקבוצות ש- %s חבר ב-",
+ "Sharing %s failed, because this item is already shared with %s" : "שיתוף %s נכשל, כיוון שפריט זה כבר משותף עם %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "השיתוף %s נכשל, כיוון שהפריט כבר משותף עם משתמש %s",
+ "Sharing %s failed, because the group %s does not exist" : "השיתוף %s נכשל, כיוון שהקבוצה %s אינה קיימת",
+ "Sharing %s failed, because %s is not a member of the group %s" : "השיתוף %s נכשל, כיוון ש- %s אינו חבר בקבוצה %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "יש לספק סיסמא ליצירת קישור ציבורי, רק קישורים מוגנים מותרים",
+ "Sharing %s failed, because sharing with links is not allowed" : "השיתוף %s נכשל, כיוון ששיתוף עם קישור אינו מותר",
+ "Not allowed to create a federated share with the same user" : "אסור ליצור שיתוף מאוגד עם אותו משתמש",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "שיתוף %s נכשל, לא ניתן לאתר %s, ייתכן שהשרת לא ניתן להשגה כרגע.",
+ "Share type %s is not valid for %s" : "שיתוף מסוג %s אינו תקף ל- %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "לא ניתן לקבוע תאריך תפוגה. שיתופים אינם יכולים לפוג תוקף מאוחר יותר מ- %s לאחר ששותפו",
+ "Cannot set expiration date. Expiration date is in the past" : "לא ניתן לקבוע תאריך תפוגה. תאריך התפוגה הנו בעבר",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "צד אחורי לשיתוף %s חייב ליישם את ממשק OCP\\Share_Backend",
+ "Sharing backend %s not found" : "צד אחורי לשיתוף %s לא נמצא",
+ "Sharing backend for %s not found" : "צד אחורי לשיתוף של %s לא נמצא",
+ "Sharing failed, because the user %s is the original sharer" : "שיתוף נכשל, כיוון שמשתמש %s הנו המשתף המקורי",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "השיתוף %s נכשל, כיוון שההרשאות עלו על ההרשאות שניתנו ל- %s",
+ "Sharing %s failed, because resharing is not allowed" : "השיתוף %s נכשל, כיוון ששיתוף מחודש אסור",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "השיתוף %s נכשל, כיוון שבצד אחורי לשיתוף עבור %s לא ניתן היה לאתר את מקורו",
+ "Sharing %s failed, because the file could not be found in the file cache" : "השיתוף %s נכשל, כייון שלא ניתן היה למצוא את הקובץ בזכרון המטמון",
+ "Can’t increase permissions of %s" : "לא ניתן לחזק את ההרשאות של %s",
+ "Files can’t be shared with delete permissions" : "לא ניתן לשתף קבצים עם הרשאת מחיקה",
+ "Files can’t be shared with create permissions" : "לא ניתן לשתף קבצים עם הרשאות יצירה",
+ "Expiration date is in the past" : "תאריך תפוגה הנו בעבר",
+ "Can’t set expiration date more than %s days in the future" : "לא ניתן להגדיר את תאריך התפוגה מעל %s ימים בעתיד",
+ "%s shared »%s« with you" : "%s שיתף/שיתפה איתך את »%s«",
+ "Click the button below to open it." : "יש ללחוץ על הכפתור להלן כדי לפתוח אותו.",
+ "Open »%s«" : "פתיחת „%s”",
+ "%s via %s" : "%s על בסיס %s",
+ "The requested share does not exist anymore" : "השיתוף המבוקש אינו קיים עוד",
+ "Could not find category \"%s\"" : "לא ניתן למצוא את הקטגוריה „%s“",
+ "Sunday" : "יום ראשון",
+ "Monday" : "יום שני",
+ "Tuesday" : "יום שלישי",
+ "Wednesday" : "יום רביעי",
+ "Thursday" : "יום חמישי",
+ "Friday" : "יום שישי",
+ "Saturday" : "שבת",
+ "Sun." : "ראשון",
+ "Mon." : "שני",
+ "Tue." : "שלישי",
+ "Wed." : "רביעי",
+ "Thu." : "חמישי",
+ "Fri." : "שישי",
+ "Sat." : "שבת",
+ "Su" : "א",
+ "Mo" : "ב",
+ "Tu" : "ג",
+ "We" : "ד",
+ "Th" : "ה",
+ "Fr" : "ו",
+ "Sa" : "ש",
+ "January" : "ינואר",
+ "February" : "פברואר",
+ "March" : "מרץ",
+ "April" : "אפריל",
+ "May" : "מאי",
+ "June" : "יוני",
+ "July" : "יולי",
+ "August" : "אוגוסט",
+ "September" : "ספטמבר",
+ "October" : "אוקטובר",
+ "November" : "נובמבר",
+ "December" : "דצמבר",
+ "Jan." : "ינו׳",
+ "Feb." : "פבר׳",
+ "Mar." : "מרץ",
+ "Apr." : "אפר׳",
+ "May." : "מאי",
+ "Jun." : "יונ׳",
+ "Jul." : "יול׳",
+ "Aug." : "אוג׳",
+ "Sep." : "ספט׳",
+ "Oct." : "אוק׳",
+ "Nov." : "נוב׳",
+ "Dec." : "דצמ׳",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "רק התווים הבאים מאושרים לשם משתמש: \"a-z\", \"A-Z\", \"0-9\", וגם \"_.@-'\"",
+ "A valid username must be provided" : "יש לספק שם משתמש תקני",
+ "Username contains whitespace at the beginning or at the end" : "שם המשתמש מכיל רווח בתחילתו או בסופו",
+ "Username must not consist of dots only" : "שם המשתמש לא יכול להיות מורכב מנקודות בלבד",
+ "A valid password must be provided" : "יש לספק ססמה תקנית",
+ "The username is already being used" : "השם משתמש כבר בשימוש",
+ "Could not create user" : "לא ניתן ליצור משתמש",
+ "User disabled" : "משתמש מנוטרל",
+ "Login canceled by app" : "התחברות בוטלה על ידי יישום",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "היישום \"%s\" לא ניתן להתקנה כיוון שיחסי התלות הבאים אינם מתקיימים: %s",
+ "a safe home for all your data" : "בית בטוח עבור כל המידע שלך",
+ "File is currently busy, please try again later" : "הקובץ בשימוש כרגע, יש לנסות שוב מאוחר יותר",
+ "Can't read file" : "לא ניתן לקרוא קובץ",
+ "Application is not enabled" : "יישומים אינם מופעלים",
+ "Authentication error" : "שגיאת הזדהות",
+ "Token expired. Please reload page." : "פג תוקף. נא לטעון שוב את הדף.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "לא מותקנים דרייברים למסד הנתונים (sqlite, mysql, או postgresql).",
+ "Cannot write into \"config\" directory" : "לא ניתן לכתוב לתיקיית \"config\"!",
+ "Cannot write into \"apps\" directory" : "לא ניתן לכתוב לתיקיית \"apps\"",
+ "This can usually be fixed by giving the webserver write access to the apps directory or disabling the appstore in the config file. See %s" : "בדרך כלל ניתן לתקן זאת על ידי הענקת גישה לשרת לכתוב לתיקיית היישומונים או להשבית את חנות היישומונים בקובץ ההגדרות. נא לעיין ב־%s",
+ "Cannot create \"data\" directory" : "לא ניתן ליצור תיקיית „data”",
+ "This can usually be fixed by giving the webserver write access to the root directory. See %s" : "בדרך כלל ניתן לתקן זאת על ידי הענקת גישה לשרת לכתוב לתיקיית הבסיס. נא לעיין ב־%s",
+ "Permissions can usually be fixed by giving the webserver write access to the root directory. See %s." : "בדרך כלל ניתן לתקן הרשאות על ידי מתן גישה לשרת שלך אל תיקיית העל. נא לעיין ב־%s.",
+ "Setting locale to %s failed" : "הגדרת שפה ל- %s נכשלה",
+ "Please install one of these locales on your system and restart your webserver." : "יש להתקין אחת מהשפות על המערכת שלך ולהפעיל מחדש את שרת האינטרנט.",
+ "Please ask your server administrator to install the module." : "יש לבקש ממנהל השרת שלך להתקין את המודול.",
+ "PHP module %s not installed." : "מודול PHP %s אינו מותקן.",
+ "PHP setting \"%s\" is not set to \"%s\"." : "הגדרות PHP \"%s\" אינם מוגדרות ל- \"%s\"",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "התאמת ההגדרה הזו ב־php.ini יאפשר ל־Nextcloud לפעול שוב",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload מוגדר ל- \"%s\" במקום הערך המצופה \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "לתיקון בעיה זו יש להגדיר <code>mbstring.func_overload</code> כ- <code>0</code> iבקובץ ה- php.ini שלך",
+ "libxml2 2.7.0 is at least required. Currently %s is installed." : "libxml2 2.7.0 נדרש לכל הפחות. כרגע %s מותקן.",
+ "To fix this issue update your libxml2 version and restart your web server." : "לתיקון הבעיה יש לעדכן את גרסת ה- libxml2 שלך ולהפעיל מחדש את שרת האינטרנט שלך.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ככל הנראה מוגדר ל- strip inline doc blocks. זה יגרום למספר יישומי ליבה לא להיות נגישים.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "זה ככל הנראה נגרם על ידי מאיץ/מטמון כמו Zend OPcache או eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "מודולי PHP הותקנו, אך עדיין רשומים כחסרים?",
+ "Please ask your server administrator to restart the web server." : "יש לבקש ממנהל השרת שלך להפעיל מחדש את שרת האינטרנט.",
+ "PostgreSQL >= 9 required" : "נדרש PostgreSQL >= 9",
+ "Please upgrade your database version" : "יש לשדרג את גרסת מסד הנתונים שלך",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "יש לשנות את ההרשאות ל- 0770 כך שהתיקייה לא תרשם על ידי משתמשים אחרים.",
+ "Your data directory is readable by other users" : "תיקיית הנתונים שלך ניתנת לקריאה על ידי משתמשים אחרים",
+ "Your data directory must be an absolute path" : "תיקיית הנתונים שלך חייבת להיות במבנה של נתיב מלא (מיקום מוחלט)",
+ "Check the value of \"datadirectory\" in your configuration" : "יש לבדוק את הערך \"datadirectory\" בהגדרות התצורה שלך",
+ "Your data directory is invalid" : "תיקיית הנתונים שלך שגויה",
+ "Ensure there is a file called \".ocdata\" in the root of the data directory." : "נא לוודא שיש קובץ בשם „‎.ocdata” בבסיס תיקיית הנתונים שלך.",
+ "Action \"%s\" not supported or implemented." : "הפעולה „%s” אינה נתמכת או שאינה מוטמעת.",
+ "Authentication failed, wrong token or provider ID given" : "האימות נכשל, האסימון או מזהה הספק שסופקו שגויים",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "חסרים משתנים להשלמת הבקשה. המשתנים החסרים: „%s”",
+ "Could not obtain lock type %d on \"%s\"." : "לא ניתן היה להשיג סוג נעילה %d ב- \"%s\".",
+ "Storage unauthorized. %s" : "אחסון לא מורשה. %s",
+ "Storage incomplete configuration. %s" : "תצורה לא מושלמת של האחסון. %s",
+ "Storage connection error. %s" : "שגיאת חיבור אחסון. %s",
+ "Storage is temporarily not available" : "האחסון אינו זמין כרגע",
+ "Storage connection timeout. %s" : "פסק זמן חיבור אחסון. %s",
+ "Personal" : "אישי",
+ "Admin" : "מנהל",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "טיפים וטריקים",
+ "DB Error: \"%s\"" : "שגיאת מסד נתונים: „%s”",
+ "Offending command was: \"%s\"" : "הפקודה הסוררת הייתה: „%s”",
+ "Offending command was: \"%s\", name: %s, password: %s" : "הפקודה הסוררת הייתה: „%s”, שם: %s, ססמה: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "הגדרות ההרשאות עבור %s נכשלה, כיוון שההרשאות חורגות מההרשאות שהוענקו ל־%s ",
+ "Setting permissions for %s failed, because the item was not found" : "הגדרת ההרשאות עבור %s נכשלה, כיוון שהפריט לא נמצא",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "לא ניתן למחוק את מועד התפוגה. לשיתופים צריך להיות מועד תפוגה.",
+ "Cannot increase permissions of %s" : "לא ניתן להוסיף על ההרשאות של %s",
+ "Files can't be shared with delete permissions" : "אי אפשר לשתף קבצים עם הרשאות מחיקה",
+ "Files can't be shared with create permissions" : "אי אפשר לשתף קבצים עם הרשאות יצירה",
+ "Cannot set expiration date more than %s days in the future" : "לא ניתן להגדיר מועד תפוגה של למעלה מ־%s ימים בעתיד",
+ "No app name specified" : "לא צוין שם יישומון",
+ "App '%s' could not be installed!" : "לא ניתן להתקין את היישומון ‚%s’!",
+ "Sync clients" : "סנכרון לקוחות"
+},
+"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;");
diff --git a/lib/l10n/he.json b/lib/l10n/he.json
new file mode 100644
index 00000000000..493005d7992
--- /dev/null
+++ b/lib/l10n/he.json
@@ -0,0 +1,252 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "לא ניתן לכתוב לתיקיית „config”!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "בדרך כלל ניתן לפתור את הבעיה על ידי כך שנותנים לתכנית השרת הרשאות כתיבה לתיקיית config",
+ "See %s" : "יש לעיין ב־%s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "או, אם עדיף לך לשמור על config.php לקריאה בלבד, ניתן להגדיר את האפשרות „config_is_read_only” לערך true.",
+ "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "בדרך כלל ניתן לתקן זאת על ידי הענקת גישה לשרת לכתוב לתיקיית ההגדרות. נא לעיין ב־%s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "או, אם עדיף לך לשמור על config.php לקריאה בלבד, ניתן להגדיר את האפשרות „config_is_read_only” לערך true. נא לעיין ב־%s",
+ "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "הקבצים של היישומון %$1s לא הוחלפו כראוי. נא לוודא שגרסה זו תואמת לזו של השרת.",
+ "Sample configuration detected" : "התגלתה דוגמת תצורה",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "התגלה שדוגמת התצורה הועתקה. דבר זה עלול לשבור את ההתקנה ולא נתמך.יש לקרוא את מסמכי התיעוד לפני שמבצעים שינויים ב- config.php",
+ "Education Edition" : "מהדורה חינוכית",
+ "Enterprise bundle" : "מהדורה מסחרית",
+ "Groupware bundle" : "מהדורה קבוצתית",
+ "Social sharing bundle" : "מאגד שיתוף חברתי",
+ "PHP %s or higher is required." : "נדרש PHP בגרסת %s ומעלה.",
+ "PHP with a version lower than %s is required." : "נדרש PHP בגרסה נמוכה מ- %s.",
+ "%sbit or higher PHP required." : "נדרש PHP בגרסת %s ומעלה.",
+ "Following databases are supported: %s" : "מסדי הנתונים הבאים נתמכים: %s",
+ "The command line tool %s could not be found" : "כלי שורת הפקודה %s לא אותר",
+ "The library %s is not available." : "הספריה %s אינה זמינה.",
+ "Library %s with a version higher than %s is required - available version %s." : "ספריה %s בגרסה גבוהה מ- %s נדרשת - גרסה זמינה %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "ספריה %s בגרסה נמוכה מ- %s נדרשת - גרסה זמינה %s.",
+ "Following platforms are supported: %s" : "הפלטפורמות הבאות נתמכות: %s",
+ "Server version %s or higher is required." : "נדרשת גרסה שרת %s ומעלה.",
+ "Server version %s or lower is required." : "נדרשת גרסה שרת %s ומטה.",
+ "Logged in user must be an admin" : "על המשתמש שנכנס להיות מנהל",
+ "Unknown filetype" : "סוג קובץ לא מוכר",
+ "Invalid image" : "תמונה לא חוקית",
+ "Avatar image is not square" : "התמונה המייצגת אינה מרובעת",
+ "today" : "היום",
+ "tomorrow" : "מחר",
+ "yesterday" : "אתמול",
+ "_in %n day_::_in %n days_" : ["בעוד יום","בעוד יומיים","בעוד %n ימים","בעוד %n ימים"],
+ "_%n day ago_::_%n days ago_" : ["לפני %n יום","לפני %n ימים","לפני %n ימים","לפני %n ימים"],
+ "next month" : "בחודש הבא",
+ "last month" : "חודש שעבר",
+ "_in %n month_::_in %n months_" : ["בעוד חודש","בעוד חודשיים","בעוד %n חודשים","בעוד %n חודשים"],
+ "_%n month ago_::_%n months ago_" : ["לפני חודש","לפני חודשיים","לפני %n חודשים","לפני %n חודשים"],
+ "next year" : "בשנה הבאה",
+ "last year" : "שנה שעברה",
+ "_in %n year_::_in %n years_" : ["בעוד שנה","בעוד שנתיים","בעוד %n שנים","בעוד %n שנים"],
+ "_%n year ago_::_%n years ago_" : ["לפני %n שנה","לפני %n שנים","לפני %n שנים","לפני %n שנים"],
+ "_in %n hour_::_in %n hours_" : ["בעוד שעה","בעוד שעתיים","בעוד %n שעות","בעוד %n שעות"],
+ "_%n hour ago_::_%n hours ago_" : ["לפני שעה","לפני שעתיים","לפני %n שעות","לפני %n שעות"],
+ "_in %n minute_::_in %n minutes_" : ["בעוד דקה","בעוד 2 דקות","בעוד %n דקות","בעוד %n דקות"],
+ "_%n minute ago_::_%n minutes ago_" : ["לפני דקה","לפני 2 דקות","לפני %n דקות","לפני %n דקות"],
+ "in a few seconds" : "בעוד מספר שניות",
+ "seconds ago" : "שניות",
+ "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "המודול עם המזהה: %s לא קיים. נא להפעיל אותו בהגדרות היישומונים שלך או ליצור קשר עם מנהל המערכת.",
+ "File name is a reserved word" : "שם קובץ הוא מילה שמורה",
+ "File name contains at least one invalid character" : "שם הקובץ כולל לפחות תו אחד לא חוקי",
+ "File name is too long" : "שם קובץ ארוך מדי",
+ "Dot files are not allowed" : "אסור ששמות קבצים יתחילו בנקודה",
+ "Empty filename is not allowed" : "שם קובץ ריק אינו מאושר",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "יישום \"%s\" לא ניתן להתקנה כיוון שקובץ appinfo לא ניתן לקריאה.",
+ "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "לא ניתן להתקין את היישומון „%s” כיוון שאין לו תמיכה בגרסה זו של השרת.",
+ "__language_name__" : "עברית",
+ "This is an automatically sent email, please do not reply." : "זו הודעת דוא״ל שנשלחה אוטומטית, נא לא להגיב.",
+ "Help" : "עזרה",
+ "Apps" : "יישומים",
+ "Settings" : "הגדרות",
+ "Log out" : "התנתק",
+ "Users" : "משתמשים",
+ "Unknown user" : "משתמש לא ידוע",
+ "Create" : "יצירה",
+ "Change" : "שינוי",
+ "Delete" : "מחיקה",
+ "Share" : "שיתוף",
+ "Overview" : "סקירה",
+ "Basic settings" : "הגדרות בסיסיות",
+ "Sharing" : "שיתוף",
+ "Security" : "אבטחה",
+ "Encryption" : "הצפנה",
+ "Groupware" : "קבוצתי",
+ "Additional settings" : "הגדרות נוספות",
+ "Personal info" : "פרטים אישיים",
+ "Mobile & desktop" : "נייד ושולחן עבודה",
+ "Unlimited" : "ללא הגבלה",
+ "Verifying" : "מתבצע אימות",
+ "Verifying …" : "מתבצע אימות…",
+ "Verify" : "אימות",
+ "%s enter the database username and name." : "%s יש להכניס את שם המשתמש ושם מסד הנתונים.",
+ "%s enter the database username." : "%s נכנס למסד נתוני שמות המשתמשים.",
+ "%s enter the database name." : "%s נכנס למסד נתוני השמות.",
+ "%s you may not use dots in the database name" : "%s לא ניתן להשתמש בנקודות בשם מסד הנתונים",
+ "Oracle connection could not be established" : "לא ניתן היה ליצור חיבור Oracle",
+ "Oracle username and/or password not valid" : "שם משתמש ו/או סיסמת Oracle אינם תקפים",
+ "PostgreSQL username and/or password not valid" : "שם משתמש ו/או סיסמת PostgreSQL אינם תקפים",
+ "You need to enter details of an existing account." : "עליך להקליד פרטים של חשבון קיים.",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X אינו נתמך ו- %s לא יעבוד כשורה בפלטפורמה זו. ניתן לקחת סיכון ולהשתמש באחריותך! ",
+ "For the best results, please consider using a GNU/Linux server instead." : "לתוצאות הכי טובות, יש לשקול שימוש בשרת GNU/Linux במקום.",
+ "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." : "נראה ש- %s עובד על בסיס סביבת 32-bit PHP ושה- open_basedir הוגדר בקובץ php.ini. מצב זה יוביל לבעיות עם קבצים הגדולים מ- 4 GB ואינו מומלץ לחלוטין.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "יש להסיר את הגדרת open_basedir מתוך קובץ php.ini או להחליף לסביבת 64-bit PHP.",
+ "Set an admin username." : "קביעת שם משתמש מנהל",
+ "Set an admin password." : "קביעת סיסמת מנהל",
+ "Can't create or write into the data directory %s" : "לא ניתן ליצור או לכתוב לתוך תיקיית הנתונים %s",
+ "Invalid Federated Cloud 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 נכשל, כיוון שהקובץ אינו קיים",
+ "You are not allowed to share %s" : "אינך רשאי/ת לשתף %s",
+ "Sharing %s failed, because you can not share with yourself" : "השיתוף %s נכשל, כיוון שלא ניתן לשתף עם עצמך",
+ "Sharing %s failed, because the user %s does not exist" : "השיתוף %s נכשל, כיוון שהמשתמש %s אינו קיים",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "השיתוף %s נכשל, כיוון שהמשתמש %s אינו חבר בקבוצות ש- %s חבר ב-",
+ "Sharing %s failed, because this item is already shared with %s" : "שיתוף %s נכשל, כיוון שפריט זה כבר משותף עם %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "השיתוף %s נכשל, כיוון שהפריט כבר משותף עם משתמש %s",
+ "Sharing %s failed, because the group %s does not exist" : "השיתוף %s נכשל, כיוון שהקבוצה %s אינה קיימת",
+ "Sharing %s failed, because %s is not a member of the group %s" : "השיתוף %s נכשל, כיוון ש- %s אינו חבר בקבוצה %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "יש לספק סיסמא ליצירת קישור ציבורי, רק קישורים מוגנים מותרים",
+ "Sharing %s failed, because sharing with links is not allowed" : "השיתוף %s נכשל, כיוון ששיתוף עם קישור אינו מותר",
+ "Not allowed to create a federated share with the same user" : "אסור ליצור שיתוף מאוגד עם אותו משתמש",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "שיתוף %s נכשל, לא ניתן לאתר %s, ייתכן שהשרת לא ניתן להשגה כרגע.",
+ "Share type %s is not valid for %s" : "שיתוף מסוג %s אינו תקף ל- %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "לא ניתן לקבוע תאריך תפוגה. שיתופים אינם יכולים לפוג תוקף מאוחר יותר מ- %s לאחר ששותפו",
+ "Cannot set expiration date. Expiration date is in the past" : "לא ניתן לקבוע תאריך תפוגה. תאריך התפוגה הנו בעבר",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "צד אחורי לשיתוף %s חייב ליישם את ממשק OCP\\Share_Backend",
+ "Sharing backend %s not found" : "צד אחורי לשיתוף %s לא נמצא",
+ "Sharing backend for %s not found" : "צד אחורי לשיתוף של %s לא נמצא",
+ "Sharing failed, because the user %s is the original sharer" : "שיתוף נכשל, כיוון שמשתמש %s הנו המשתף המקורי",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "השיתוף %s נכשל, כיוון שההרשאות עלו על ההרשאות שניתנו ל- %s",
+ "Sharing %s failed, because resharing is not allowed" : "השיתוף %s נכשל, כיוון ששיתוף מחודש אסור",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "השיתוף %s נכשל, כיוון שבצד אחורי לשיתוף עבור %s לא ניתן היה לאתר את מקורו",
+ "Sharing %s failed, because the file could not be found in the file cache" : "השיתוף %s נכשל, כייון שלא ניתן היה למצוא את הקובץ בזכרון המטמון",
+ "Can’t increase permissions of %s" : "לא ניתן לחזק את ההרשאות של %s",
+ "Files can’t be shared with delete permissions" : "לא ניתן לשתף קבצים עם הרשאת מחיקה",
+ "Files can’t be shared with create permissions" : "לא ניתן לשתף קבצים עם הרשאות יצירה",
+ "Expiration date is in the past" : "תאריך תפוגה הנו בעבר",
+ "Can’t set expiration date more than %s days in the future" : "לא ניתן להגדיר את תאריך התפוגה מעל %s ימים בעתיד",
+ "%s shared »%s« with you" : "%s שיתף/שיתפה איתך את »%s«",
+ "Click the button below to open it." : "יש ללחוץ על הכפתור להלן כדי לפתוח אותו.",
+ "Open »%s«" : "פתיחת „%s”",
+ "%s via %s" : "%s על בסיס %s",
+ "The requested share does not exist anymore" : "השיתוף המבוקש אינו קיים עוד",
+ "Could not find category \"%s\"" : "לא ניתן למצוא את הקטגוריה „%s“",
+ "Sunday" : "יום ראשון",
+ "Monday" : "יום שני",
+ "Tuesday" : "יום שלישי",
+ "Wednesday" : "יום רביעי",
+ "Thursday" : "יום חמישי",
+ "Friday" : "יום שישי",
+ "Saturday" : "שבת",
+ "Sun." : "ראשון",
+ "Mon." : "שני",
+ "Tue." : "שלישי",
+ "Wed." : "רביעי",
+ "Thu." : "חמישי",
+ "Fri." : "שישי",
+ "Sat." : "שבת",
+ "Su" : "א",
+ "Mo" : "ב",
+ "Tu" : "ג",
+ "We" : "ד",
+ "Th" : "ה",
+ "Fr" : "ו",
+ "Sa" : "ש",
+ "January" : "ינואר",
+ "February" : "פברואר",
+ "March" : "מרץ",
+ "April" : "אפריל",
+ "May" : "מאי",
+ "June" : "יוני",
+ "July" : "יולי",
+ "August" : "אוגוסט",
+ "September" : "ספטמבר",
+ "October" : "אוקטובר",
+ "November" : "נובמבר",
+ "December" : "דצמבר",
+ "Jan." : "ינו׳",
+ "Feb." : "פבר׳",
+ "Mar." : "מרץ",
+ "Apr." : "אפר׳",
+ "May." : "מאי",
+ "Jun." : "יונ׳",
+ "Jul." : "יול׳",
+ "Aug." : "אוג׳",
+ "Sep." : "ספט׳",
+ "Oct." : "אוק׳",
+ "Nov." : "נוב׳",
+ "Dec." : "דצמ׳",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "רק התווים הבאים מאושרים לשם משתמש: \"a-z\", \"A-Z\", \"0-9\", וגם \"_.@-'\"",
+ "A valid username must be provided" : "יש לספק שם משתמש תקני",
+ "Username contains whitespace at the beginning or at the end" : "שם המשתמש מכיל רווח בתחילתו או בסופו",
+ "Username must not consist of dots only" : "שם המשתמש לא יכול להיות מורכב מנקודות בלבד",
+ "A valid password must be provided" : "יש לספק ססמה תקנית",
+ "The username is already being used" : "השם משתמש כבר בשימוש",
+ "Could not create user" : "לא ניתן ליצור משתמש",
+ "User disabled" : "משתמש מנוטרל",
+ "Login canceled by app" : "התחברות בוטלה על ידי יישום",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "היישום \"%s\" לא ניתן להתקנה כיוון שיחסי התלות הבאים אינם מתקיימים: %s",
+ "a safe home for all your data" : "בית בטוח עבור כל המידע שלך",
+ "File is currently busy, please try again later" : "הקובץ בשימוש כרגע, יש לנסות שוב מאוחר יותר",
+ "Can't read file" : "לא ניתן לקרוא קובץ",
+ "Application is not enabled" : "יישומים אינם מופעלים",
+ "Authentication error" : "שגיאת הזדהות",
+ "Token expired. Please reload page." : "פג תוקף. נא לטעון שוב את הדף.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "לא מותקנים דרייברים למסד הנתונים (sqlite, mysql, או postgresql).",
+ "Cannot write into \"config\" directory" : "לא ניתן לכתוב לתיקיית \"config\"!",
+ "Cannot write into \"apps\" directory" : "לא ניתן לכתוב לתיקיית \"apps\"",
+ "This can usually be fixed by giving the webserver write access to the apps directory or disabling the appstore in the config file. See %s" : "בדרך כלל ניתן לתקן זאת על ידי הענקת גישה לשרת לכתוב לתיקיית היישומונים או להשבית את חנות היישומונים בקובץ ההגדרות. נא לעיין ב־%s",
+ "Cannot create \"data\" directory" : "לא ניתן ליצור תיקיית „data”",
+ "This can usually be fixed by giving the webserver write access to the root directory. See %s" : "בדרך כלל ניתן לתקן זאת על ידי הענקת גישה לשרת לכתוב לתיקיית הבסיס. נא לעיין ב־%s",
+ "Permissions can usually be fixed by giving the webserver write access to the root directory. See %s." : "בדרך כלל ניתן לתקן הרשאות על ידי מתן גישה לשרת שלך אל תיקיית העל. נא לעיין ב־%s.",
+ "Setting locale to %s failed" : "הגדרת שפה ל- %s נכשלה",
+ "Please install one of these locales on your system and restart your webserver." : "יש להתקין אחת מהשפות על המערכת שלך ולהפעיל מחדש את שרת האינטרנט.",
+ "Please ask your server administrator to install the module." : "יש לבקש ממנהל השרת שלך להתקין את המודול.",
+ "PHP module %s not installed." : "מודול PHP %s אינו מותקן.",
+ "PHP setting \"%s\" is not set to \"%s\"." : "הגדרות PHP \"%s\" אינם מוגדרות ל- \"%s\"",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "התאמת ההגדרה הזו ב־php.ini יאפשר ל־Nextcloud לפעול שוב",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload מוגדר ל- \"%s\" במקום הערך המצופה \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "לתיקון בעיה זו יש להגדיר <code>mbstring.func_overload</code> כ- <code>0</code> iבקובץ ה- php.ini שלך",
+ "libxml2 2.7.0 is at least required. Currently %s is installed." : "libxml2 2.7.0 נדרש לכל הפחות. כרגע %s מותקן.",
+ "To fix this issue update your libxml2 version and restart your web server." : "לתיקון הבעיה יש לעדכן את גרסת ה- libxml2 שלך ולהפעיל מחדש את שרת האינטרנט שלך.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ככל הנראה מוגדר ל- strip inline doc blocks. זה יגרום למספר יישומי ליבה לא להיות נגישים.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "זה ככל הנראה נגרם על ידי מאיץ/מטמון כמו Zend OPcache או eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "מודולי PHP הותקנו, אך עדיין רשומים כחסרים?",
+ "Please ask your server administrator to restart the web server." : "יש לבקש ממנהל השרת שלך להפעיל מחדש את שרת האינטרנט.",
+ "PostgreSQL >= 9 required" : "נדרש PostgreSQL >= 9",
+ "Please upgrade your database version" : "יש לשדרג את גרסת מסד הנתונים שלך",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "יש לשנות את ההרשאות ל- 0770 כך שהתיקייה לא תרשם על ידי משתמשים אחרים.",
+ "Your data directory is readable by other users" : "תיקיית הנתונים שלך ניתנת לקריאה על ידי משתמשים אחרים",
+ "Your data directory must be an absolute path" : "תיקיית הנתונים שלך חייבת להיות במבנה של נתיב מלא (מיקום מוחלט)",
+ "Check the value of \"datadirectory\" in your configuration" : "יש לבדוק את הערך \"datadirectory\" בהגדרות התצורה שלך",
+ "Your data directory is invalid" : "תיקיית הנתונים שלך שגויה",
+ "Ensure there is a file called \".ocdata\" in the root of the data directory." : "נא לוודא שיש קובץ בשם „‎.ocdata” בבסיס תיקיית הנתונים שלך.",
+ "Action \"%s\" not supported or implemented." : "הפעולה „%s” אינה נתמכת או שאינה מוטמעת.",
+ "Authentication failed, wrong token or provider ID given" : "האימות נכשל, האסימון או מזהה הספק שסופקו שגויים",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "חסרים משתנים להשלמת הבקשה. המשתנים החסרים: „%s”",
+ "Could not obtain lock type %d on \"%s\"." : "לא ניתן היה להשיג סוג נעילה %d ב- \"%s\".",
+ "Storage unauthorized. %s" : "אחסון לא מורשה. %s",
+ "Storage incomplete configuration. %s" : "תצורה לא מושלמת של האחסון. %s",
+ "Storage connection error. %s" : "שגיאת חיבור אחסון. %s",
+ "Storage is temporarily not available" : "האחסון אינו זמין כרגע",
+ "Storage connection timeout. %s" : "פסק זמן חיבור אחסון. %s",
+ "Personal" : "אישי",
+ "Admin" : "מנהל",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "טיפים וטריקים",
+ "DB Error: \"%s\"" : "שגיאת מסד נתונים: „%s”",
+ "Offending command was: \"%s\"" : "הפקודה הסוררת הייתה: „%s”",
+ "Offending command was: \"%s\", name: %s, password: %s" : "הפקודה הסוררת הייתה: „%s”, שם: %s, ססמה: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "הגדרות ההרשאות עבור %s נכשלה, כיוון שההרשאות חורגות מההרשאות שהוענקו ל־%s ",
+ "Setting permissions for %s failed, because the item was not found" : "הגדרת ההרשאות עבור %s נכשלה, כיוון שהפריט לא נמצא",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "לא ניתן למחוק את מועד התפוגה. לשיתופים צריך להיות מועד תפוגה.",
+ "Cannot increase permissions of %s" : "לא ניתן להוסיף על ההרשאות של %s",
+ "Files can't be shared with delete permissions" : "אי אפשר לשתף קבצים עם הרשאות מחיקה",
+ "Files can't be shared with create permissions" : "אי אפשר לשתף קבצים עם הרשאות יצירה",
+ "Cannot set expiration date more than %s days in the future" : "לא ניתן להגדיר מועד תפוגה של למעלה מ־%s ימים בעתיד",
+ "No app name specified" : "לא צוין שם יישומון",
+ "App '%s' could not be installed!" : "לא ניתן להתקין את היישומון ‚%s’!",
+ "Sync clients" : "סנכרון לקוחות"
+},"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;"
+} \ No newline at end of file
diff --git a/lib/l10n/hr.js b/lib/l10n/hr.js
new file mode 100644
index 00000000000..6bd56fd7773
--- /dev/null
+++ b/lib/l10n/hr.js
@@ -0,0 +1,82 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Pisanje u \"config\" direktoriju nije moguće!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Ovo se obično može popraviti tako da se Web poslužitelju dopusti pristup za pisanje u config direktoriju",
+ "See %s" : "Vidite %s",
+ "Sample configuration detected" : "Nađena ogledna konfiguracija",
+ "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" : "Otkriveno je da je ogledna konfiguracija kopirana. To može vašu instalaciju prekinuti i nije podržano.Molimo pročitajte dokumentaciju prije nego li izvršite promjene na config.php",
+ "PHP %s or higher is required." : "PHP verzija treba biti %s ili viša.",
+ "PHP with a version lower than %s is required." : "PHP sa verzijom manjom od %s je potrebna.",
+ "Following databases are supported: %s" : "Sljedece baza podataka je podrzana: %s",
+ "The library %s is not available." : "Knjiznica %s nije dostupna.",
+ "Following platforms are supported: %s" : "Sljedece platforme su podrzane: %s",
+ "Unknown filetype" : "Vrsta datoteke nepoznata",
+ "Invalid image" : "Neispravna slika",
+ "today" : "Danas",
+ "yesterday" : "Jučer",
+ "last month" : "Prošli mjesec",
+ "_%n month ago_::_%n months ago_" : ["prije %n mjeseca","prije %n mjeseci","prije %n mjeseci"],
+ "last year" : "Prošle godine",
+ "_%n hour ago_::_%n hours ago_" : ["prije %n sata","prije %n sati","prije %n sati"],
+ "_%n minute ago_::_%n minutes ago_" : ["prije %n minute","prije %n minuta","prije %n minuta"],
+ "seconds ago" : "prije par sekundi",
+ "__language_name__" : "Hrvatski",
+ "Apps" : "Aplikacije",
+ "Users" : "Korisnici",
+ "Unknown user" : "Korisnik nepoznat",
+ "%s enter the database username." : "%s unesite naziva korisnika baze podataka.",
+ "%s enter the database name." : "%s unesite naziv baze podataka",
+ "%s you may not use dots in the database name" : "%s ne smijete koristiti točke u nazivu baze podataka",
+ "Oracle connection could not be established" : "Vezu Oracle nije moguće uspostaviti",
+ "Oracle username and/or password not valid" : "Korisničko ime i/ili lozinka Oracle neispravni",
+ "PostgreSQL username and/or password not valid" : "Korisničko ime i/ili lozinka PostgreSQL neispravni",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nije podržan i %s na ovoj platformi neće raditi kako treba.",
+ "For the best results, please consider using a GNU/Linux server instead." : "Za najbolje rezultate, molimo razmotrite mogućnost korištenje poslužitelja GNU/Linux.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Molimo uklonite postavke za open_basedir setting iz datoteke php.ini ili se prebacite na 64-bitni PHP.",
+ "Set an admin username." : "Navedite admin korisničko ime.",
+ "Set an admin password." : "Navedite admin lozinku.",
+ "Can't create or write into the data directory %s" : "Ne moze se kreirati ili napisati u imenik podataka %s",
+ "Sharing %s failed, because the file does not exist" : "Dijeljenje %s nije uspjelo jer ta datoteka ne postoji",
+ "You are not allowed to share %s" : "Nije vam dopušteno dijeliti %s",
+ "Sharing %s failed, because the user %s does not exist" : "Dijeljenje %s nije uspjelo jer korisnik %s ne postoji",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Dijeljenje %s nije uspjelo jer korisnik %s nije član niti jedne grupe u kojoj je %s član",
+ "Sharing %s failed, because this item is already shared with %s" : "Dijeljenje %s nije uspjelo jer je ova stavka već podijeljena s %s",
+ "Sharing %s failed, because the group %s does not exist" : "Dijeljenje %s nije uspjelo jer grupa %s ne postoji",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Dijeljenje %s nije uspjelo jer %s nije član grupe %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Da biste kreirali javnu vezu, morate navesti lozinku, samo zaštićene veze su dopuštene.",
+ "Sharing %s failed, because sharing with links is not allowed" : "Dijeljenje %s nije uspjelo jer dijeljenje s vezama nije dopušteno.",
+ "Share type %s is not valid for %s" : "Tip dijeljenja %s nije dopušteni tip za %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Nije moguće postaviti datum isteka. Nakon što su podijeljeni, resursi ne mogu isteći kasnije nego %s ",
+ "Cannot set expiration date. Expiration date is in the past" : "Nije moguće postaviti datum isteka. Datum isteka je u prošlosti",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Dijeljenje pozadine %s mora implementirati sučelje OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Dijeljenje pozadine %s nije nađeno",
+ "Sharing backend for %s not found" : "Dijeljenje pozadine za %s nije nađeno",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Dijeljenje %s nije uspjelo jer dozvole premašuju dozvole za koje %s ima odobrenje.",
+ "Sharing %s failed, because resharing is not allowed" : "Dijeljenje %s nije uspjelo jer ponovno dijeljenje nije dopušteno.",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Dijeljenje %s nije uspjelo jer pozadina za %s nije mogla pronaći svoj izvor",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Dijeljenje %s nije uspjelo jer u predmemoriji datoteke datoteka nije nađena.",
+ "%s shared »%s« with you" : "%s je s vama podijelio »%s«",
+ "Could not find category \"%s\"" : "Kategorija \"%s\" nije nađena",
+ "A valid username must be provided" : "Nužno je navesti ispravno korisničko ime",
+ "A valid password must be provided" : "Nužno je navesti ispravnu lozinku",
+ "The username is already being used" : "Korisničko ime se već koristi",
+ "Application is not enabled" : "Aplikacija nije aktivirana",
+ "Authentication error" : "Pogrešna autentikacija",
+ "Token expired. Please reload page." : "Token je istekao. Molimo, ponovno učitajte stranicu.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Pogonski programi baze podataka (sqlite, mysql, ili postgresql) nisu instalirani.",
+ "Cannot write into \"config\" directory" : "Nije moguće zapisivati u \"config\" direktorij",
+ "Cannot write into \"apps\" directory" : "Nije moguće zapisivati u \"apps\" direktorij",
+ "Setting locale to %s failed" : "Postavljanje regionalne sheme u %s nije uspjelo",
+ "Please install one of these locales on your system and restart your webserver." : "Molimo instalirajte jednu od ovih regionalnih shema u svoj sustav i ponovno pokrenite svoj web poslužitelj.",
+ "Please ask your server administrator to install the module." : "Molimo zamolite svog administratora poslužitelja da instalira modul.",
+ "PHP module %s not installed." : "PHP modul %s nije instaliran.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Uzrok tome je vjerojatno neki ubrzivač predmemoriranja kao što je Zend OPcache ilieAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "PHP moduli su instalirani, ali još uvijek su na popisu onih koji nedostaju?",
+ "Please ask your server administrator to restart the web server." : "Molimo zamolite svog administratora poslužitelja da ponovno pokrene web poslužitelj.",
+ "PostgreSQL >= 9 required" : "Potreban je PostgreSQL >= 9",
+ "Please upgrade your database version" : "Molimo, ažurirajte svoju verziju baze podataka",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Molimo promijenite dozvole na 0770 tako da se tim direktorijem ne mogu služiti drugi korisnici",
+ "Could not obtain lock type %d on \"%s\"." : "Nije moguće dobiti lock tip %d na \"%s\"."
+},
+"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;");
diff --git a/lib/l10n/hr.json b/lib/l10n/hr.json
new file mode 100644
index 00000000000..2cc8e0c3f4f
--- /dev/null
+++ b/lib/l10n/hr.json
@@ -0,0 +1,80 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Pisanje u \"config\" direktoriju nije moguće!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Ovo se obično može popraviti tako da se Web poslužitelju dopusti pristup za pisanje u config direktoriju",
+ "See %s" : "Vidite %s",
+ "Sample configuration detected" : "Nađena ogledna konfiguracija",
+ "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" : "Otkriveno je da je ogledna konfiguracija kopirana. To može vašu instalaciju prekinuti i nije podržano.Molimo pročitajte dokumentaciju prije nego li izvršite promjene na config.php",
+ "PHP %s or higher is required." : "PHP verzija treba biti %s ili viša.",
+ "PHP with a version lower than %s is required." : "PHP sa verzijom manjom od %s je potrebna.",
+ "Following databases are supported: %s" : "Sljedece baza podataka je podrzana: %s",
+ "The library %s is not available." : "Knjiznica %s nije dostupna.",
+ "Following platforms are supported: %s" : "Sljedece platforme su podrzane: %s",
+ "Unknown filetype" : "Vrsta datoteke nepoznata",
+ "Invalid image" : "Neispravna slika",
+ "today" : "Danas",
+ "yesterday" : "Jučer",
+ "last month" : "Prošli mjesec",
+ "_%n month ago_::_%n months ago_" : ["prije %n mjeseca","prije %n mjeseci","prije %n mjeseci"],
+ "last year" : "Prošle godine",
+ "_%n hour ago_::_%n hours ago_" : ["prije %n sata","prije %n sati","prije %n sati"],
+ "_%n minute ago_::_%n minutes ago_" : ["prije %n minute","prije %n minuta","prije %n minuta"],
+ "seconds ago" : "prije par sekundi",
+ "__language_name__" : "Hrvatski",
+ "Apps" : "Aplikacije",
+ "Users" : "Korisnici",
+ "Unknown user" : "Korisnik nepoznat",
+ "%s enter the database username." : "%s unesite naziva korisnika baze podataka.",
+ "%s enter the database name." : "%s unesite naziv baze podataka",
+ "%s you may not use dots in the database name" : "%s ne smijete koristiti točke u nazivu baze podataka",
+ "Oracle connection could not be established" : "Vezu Oracle nije moguće uspostaviti",
+ "Oracle username and/or password not valid" : "Korisničko ime i/ili lozinka Oracle neispravni",
+ "PostgreSQL username and/or password not valid" : "Korisničko ime i/ili lozinka PostgreSQL neispravni",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nije podržan i %s na ovoj platformi neće raditi kako treba.",
+ "For the best results, please consider using a GNU/Linux server instead." : "Za najbolje rezultate, molimo razmotrite mogućnost korištenje poslužitelja GNU/Linux.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Molimo uklonite postavke za open_basedir setting iz datoteke php.ini ili se prebacite na 64-bitni PHP.",
+ "Set an admin username." : "Navedite admin korisničko ime.",
+ "Set an admin password." : "Navedite admin lozinku.",
+ "Can't create or write into the data directory %s" : "Ne moze se kreirati ili napisati u imenik podataka %s",
+ "Sharing %s failed, because the file does not exist" : "Dijeljenje %s nije uspjelo jer ta datoteka ne postoji",
+ "You are not allowed to share %s" : "Nije vam dopušteno dijeliti %s",
+ "Sharing %s failed, because the user %s does not exist" : "Dijeljenje %s nije uspjelo jer korisnik %s ne postoji",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Dijeljenje %s nije uspjelo jer korisnik %s nije član niti jedne grupe u kojoj je %s član",
+ "Sharing %s failed, because this item is already shared with %s" : "Dijeljenje %s nije uspjelo jer je ova stavka već podijeljena s %s",
+ "Sharing %s failed, because the group %s does not exist" : "Dijeljenje %s nije uspjelo jer grupa %s ne postoji",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Dijeljenje %s nije uspjelo jer %s nije član grupe %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Da biste kreirali javnu vezu, morate navesti lozinku, samo zaštićene veze su dopuštene.",
+ "Sharing %s failed, because sharing with links is not allowed" : "Dijeljenje %s nije uspjelo jer dijeljenje s vezama nije dopušteno.",
+ "Share type %s is not valid for %s" : "Tip dijeljenja %s nije dopušteni tip za %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Nije moguće postaviti datum isteka. Nakon što su podijeljeni, resursi ne mogu isteći kasnije nego %s ",
+ "Cannot set expiration date. Expiration date is in the past" : "Nije moguće postaviti datum isteka. Datum isteka je u prošlosti",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Dijeljenje pozadine %s mora implementirati sučelje OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Dijeljenje pozadine %s nije nađeno",
+ "Sharing backend for %s not found" : "Dijeljenje pozadine za %s nije nađeno",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Dijeljenje %s nije uspjelo jer dozvole premašuju dozvole za koje %s ima odobrenje.",
+ "Sharing %s failed, because resharing is not allowed" : "Dijeljenje %s nije uspjelo jer ponovno dijeljenje nije dopušteno.",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Dijeljenje %s nije uspjelo jer pozadina za %s nije mogla pronaći svoj izvor",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Dijeljenje %s nije uspjelo jer u predmemoriji datoteke datoteka nije nađena.",
+ "%s shared »%s« with you" : "%s je s vama podijelio »%s«",
+ "Could not find category \"%s\"" : "Kategorija \"%s\" nije nađena",
+ "A valid username must be provided" : "Nužno je navesti ispravno korisničko ime",
+ "A valid password must be provided" : "Nužno je navesti ispravnu lozinku",
+ "The username is already being used" : "Korisničko ime se već koristi",
+ "Application is not enabled" : "Aplikacija nije aktivirana",
+ "Authentication error" : "Pogrešna autentikacija",
+ "Token expired. Please reload page." : "Token je istekao. Molimo, ponovno učitajte stranicu.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Pogonski programi baze podataka (sqlite, mysql, ili postgresql) nisu instalirani.",
+ "Cannot write into \"config\" directory" : "Nije moguće zapisivati u \"config\" direktorij",
+ "Cannot write into \"apps\" directory" : "Nije moguće zapisivati u \"apps\" direktorij",
+ "Setting locale to %s failed" : "Postavljanje regionalne sheme u %s nije uspjelo",
+ "Please install one of these locales on your system and restart your webserver." : "Molimo instalirajte jednu od ovih regionalnih shema u svoj sustav i ponovno pokrenite svoj web poslužitelj.",
+ "Please ask your server administrator to install the module." : "Molimo zamolite svog administratora poslužitelja da instalira modul.",
+ "PHP module %s not installed." : "PHP modul %s nije instaliran.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Uzrok tome je vjerojatno neki ubrzivač predmemoriranja kao što je Zend OPcache ilieAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "PHP moduli su instalirani, ali još uvijek su na popisu onih koji nedostaju?",
+ "Please ask your server administrator to restart the web server." : "Molimo zamolite svog administratora poslužitelja da ponovno pokrene web poslužitelj.",
+ "PostgreSQL >= 9 required" : "Potreban je PostgreSQL >= 9",
+ "Please upgrade your database version" : "Molimo, ažurirajte svoju verziju baze podataka",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Molimo promijenite dozvole na 0770 tako da se tim direktorijem ne mogu služiti drugi korisnici",
+ "Could not obtain lock type %d on \"%s\"." : "Nije moguće dobiti lock tip %d na \"%s\"."
+},"pluralForm" :"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;"
+} \ No newline at end of file
diff --git a/lib/l10n/hu.js b/lib/l10n/hu.js
index d4a5c3ee1ee..60c3c21b089 100644
--- a/lib/l10n/hu.js
+++ b/lib/l10n/hu.js
@@ -27,6 +27,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Ezek a platformok támogatottak: %s",
"Server version %s or higher is required." : "%s vagy újabb szerver verzió szükséges.",
"Server version %s or lower is required." : "%s vagy régebbi szerver verzió szükséges.",
+ "Logged in user must be an admin" : "Adminnak kell bejelentkeznie",
"Unknown filetype" : "Ismeretlen fájl típus",
"Invalid image" : "Hibás kép",
"Avatar image is not square" : "Az avatár kép nem négyzetes.",
@@ -57,6 +58,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Üres fájlnév nem engedétlyezett",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "\"%s\" alkalmazás nem lehet telepíteni, mert az appinfo fájl nem olvasható.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "\"%s\" alkalmazás nem lehet telepíteni, mert nem kompatibilis a szerver jelen verziójával.",
+ "__language_name__" : "Magyar",
"This is an automatically sent email, please do not reply." : "Ez egy automatikusan küldött levél, kérlek ne válaszolj rá.",
"Help" : "Súgó",
"Apps" : "Alkalmazások",
@@ -64,18 +66,17 @@ OC.L10N.register(
"Log out" : "Kijelentkezés",
"Users" : "Felhasználók",
"Unknown user" : "Ismeretlen felhasználó",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Létrehozás",
+ "Change" : "Változtatás",
+ "Delete" : "Törlés",
+ "Share" : "Megosztás",
"Basic settings" : "Alapvető beállítások",
"Sharing" : "Megosztás",
"Security" : "Biztonság",
"Encryption" : "Titkosítás",
"Additional settings" : "További beállítások",
- "Tips & tricks" : "Tippek és trükkök",
"Personal info" : "Személyes információk",
- "Sync clients" : "Szinkronizálási kliensek",
"Unlimited" : "Korlátlan",
- "__language_name__" : "__language_name__",
"Verifying" : "Ellenőrzés",
"Verifying …" : "Ellenőrzés...",
"Verify" : "Ellenőrzés",
@@ -227,6 +228,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "A tároló beállítása nem teljes. %s",
"Storage connection error. %s" : "Tároló kapcsolódási hiba. %s",
"Storage is temporarily not available" : "A tároló átmenetileg nem érthető el",
- "Storage connection timeout. %s" : "Tároló kapcsolat időtúllépés. %s"
+ "Storage connection timeout. %s" : "Tároló kapcsolat időtúllépés. %s",
+ "Personal" : "Személyes",
+ "Admin" : "Adminisztrátor",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tippek és trükkök",
+ "DB Error: \"%s\"" : "Adatbázis hiba: \"%s\"",
+ "Offending command was: \"%s\"" : "A hibát ez a parancs okozta: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "A hibát okozó parancs ez volt: \"%s\", login név: %s, jelszó: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Nem sikerült %s-re beállítani az elérési jogosultságokat, mert a megadottak túllépik a %s-re érvényes jogosultságokat",
+ "Setting permissions for %s failed, because the item was not found" : "Nem sikerült %s-re beállítani az elérési jogosultságokat, mert a kérdéses fájl nem található",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Nem lehet beállítani a lejárati időt. A megosztásoknak kötelező megadni lejárati időt!",
+ "Cannot increase permissions of %s" : "%s jogosultságait nem lehet megemelni",
+ "Files can't be shared with delete permissions" : "A fájlokat nem lehet megosztani a törlési jogosultságokkal",
+ "Files can't be shared with create permissions" : "A fájlokat nem lehet megosztani a létrehozási jogosultságokkal",
+ "Cannot set expiration date more than %s days in the future" : "%s napnál távolabbi lejárati dátumot nem lehet beállítani",
+ "No app name specified" : "Nincs az alkalmazás név megadva.",
+ "App '%s' could not be installed!" : "\"%s\" alkalmazás nem lehet telepíthető!",
+ "Sync clients" : "Szinkronizálási kliensek"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/hu.json b/lib/l10n/hu.json
index 142469e54b3..42e219a11f5 100644
--- a/lib/l10n/hu.json
+++ b/lib/l10n/hu.json
@@ -25,6 +25,7 @@
"Following platforms are supported: %s" : "Ezek a platformok támogatottak: %s",
"Server version %s or higher is required." : "%s vagy újabb szerver verzió szükséges.",
"Server version %s or lower is required." : "%s vagy régebbi szerver verzió szükséges.",
+ "Logged in user must be an admin" : "Adminnak kell bejelentkeznie",
"Unknown filetype" : "Ismeretlen fájl típus",
"Invalid image" : "Hibás kép",
"Avatar image is not square" : "Az avatár kép nem négyzetes.",
@@ -55,6 +56,7 @@
"Empty filename is not allowed" : "Üres fájlnév nem engedétlyezett",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "\"%s\" alkalmazás nem lehet telepíteni, mert az appinfo fájl nem olvasható.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "\"%s\" alkalmazás nem lehet telepíteni, mert nem kompatibilis a szerver jelen verziójával.",
+ "__language_name__" : "Magyar",
"This is an automatically sent email, please do not reply." : "Ez egy automatikusan küldött levél, kérlek ne válaszolj rá.",
"Help" : "Súgó",
"Apps" : "Alkalmazások",
@@ -62,18 +64,17 @@
"Log out" : "Kijelentkezés",
"Users" : "Felhasználók",
"Unknown user" : "Ismeretlen felhasználó",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Létrehozás",
+ "Change" : "Változtatás",
+ "Delete" : "Törlés",
+ "Share" : "Megosztás",
"Basic settings" : "Alapvető beállítások",
"Sharing" : "Megosztás",
"Security" : "Biztonság",
"Encryption" : "Titkosítás",
"Additional settings" : "További beállítások",
- "Tips & tricks" : "Tippek és trükkök",
"Personal info" : "Személyes információk",
- "Sync clients" : "Szinkronizálási kliensek",
"Unlimited" : "Korlátlan",
- "__language_name__" : "__language_name__",
"Verifying" : "Ellenőrzés",
"Verifying …" : "Ellenőrzés...",
"Verify" : "Ellenőrzés",
@@ -225,6 +226,24 @@
"Storage incomplete configuration. %s" : "A tároló beállítása nem teljes. %s",
"Storage connection error. %s" : "Tároló kapcsolódási hiba. %s",
"Storage is temporarily not available" : "A tároló átmenetileg nem érthető el",
- "Storage connection timeout. %s" : "Tároló kapcsolat időtúllépés. %s"
+ "Storage connection timeout. %s" : "Tároló kapcsolat időtúllépés. %s",
+ "Personal" : "Személyes",
+ "Admin" : "Adminisztrátor",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tippek és trükkök",
+ "DB Error: \"%s\"" : "Adatbázis hiba: \"%s\"",
+ "Offending command was: \"%s\"" : "A hibát ez a parancs okozta: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "A hibát okozó parancs ez volt: \"%s\", login név: %s, jelszó: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Nem sikerült %s-re beállítani az elérési jogosultságokat, mert a megadottak túllépik a %s-re érvényes jogosultságokat",
+ "Setting permissions for %s failed, because the item was not found" : "Nem sikerült %s-re beállítani az elérési jogosultságokat, mert a kérdéses fájl nem található",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Nem lehet beállítani a lejárati időt. A megosztásoknak kötelező megadni lejárati időt!",
+ "Cannot increase permissions of %s" : "%s jogosultságait nem lehet megemelni",
+ "Files can't be shared with delete permissions" : "A fájlokat nem lehet megosztani a törlési jogosultságokkal",
+ "Files can't be shared with create permissions" : "A fájlokat nem lehet megosztani a létrehozási jogosultságokkal",
+ "Cannot set expiration date more than %s days in the future" : "%s napnál távolabbi lejárati dátumot nem lehet beállítani",
+ "No app name specified" : "Nincs az alkalmazás név megadva.",
+ "App '%s' could not be installed!" : "\"%s\" alkalmazás nem lehet telepíthető!",
+ "Sync clients" : "Szinkronizálási kliensek"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/hy.js b/lib/l10n/hy.js
new file mode 100644
index 00000000000..e23c4d99ad6
--- /dev/null
+++ b/lib/l10n/hy.js
@@ -0,0 +1,9 @@
+OC.L10N.register(
+ "lib",
+ {
+ "today" : "այսօր",
+ "seconds ago" : "վրկ. առաջ",
+ "File name contains at least one invalid character" : "Ֆայլի անունը առնվազն մի անվավեր նիշ է պարունակում",
+ "__language_name__" : "Հայերեն"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/hy.json b/lib/l10n/hy.json
new file mode 100644
index 00000000000..5d34089f62f
--- /dev/null
+++ b/lib/l10n/hy.json
@@ -0,0 +1,7 @@
+{ "translations": {
+ "today" : "այսօր",
+ "seconds ago" : "վրկ. առաջ",
+ "File name contains at least one invalid character" : "Ֆայլի անունը առնվազն մի անվավեր նիշ է պարունակում",
+ "__language_name__" : "Հայերեն"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/id.js b/lib/l10n/id.js
new file mode 100644
index 00000000000..a543a03b697
--- /dev/null
+++ b/lib/l10n/id.js
@@ -0,0 +1,130 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Tidak dapat menulis kedalam direktori \"config\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Hal ini biasanya dapat diperbaiki dengan memberikan akses tulis bagi situs web ke direktori config",
+ "See %s" : "Lihat %s",
+ "Sample configuration detected" : "Konfigurasi sampel ditemukan",
+ "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" : "Ditemukan bahwa konfigurasi sampel telah disalin. Hal ini dapat merusak instalasi Anda dan tidak didukung. Silahkan baca dokumentasi sebelum melakukan perubahan pada config.php",
+ "PHP %s or higher is required." : "Diperlukan PHP %s atau yang lebih tinggi.",
+ "PHP with a version lower than %s is required." : "Diperlukan PHP dengan versi yang lebh rendah dari %s.",
+ "%sbit or higher PHP required." : "PHP %sbit atau yang lebih tinggi diperlukan.",
+ "Following databases are supported: %s" : "Berikut adalah basis data yang didukung: %s",
+ "The command line tool %s could not be found" : "Alat baris perintah %s tidak ditemukan",
+ "The library %s is not available." : "Pustaka %s tidak tersedia.",
+ "Library %s with a version higher than %s is required - available version %s." : "Diperlukan pustaka %s dengan versi yang lebih tinggi dari %s - versi yang tersedia %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "Diperlukan pustaka %s dengan versi yang lebih rendah dari %s - versi yang tersedia %s.",
+ "Following platforms are supported: %s" : "Berikut adalah platform yang didukung: %s",
+ "Server version %s or higher is required." : "Server versi %s atau yang lebih tinggi diperlukan.",
+ "Server version %s or lower is required." : "Server versi %s atau yang lebih rendah diperlukan.",
+ "Unknown filetype" : "Tipe berkas tak dikenal",
+ "Invalid image" : "Gambar tidak sah",
+ "today" : "hari ini",
+ "yesterday" : "kemarin",
+ "_%n day ago_::_%n days ago_" : ["%n hari yang lalu"],
+ "last month" : "bulan kemarin",
+ "_%n month ago_::_%n months ago_" : ["%n bulan yang lalu"],
+ "last year" : "tahun kemarin",
+ "_%n year ago_::_%n years ago_" : ["%n tahun yang lalu"],
+ "_%n hour ago_::_%n hours ago_" : ["%n jam yang lalu"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n menit yang lalu"],
+ "seconds ago" : "beberapa detik yang lalu",
+ "File name is a reserved word" : "Nama berkas merupakan kata yang disediakan",
+ "File name contains at least one invalid character" : "Nama berkas berisi setidaknya satu karakter yang tidak sah.",
+ "File name is too long" : "Nama berkas terlalu panjang",
+ "Dot files are not allowed" : "Berkas titik tidak diperbolehkan",
+ "Empty filename is not allowed" : "Nama berkas kosong tidak diperbolehkan",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "Aplikasi \"%s\" tidak dapat dipasang karena berkas appinfo tidak dapat dibaca.",
+ "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Aplikasi \"%s\" tidak dapat dipasang karena tidak kompatibel dengan versi server ini",
+ "__language_name__" : "Bahasa Indonesia",
+ "Help" : "Bantuan",
+ "Apps" : "aplikasi",
+ "Log out" : "Keluar",
+ "Users" : "Pengguna",
+ "Unknown user" : "Pengguna tidak dikenal",
+ "%s enter the database username and name." : "%s masukkan nama pengguna database dan nama database.",
+ "%s enter the database username." : "%s masukkan nama pengguna basis data.",
+ "%s enter the database name." : "%s masukkan nama basis data.",
+ "%s you may not use dots in the database name" : "%s anda tidak boleh menggunakan karakter titik pada nama basis data",
+ "Oracle connection could not be established" : "Koneksi Oracle tidak dapat dibuat",
+ "Oracle username and/or password not valid" : "Nama pengguna dan/atau kata sandi Oracle tidak sah",
+ "PostgreSQL username and/or password not valid" : "Nama pengguna dan/atau kata sandi PostgreSQL tidak valid",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X tidak didukung dan %s tidak akan bekerja dengan baik pada platform ini. Gunakan dengan resiko Anda sendiri!",
+ "For the best results, please consider using a GNU/Linux server instead." : "Untuk hasil terbaik, pertimbangkan untuk menggunakan server GNU/Linux sebagai gantinya. ",
+ "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." : "Kelihatannya instansi %s ini berjalan di lingkungan PHP 32-bit dan open_basedir telah dikonfigurasi di php.ini. Hal ini akan menyebabkan masalah dengan berkas lebih dari 4 GB dan sangat tidak disarankan.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Mohon hapus pengaturan open_basedir didalam php.ini atau beralih ke PHP 64-bit.",
+ "Set an admin username." : "Tetapkan nama pengguna admin.",
+ "Set an admin password." : "Tetapkan kata sandi admin.",
+ "Can't create or write into the data directory %s" : "Tidak dapat membuat atau menulis kedalam direktori data %s",
+ "Invalid Federated Cloud ID" : "Federated Cloud ID tidak sah",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "Gagal berbagi %s, karena backend tidak mengizinkan berbagi dengan tipe %i",
+ "Sharing %s failed, because the file does not exist" : "Gagal membagikan %s, karena berkas tidak ada",
+ "You are not allowed to share %s" : "Anda tidak diizinkan untuk membagikan %s",
+ "Sharing %s failed, because you can not share with yourself" : "Berbagi %s gagal, karena Anda tidak dapat berbagi dengan diri sendiri",
+ "Sharing %s failed, because the user %s does not exist" : "Gagal membagikan %s, karena pengguna %s tidak ada",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Gagal membagikan %s, karena pengguna %s bukan merupakan anggota dari grup yang %s ikuti",
+ "Sharing %s failed, because this item is already shared with %s" : "Gagal membagkan %s, karena item ini sudah dibagikan dengan %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "Berbagi %s gagal karena item ini sudah dibagikan dengan pengguna %s",
+ "Sharing %s failed, because the group %s does not exist" : "Gagal membagikan %s, karena grup %s tidak ada",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Gagal membagikan %s, karena %s bukan anggota dari grup %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Anda perlu memberikan kata sandi untuk membuat tautan publik, hanya tautan yang terlindungi yang diizinkan",
+ "Sharing %s failed, because sharing with links is not allowed" : "Gagal membagikan %s, karena berbag dengan tautan tidak diizinkan",
+ "Not allowed to create a federated share with the same user" : "Tidak diizinkan membuat pembagian terfederasi dengan pengguna yang sama",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Berbagi %s gagal, tidak menemukan %s, kemungkinan saat ini server tidak dapat dijangkau.",
+ "Share type %s is not valid for %s" : "Barbagi tipe %s tidak sah untuk %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Tidak dapat menyetel tanggal kadaluarsa. Pembagian tidak dapat kadaluarsa lebih lambat dari %s setelah mereka dibagikan.",
+ "Cannot set expiration date. Expiration date is in the past" : "Tidak dapat menyetel tanggal kadaluarsa. Tanggal kadaluarsa dimasa lalu",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Backend berbagi %s harus mengimplementasi antarmuka OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Backend berbagi %s tidak ditemukan",
+ "Sharing backend for %s not found" : "Backend berbagi untuk %s tidak ditemukan",
+ "Sharing failed, because the user %s is the original sharer" : "Berbagi gagal, karena pengguna %s adalah pembagi awal",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Gagal membagikan %s, karena izin melebihi izin yang diberikan untuk %s",
+ "Sharing %s failed, because resharing is not allowed" : "Gagal berbagi %s, karena membagikan ulang tidak diizinkan",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Berbagi %s gagal, karena backend berbagi untuk %s tidak menemukan sumbernya",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Gagal berbagi %s, karena berkas tidak ditemukan di berkas cache",
+ "Expiration date is in the past" : "Tanggal kedaluwarsa sudah lewat",
+ "%s shared »%s« with you" : "%s membagikan »%s« dengan anda",
+ "%s via %s" : "%s melalui %s",
+ "Could not find category \"%s\"" : "Tidak menemukan kategori \"%s\"",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Hanya karakter ini yang diizinkan dalam nama pengguna: \"a-z\", \"A-Z\", \"0-9\", dan \"_.@-'\"",
+ "A valid username must be provided" : "Tuliskan nama pengguna yang valid",
+ "Username contains whitespace at the beginning or at the end" : "Nama pengguna mengandung spasi di depan atau di belakang.",
+ "A valid password must be provided" : "Tuliskan kata sandi yang valid",
+ "The username is already being used" : "Nama pengguna ini telah digunakan",
+ "User disabled" : "Pengguna dinonaktifkan",
+ "Login canceled by app" : "Log masuk dibatalkan oleh aplikasi",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "aplikasi \"%s\" tidak dapat dipasang karena dependensi berikut belum terpenuhi: %s",
+ "a safe home for all your data" : "rumah yang aman untuk semua datamu",
+ "File is currently busy, please try again later" : "Berkas sedang sibuk, mohon coba lagi nanti",
+ "Can't read file" : "Tidak dapat membaca berkas",
+ "Application is not enabled" : "aplikasi tidak diaktifkan",
+ "Authentication error" : "Galat saat otentikasi",
+ "Token expired. Please reload page." : "Token sudah kedaluwarsa. Silakan muat ulang halaman.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Tidak ada driver (sqlite, mysql, or postgresql) yang terinstal.",
+ "Cannot write into \"config\" directory" : "Tidak dapat menulis kedalam direktori \"config\"",
+ "Cannot write into \"apps\" directory" : "Tidak dapat menulis kedalam direktori \"apps\"",
+ "Setting locale to %s failed" : "Pengaturan lokal ke %s gagal",
+ "Please install one of these locales on your system and restart your webserver." : "Mohon instal paling tidak satu lokal pada sistem Anda dan jalankan ulang server web.",
+ "Please ask your server administrator to install the module." : "Mohon tanyakan administrator Anda untuk menginstal module.",
+ "PHP module %s not installed." : "Module PHP %s tidak terinstal.",
+ "PHP setting \"%s\" is not set to \"%s\"." : "Pengaturan PHP \"%s\" tidak diatur ke \"%s\".",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "Menyesuaikan pengaturan ini di php.ini akan membuat Nextcloud berjalan kembali",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload diatur menjadi \"%s\" bukan nilai yang diharapkan \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Untuk memperbaiki masalah ini, atur <code>mbstring.func_overload</code> menjadi <code>0</code> pada berkas php.ini Anda",
+ "libxml2 2.7.0 is at least required. Currently %s is installed." : "Setidaknya libxml2 2.7.0 dibutuhkan. Saat ini %s dipasang.",
+ "To fix this issue update your libxml2 version and restart your web server." : "Untuk mengatasi masalah ini, perbarui versi libxml2 Anda dan mulai-ulang server web Anda.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "Tampaknya PHP diatur untuk memotong inline doc blocks. Hal ini akan menyebabkan beberapa aplikasi inti menjadi tidak dapat diakses.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Hal ini kemungkinan disebabkan oleh cache/akselerator seperti Zend OPcache atau eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "Modul PHP telah terinstal, tetapi mereka terlihat tidak ada?",
+ "Please ask your server administrator to restart the web server." : "Mohon minta administrator Anda untuk menjalankan ulang server web.",
+ "PostgreSQL >= 9 required" : "Diperlukan PostgreSQL >= 9",
+ "Please upgrade your database version" : "Mohon perbarui versi basis data Anda",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Mohon ubah perizinan menjadi 0770 sehingga direktori tersebut tidak dapat dilihat oleh pengguna lain.",
+ "Check the value of \"datadirectory\" in your configuration" : "Periksa nilai \"datadirectory\" di konfigurasi Anda",
+ "Could not obtain lock type %d on \"%s\"." : "Tidak bisa memperoleh jenis kunci %d pada \"%s\".",
+ "Storage unauthorized. %s" : "Penyimpanan tidak terotorisasi. %s",
+ "Storage incomplete configuration. %s" : "Konfigurasi penyimpanan tidak terselesaikan. %s",
+ "Storage connection error. %s" : "Koneksi penyimpanan bermasalah. %s",
+ "Storage connection timeout. %s" : "Koneksi penyimpanan waktu-habis. %s"
+},
+"nplurals=1; plural=0;");
diff --git a/lib/l10n/id.json b/lib/l10n/id.json
new file mode 100644
index 00000000000..16da7e0634a
--- /dev/null
+++ b/lib/l10n/id.json
@@ -0,0 +1,128 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Tidak dapat menulis kedalam direktori \"config\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Hal ini biasanya dapat diperbaiki dengan memberikan akses tulis bagi situs web ke direktori config",
+ "See %s" : "Lihat %s",
+ "Sample configuration detected" : "Konfigurasi sampel ditemukan",
+ "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" : "Ditemukan bahwa konfigurasi sampel telah disalin. Hal ini dapat merusak instalasi Anda dan tidak didukung. Silahkan baca dokumentasi sebelum melakukan perubahan pada config.php",
+ "PHP %s or higher is required." : "Diperlukan PHP %s atau yang lebih tinggi.",
+ "PHP with a version lower than %s is required." : "Diperlukan PHP dengan versi yang lebh rendah dari %s.",
+ "%sbit or higher PHP required." : "PHP %sbit atau yang lebih tinggi diperlukan.",
+ "Following databases are supported: %s" : "Berikut adalah basis data yang didukung: %s",
+ "The command line tool %s could not be found" : "Alat baris perintah %s tidak ditemukan",
+ "The library %s is not available." : "Pustaka %s tidak tersedia.",
+ "Library %s with a version higher than %s is required - available version %s." : "Diperlukan pustaka %s dengan versi yang lebih tinggi dari %s - versi yang tersedia %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "Diperlukan pustaka %s dengan versi yang lebih rendah dari %s - versi yang tersedia %s.",
+ "Following platforms are supported: %s" : "Berikut adalah platform yang didukung: %s",
+ "Server version %s or higher is required." : "Server versi %s atau yang lebih tinggi diperlukan.",
+ "Server version %s or lower is required." : "Server versi %s atau yang lebih rendah diperlukan.",
+ "Unknown filetype" : "Tipe berkas tak dikenal",
+ "Invalid image" : "Gambar tidak sah",
+ "today" : "hari ini",
+ "yesterday" : "kemarin",
+ "_%n day ago_::_%n days ago_" : ["%n hari yang lalu"],
+ "last month" : "bulan kemarin",
+ "_%n month ago_::_%n months ago_" : ["%n bulan yang lalu"],
+ "last year" : "tahun kemarin",
+ "_%n year ago_::_%n years ago_" : ["%n tahun yang lalu"],
+ "_%n hour ago_::_%n hours ago_" : ["%n jam yang lalu"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n menit yang lalu"],
+ "seconds ago" : "beberapa detik yang lalu",
+ "File name is a reserved word" : "Nama berkas merupakan kata yang disediakan",
+ "File name contains at least one invalid character" : "Nama berkas berisi setidaknya satu karakter yang tidak sah.",
+ "File name is too long" : "Nama berkas terlalu panjang",
+ "Dot files are not allowed" : "Berkas titik tidak diperbolehkan",
+ "Empty filename is not allowed" : "Nama berkas kosong tidak diperbolehkan",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "Aplikasi \"%s\" tidak dapat dipasang karena berkas appinfo tidak dapat dibaca.",
+ "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Aplikasi \"%s\" tidak dapat dipasang karena tidak kompatibel dengan versi server ini",
+ "__language_name__" : "Bahasa Indonesia",
+ "Help" : "Bantuan",
+ "Apps" : "aplikasi",
+ "Log out" : "Keluar",
+ "Users" : "Pengguna",
+ "Unknown user" : "Pengguna tidak dikenal",
+ "%s enter the database username and name." : "%s masukkan nama pengguna database dan nama database.",
+ "%s enter the database username." : "%s masukkan nama pengguna basis data.",
+ "%s enter the database name." : "%s masukkan nama basis data.",
+ "%s you may not use dots in the database name" : "%s anda tidak boleh menggunakan karakter titik pada nama basis data",
+ "Oracle connection could not be established" : "Koneksi Oracle tidak dapat dibuat",
+ "Oracle username and/or password not valid" : "Nama pengguna dan/atau kata sandi Oracle tidak sah",
+ "PostgreSQL username and/or password not valid" : "Nama pengguna dan/atau kata sandi PostgreSQL tidak valid",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X tidak didukung dan %s tidak akan bekerja dengan baik pada platform ini. Gunakan dengan resiko Anda sendiri!",
+ "For the best results, please consider using a GNU/Linux server instead." : "Untuk hasil terbaik, pertimbangkan untuk menggunakan server GNU/Linux sebagai gantinya. ",
+ "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." : "Kelihatannya instansi %s ini berjalan di lingkungan PHP 32-bit dan open_basedir telah dikonfigurasi di php.ini. Hal ini akan menyebabkan masalah dengan berkas lebih dari 4 GB dan sangat tidak disarankan.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Mohon hapus pengaturan open_basedir didalam php.ini atau beralih ke PHP 64-bit.",
+ "Set an admin username." : "Tetapkan nama pengguna admin.",
+ "Set an admin password." : "Tetapkan kata sandi admin.",
+ "Can't create or write into the data directory %s" : "Tidak dapat membuat atau menulis kedalam direktori data %s",
+ "Invalid Federated Cloud ID" : "Federated Cloud ID tidak sah",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "Gagal berbagi %s, karena backend tidak mengizinkan berbagi dengan tipe %i",
+ "Sharing %s failed, because the file does not exist" : "Gagal membagikan %s, karena berkas tidak ada",
+ "You are not allowed to share %s" : "Anda tidak diizinkan untuk membagikan %s",
+ "Sharing %s failed, because you can not share with yourself" : "Berbagi %s gagal, karena Anda tidak dapat berbagi dengan diri sendiri",
+ "Sharing %s failed, because the user %s does not exist" : "Gagal membagikan %s, karena pengguna %s tidak ada",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Gagal membagikan %s, karena pengguna %s bukan merupakan anggota dari grup yang %s ikuti",
+ "Sharing %s failed, because this item is already shared with %s" : "Gagal membagkan %s, karena item ini sudah dibagikan dengan %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "Berbagi %s gagal karena item ini sudah dibagikan dengan pengguna %s",
+ "Sharing %s failed, because the group %s does not exist" : "Gagal membagikan %s, karena grup %s tidak ada",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Gagal membagikan %s, karena %s bukan anggota dari grup %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Anda perlu memberikan kata sandi untuk membuat tautan publik, hanya tautan yang terlindungi yang diizinkan",
+ "Sharing %s failed, because sharing with links is not allowed" : "Gagal membagikan %s, karena berbag dengan tautan tidak diizinkan",
+ "Not allowed to create a federated share with the same user" : "Tidak diizinkan membuat pembagian terfederasi dengan pengguna yang sama",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Berbagi %s gagal, tidak menemukan %s, kemungkinan saat ini server tidak dapat dijangkau.",
+ "Share type %s is not valid for %s" : "Barbagi tipe %s tidak sah untuk %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Tidak dapat menyetel tanggal kadaluarsa. Pembagian tidak dapat kadaluarsa lebih lambat dari %s setelah mereka dibagikan.",
+ "Cannot set expiration date. Expiration date is in the past" : "Tidak dapat menyetel tanggal kadaluarsa. Tanggal kadaluarsa dimasa lalu",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Backend berbagi %s harus mengimplementasi antarmuka OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Backend berbagi %s tidak ditemukan",
+ "Sharing backend for %s not found" : "Backend berbagi untuk %s tidak ditemukan",
+ "Sharing failed, because the user %s is the original sharer" : "Berbagi gagal, karena pengguna %s adalah pembagi awal",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Gagal membagikan %s, karena izin melebihi izin yang diberikan untuk %s",
+ "Sharing %s failed, because resharing is not allowed" : "Gagal berbagi %s, karena membagikan ulang tidak diizinkan",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Berbagi %s gagal, karena backend berbagi untuk %s tidak menemukan sumbernya",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Gagal berbagi %s, karena berkas tidak ditemukan di berkas cache",
+ "Expiration date is in the past" : "Tanggal kedaluwarsa sudah lewat",
+ "%s shared »%s« with you" : "%s membagikan »%s« dengan anda",
+ "%s via %s" : "%s melalui %s",
+ "Could not find category \"%s\"" : "Tidak menemukan kategori \"%s\"",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Hanya karakter ini yang diizinkan dalam nama pengguna: \"a-z\", \"A-Z\", \"0-9\", dan \"_.@-'\"",
+ "A valid username must be provided" : "Tuliskan nama pengguna yang valid",
+ "Username contains whitespace at the beginning or at the end" : "Nama pengguna mengandung spasi di depan atau di belakang.",
+ "A valid password must be provided" : "Tuliskan kata sandi yang valid",
+ "The username is already being used" : "Nama pengguna ini telah digunakan",
+ "User disabled" : "Pengguna dinonaktifkan",
+ "Login canceled by app" : "Log masuk dibatalkan oleh aplikasi",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "aplikasi \"%s\" tidak dapat dipasang karena dependensi berikut belum terpenuhi: %s",
+ "a safe home for all your data" : "rumah yang aman untuk semua datamu",
+ "File is currently busy, please try again later" : "Berkas sedang sibuk, mohon coba lagi nanti",
+ "Can't read file" : "Tidak dapat membaca berkas",
+ "Application is not enabled" : "aplikasi tidak diaktifkan",
+ "Authentication error" : "Galat saat otentikasi",
+ "Token expired. Please reload page." : "Token sudah kedaluwarsa. Silakan muat ulang halaman.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Tidak ada driver (sqlite, mysql, or postgresql) yang terinstal.",
+ "Cannot write into \"config\" directory" : "Tidak dapat menulis kedalam direktori \"config\"",
+ "Cannot write into \"apps\" directory" : "Tidak dapat menulis kedalam direktori \"apps\"",
+ "Setting locale to %s failed" : "Pengaturan lokal ke %s gagal",
+ "Please install one of these locales on your system and restart your webserver." : "Mohon instal paling tidak satu lokal pada sistem Anda dan jalankan ulang server web.",
+ "Please ask your server administrator to install the module." : "Mohon tanyakan administrator Anda untuk menginstal module.",
+ "PHP module %s not installed." : "Module PHP %s tidak terinstal.",
+ "PHP setting \"%s\" is not set to \"%s\"." : "Pengaturan PHP \"%s\" tidak diatur ke \"%s\".",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "Menyesuaikan pengaturan ini di php.ini akan membuat Nextcloud berjalan kembali",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload diatur menjadi \"%s\" bukan nilai yang diharapkan \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Untuk memperbaiki masalah ini, atur <code>mbstring.func_overload</code> menjadi <code>0</code> pada berkas php.ini Anda",
+ "libxml2 2.7.0 is at least required. Currently %s is installed." : "Setidaknya libxml2 2.7.0 dibutuhkan. Saat ini %s dipasang.",
+ "To fix this issue update your libxml2 version and restart your web server." : "Untuk mengatasi masalah ini, perbarui versi libxml2 Anda dan mulai-ulang server web Anda.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "Tampaknya PHP diatur untuk memotong inline doc blocks. Hal ini akan menyebabkan beberapa aplikasi inti menjadi tidak dapat diakses.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Hal ini kemungkinan disebabkan oleh cache/akselerator seperti Zend OPcache atau eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "Modul PHP telah terinstal, tetapi mereka terlihat tidak ada?",
+ "Please ask your server administrator to restart the web server." : "Mohon minta administrator Anda untuk menjalankan ulang server web.",
+ "PostgreSQL >= 9 required" : "Diperlukan PostgreSQL >= 9",
+ "Please upgrade your database version" : "Mohon perbarui versi basis data Anda",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Mohon ubah perizinan menjadi 0770 sehingga direktori tersebut tidak dapat dilihat oleh pengguna lain.",
+ "Check the value of \"datadirectory\" in your configuration" : "Periksa nilai \"datadirectory\" di konfigurasi Anda",
+ "Could not obtain lock type %d on \"%s\"." : "Tidak bisa memperoleh jenis kunci %d pada \"%s\".",
+ "Storage unauthorized. %s" : "Penyimpanan tidak terotorisasi. %s",
+ "Storage incomplete configuration. %s" : "Konfigurasi penyimpanan tidak terselesaikan. %s",
+ "Storage connection error. %s" : "Koneksi penyimpanan bermasalah. %s",
+ "Storage connection timeout. %s" : "Koneksi penyimpanan waktu-habis. %s"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/lib/l10n/is.js b/lib/l10n/is.js
index e046a1454d6..c9beec4994d 100644
--- a/lib/l10n/is.js
+++ b/lib/l10n/is.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Autt skráarheiti er ekki leyft.",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Ekki er hægt að setja upp \"%s\" forritið vegna þess að ekki var hægt að lesa appinfo-skrána.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Ekki var hægt að setja upp forritið \"%s\" vegna þess að það er ekki samhæft þessari útgáfu vefþjónsins.",
+ "__language_name__" : "Íslenska",
"This is an automatically sent email, please do not reply." : "Þetta er sjálfvirk tölvupóstsending, ekki svara þessu.",
"Help" : "Hjálp",
"Apps" : "Forrit",
@@ -64,18 +65,13 @@ OC.L10N.register(
"Log out" : "Skrá út",
"Users" : "Notendur",
"Unknown user" : "Óþekktur notandi",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Grunnstillingar",
"Sharing" : "Deiling",
"Security" : "Öryggi",
"Encryption" : "Dulritun",
"Additional settings" : "Valfrjálsar stillingar",
- "Tips & tricks" : "Ábendingar og góð ráð",
"Personal info" : "Persónulegar upplýsingar",
- "Sync clients" : "Samstilla biðlara",
"Unlimited" : "Ótakmarkað",
- "__language_name__" : "Íslenska",
"Verifying" : "Sannreyni",
"Verifying …" : "Sannreyni …",
"Verify" : "Sannreyna",
@@ -227,6 +223,10 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Ófullgerð uppsetning gagnageymslu. %s",
"Storage connection error. %s" : "Villa í tengingu við gagnageymslu. %s",
"Storage is temporarily not available" : "Gagnageymsla ekki tiltæk í augnablikinu",
- "Storage connection timeout. %s" : "Gagnageymsla féll á tíma. %s"
+ "Storage connection timeout. %s" : "Gagnageymsla féll á tíma. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Ábendingar og góð ráð",
+ "Sync clients" : "Samstilla biðlara"
},
"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);");
diff --git a/lib/l10n/is.json b/lib/l10n/is.json
index 5c93e82dc00..bf7eea16be6 100644
--- a/lib/l10n/is.json
+++ b/lib/l10n/is.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "Autt skráarheiti er ekki leyft.",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Ekki er hægt að setja upp \"%s\" forritið vegna þess að ekki var hægt að lesa appinfo-skrána.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Ekki var hægt að setja upp forritið \"%s\" vegna þess að það er ekki samhæft þessari útgáfu vefþjónsins.",
+ "__language_name__" : "Íslenska",
"This is an automatically sent email, please do not reply." : "Þetta er sjálfvirk tölvupóstsending, ekki svara þessu.",
"Help" : "Hjálp",
"Apps" : "Forrit",
@@ -62,18 +63,13 @@
"Log out" : "Skrá út",
"Users" : "Notendur",
"Unknown user" : "Óþekktur notandi",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Grunnstillingar",
"Sharing" : "Deiling",
"Security" : "Öryggi",
"Encryption" : "Dulritun",
"Additional settings" : "Valfrjálsar stillingar",
- "Tips & tricks" : "Ábendingar og góð ráð",
"Personal info" : "Persónulegar upplýsingar",
- "Sync clients" : "Samstilla biðlara",
"Unlimited" : "Ótakmarkað",
- "__language_name__" : "Íslenska",
"Verifying" : "Sannreyni",
"Verifying …" : "Sannreyni …",
"Verify" : "Sannreyna",
@@ -225,6 +221,10 @@
"Storage incomplete configuration. %s" : "Ófullgerð uppsetning gagnageymslu. %s",
"Storage connection error. %s" : "Villa í tengingu við gagnageymslu. %s",
"Storage is temporarily not available" : "Gagnageymsla ekki tiltæk í augnablikinu",
- "Storage connection timeout. %s" : "Gagnageymsla féll á tíma. %s"
+ "Storage connection timeout. %s" : "Gagnageymsla féll á tíma. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Ábendingar og góð ráð",
+ "Sync clients" : "Samstilla biðlara"
},"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"
} \ No newline at end of file
diff --git a/lib/l10n/it.js b/lib/l10n/it.js
index f9c643e9164..f80a4e63354 100644
--- a/lib/l10n/it.js
+++ b/lib/l10n/it.js
@@ -4,7 +4,9 @@ OC.L10N.register(
"Cannot write into \"config\" directory!" : "Impossibile scrivere nella cartella \"config\"!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Ciò può essere normalmente corretto fornendo al server web accesso in scrittura alla cartella \"config\"",
"See %s" : "Vedi %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "O, se preferisci mantenere il file config.php in sola lettura, imposta l'opzione \"config_is_read_only\" a true.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ciò può essere normalmente corretto fornendo al server web accesso in scrittura alla cartella di configurazione. Vedi %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "O, se preferisci mantenere il file config.php in sola lettura, imposta l'opzione \"config_is_read_only\" a true. Vedi %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "I file dell'applicazione %1$s non sono stati sostituiti correttamente. Assicurati che sia una versione compatibile con il server.",
"Sample configuration detected" : "Configurazione di esempio rilevata",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "È stato rilevato che la configurazione di esempio è stata copiata. Ciò può compromettere la tua installazione e non è supportato. Leggi la documentazione prima di modificare il file config.php",
@@ -27,6 +29,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Sono supportate le seguenti piattaforme: %s",
"Server version %s or higher is required." : "È richiesta la versione %s o successiva.",
"Server version %s or lower is required." : "È richiesta la versione %s o precedente.",
+ "Logged in user must be an admin" : "L'utente che ha eseguito l'accesso deve essere un amministratore ",
"Unknown filetype" : "Tipo di file sconosciuto",
"Invalid image" : "Immagine non valida",
"Avatar image is not square" : "L'immagine personale non è quadrata",
@@ -57,6 +60,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Un nome di file vuoto non è consentito",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "L'applicazione \"%s\" non può essere installata poiché il file appinfo non può essere letto.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "L'applicazione \"%s\" non può essere installata perché non è compatibile con questa versione del server.",
+ "__language_name__" : "Italiano",
"This is an automatically sent email, please do not reply." : "Questo è un messaggio di posta inviato automaticamente, non rispondere.",
"Help" : "Aiuto",
"Apps" : "Applicazioni",
@@ -64,18 +68,20 @@ OC.L10N.register(
"Log out" : "Esci",
"Users" : "Utenti",
"Unknown user" : "Utente sconosciuto",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crea",
+ "Change" : "Modifica",
+ "Delete" : "Elimina",
+ "Share" : "Condividi",
+ "Overview" : "Riepilogo",
"Basic settings" : "Impostazioni di base",
"Sharing" : "Condivisione",
"Security" : "Sicurezza",
"Encryption" : "Cifratura",
+ "Groupware" : "Groupware",
"Additional settings" : "Impostazioni aggiuntive",
- "Tips & tricks" : "Suggerimenti e trucchi",
"Personal info" : "Informazioni personali",
- "Sync clients" : "Client di sincronizzazione",
+ "Mobile & desktop" : "Mobile e desktop",
"Unlimited" : "Illimitato",
- "__language_name__" : "Italiano",
"Verifying" : "Verifica",
"Verifying …" : "Verifica in corso...",
"Verify" : "Verifica",
@@ -222,6 +228,11 @@ OC.L10N.register(
"Check the value of \"datadirectory\" in your configuration" : "Controlla il valore di \"datadirectory\" nella tua configurazione",
"Your data directory is invalid" : "La cartella dei dati non è valida",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assicurati che ci sia un file \".ocdata\" nella radice della cartella data.",
+ "Action \"%s\" not supported or implemented." : "Azione \"%s\" non supportata o implementata.",
+ "Authentication failed, wrong token or provider ID given" : "Autenticazione non riuscita, token o ID fornitore errato ",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Parametri mancanti per completare la richiesta. Parametri mancanti: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "ID \"%s\" già utilizzato dal fornitore della federazione cloud \"%s\"",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Il fornitore della federazione cloud con ID: \"%s\" non esiste.",
"Could not obtain lock type %d on \"%s\"." : "Impossibile ottenere il blocco di tipo %d su \"%s\".",
"Storage unauthorized. %s" : "Archiviazione non autorizzata. %s",
"Storage incomplete configuration. %s" : "Configurazione dell'archiviazione incompleta.%s",
@@ -230,6 +241,9 @@ OC.L10N.register(
"Storage connection timeout. %s" : "Timeout di connessione all'archiviazione. %s",
"Personal" : "Personale",
"Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Suggerimenti e trucchi",
"DB Error: \"%s\"" : "Errore DB: \"%s\"",
"Offending command was: \"%s\"" : "Il comando non consentito era: \"%s\"",
"Offending command was: \"%s\", name: %s, password: %s" : "Il comando non consentito era: \"%s\", nome: %s, password: %s",
@@ -241,6 +255,7 @@ OC.L10N.register(
"Files can't be shared with create permissions" : "I file non possono essere condivisi con permessi di creazione",
"Cannot set expiration date more than %s days in the future" : "Impossibile impostare la data di scadenza a più di %s giorni nel futuro",
"No app name specified" : "Il nome dell'applicazione non è specificato",
- "App '%s' could not be installed!" : "L'applicazione '%s' non può essere installata!"
+ "App '%s' could not be installed!" : "L'applicazione '%s' non può essere installata!",
+ "Sync clients" : "Client di sincronizzazione"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/it.json b/lib/l10n/it.json
index 099ee47f9ff..14fd59ba701 100644
--- a/lib/l10n/it.json
+++ b/lib/l10n/it.json
@@ -2,7 +2,9 @@
"Cannot write into \"config\" directory!" : "Impossibile scrivere nella cartella \"config\"!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Ciò può essere normalmente corretto fornendo al server web accesso in scrittura alla cartella \"config\"",
"See %s" : "Vedi %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "O, se preferisci mantenere il file config.php in sola lettura, imposta l'opzione \"config_is_read_only\" a true.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ciò può essere normalmente corretto fornendo al server web accesso in scrittura alla cartella di configurazione. Vedi %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "O, se preferisci mantenere il file config.php in sola lettura, imposta l'opzione \"config_is_read_only\" a true. Vedi %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "I file dell'applicazione %1$s non sono stati sostituiti correttamente. Assicurati che sia una versione compatibile con il server.",
"Sample configuration detected" : "Configurazione di esempio rilevata",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "È stato rilevato che la configurazione di esempio è stata copiata. Ciò può compromettere la tua installazione e non è supportato. Leggi la documentazione prima di modificare il file config.php",
@@ -25,6 +27,7 @@
"Following platforms are supported: %s" : "Sono supportate le seguenti piattaforme: %s",
"Server version %s or higher is required." : "È richiesta la versione %s o successiva.",
"Server version %s or lower is required." : "È richiesta la versione %s o precedente.",
+ "Logged in user must be an admin" : "L'utente che ha eseguito l'accesso deve essere un amministratore ",
"Unknown filetype" : "Tipo di file sconosciuto",
"Invalid image" : "Immagine non valida",
"Avatar image is not square" : "L'immagine personale non è quadrata",
@@ -55,6 +58,7 @@
"Empty filename is not allowed" : "Un nome di file vuoto non è consentito",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "L'applicazione \"%s\" non può essere installata poiché il file appinfo non può essere letto.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "L'applicazione \"%s\" non può essere installata perché non è compatibile con questa versione del server.",
+ "__language_name__" : "Italiano",
"This is an automatically sent email, please do not reply." : "Questo è un messaggio di posta inviato automaticamente, non rispondere.",
"Help" : "Aiuto",
"Apps" : "Applicazioni",
@@ -62,18 +66,20 @@
"Log out" : "Esci",
"Users" : "Utenti",
"Unknown user" : "Utente sconosciuto",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Crea",
+ "Change" : "Modifica",
+ "Delete" : "Elimina",
+ "Share" : "Condividi",
+ "Overview" : "Riepilogo",
"Basic settings" : "Impostazioni di base",
"Sharing" : "Condivisione",
"Security" : "Sicurezza",
"Encryption" : "Cifratura",
+ "Groupware" : "Groupware",
"Additional settings" : "Impostazioni aggiuntive",
- "Tips & tricks" : "Suggerimenti e trucchi",
"Personal info" : "Informazioni personali",
- "Sync clients" : "Client di sincronizzazione",
+ "Mobile & desktop" : "Mobile e desktop",
"Unlimited" : "Illimitato",
- "__language_name__" : "Italiano",
"Verifying" : "Verifica",
"Verifying …" : "Verifica in corso...",
"Verify" : "Verifica",
@@ -220,6 +226,11 @@
"Check the value of \"datadirectory\" in your configuration" : "Controlla il valore di \"datadirectory\" nella tua configurazione",
"Your data directory is invalid" : "La cartella dei dati non è valida",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assicurati che ci sia un file \".ocdata\" nella radice della cartella data.",
+ "Action \"%s\" not supported or implemented." : "Azione \"%s\" non supportata o implementata.",
+ "Authentication failed, wrong token or provider ID given" : "Autenticazione non riuscita, token o ID fornitore errato ",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Parametri mancanti per completare la richiesta. Parametri mancanti: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "ID \"%s\" già utilizzato dal fornitore della federazione cloud \"%s\"",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Il fornitore della federazione cloud con ID: \"%s\" non esiste.",
"Could not obtain lock type %d on \"%s\"." : "Impossibile ottenere il blocco di tipo %d su \"%s\".",
"Storage unauthorized. %s" : "Archiviazione non autorizzata. %s",
"Storage incomplete configuration. %s" : "Configurazione dell'archiviazione incompleta.%s",
@@ -228,6 +239,9 @@
"Storage connection timeout. %s" : "Timeout di connessione all'archiviazione. %s",
"Personal" : "Personale",
"Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Suggerimenti e trucchi",
"DB Error: \"%s\"" : "Errore DB: \"%s\"",
"Offending command was: \"%s\"" : "Il comando non consentito era: \"%s\"",
"Offending command was: \"%s\", name: %s, password: %s" : "Il comando non consentito era: \"%s\", nome: %s, password: %s",
@@ -239,6 +253,7 @@
"Files can't be shared with create permissions" : "I file non possono essere condivisi con permessi di creazione",
"Cannot set expiration date more than %s days in the future" : "Impossibile impostare la data di scadenza a più di %s giorni nel futuro",
"No app name specified" : "Il nome dell'applicazione non è specificato",
- "App '%s' could not be installed!" : "L'applicazione '%s' non può essere installata!"
+ "App '%s' could not be installed!" : "L'applicazione '%s' non può essere installata!",
+ "Sync clients" : "Client di sincronizzazione"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/ja.js b/lib/l10n/ja.js
index 09a95e318c1..7821322dd24 100644
--- a/lib/l10n/ja.js
+++ b/lib/l10n/ja.js
@@ -13,6 +13,9 @@ OC.L10N.register(
"%1$s, %2$s, %3$s and %4$s" : "%1$s と %2$s、%3$s、%4$s",
"%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s と %2$s、%3$s、%4$s、%5$s",
"Education Edition" : "Education Edition",
+ "Enterprise bundle" : "エンタープライズ バンドル",
+ "Groupware bundle" : "グループウェア バンドル",
+ "Social sharing bundle" : "SNS バンドル",
"PHP %s or higher is required." : "PHP %s 以上が必要です。",
"PHP with a version lower than %s is required." : "%s 以前のバージョンのPHPが必要です。",
"%sbit or higher PHP required." : "%sbit 以上の新しいバージョンのPHPが必要です。",
@@ -24,18 +27,28 @@ OC.L10N.register(
"Following platforms are supported: %s" : "次のプラットフォームをサポートしています: %s",
"Server version %s or higher is required." : "サーバーの %s よりも高いバージョンが必要です。",
"Server version %s or lower is required." : "サーバーの %s よりも低いバージョンが必要です。",
+ "Logged in user must be an admin" : "ログインユーザーは管理者である必要があります",
"Unknown filetype" : "不明なファイルタイプ",
"Invalid image" : "無効な画像",
"Avatar image is not square" : "アバター画像が正方形ではありません",
"today" : "今日",
- "yesterday" : "1日前",
+ "tomorrow" : "明日",
+ "yesterday" : "昨日",
+ "_in %n day_::_in %n days_" : ["%n 日"],
"_%n day ago_::_%n days ago_" : ["%n 日前"],
- "last month" : "1ヶ月前",
- "_%n month ago_::_%n months ago_" : ["%nヶ月前"],
- "last year" : "1年前",
+ "next month" : "来月",
+ "last month" : "先月",
+ "_in %n month_::_in %n months_" : ["%n ヶ月"],
+ "_%n month ago_::_%n months ago_" : ["%n ヶ月前"],
+ "next year" : "来年",
+ "last year" : "去年",
+ "_in %n year_::_in %n years_" : ["%n 年"],
"_%n year ago_::_%n years ago_" : ["%n 年前"],
+ "_in %n hour_::_in %n hours_" : ["%n 時間"],
"_%n hour ago_::_%n hours ago_" : ["%n 時間前"],
+ "_in %n minute_::_in %n minutes_" : ["%n 分"],
"_%n minute ago_::_%n minutes ago_" : ["%n 分前"],
+ "in a few seconds" : "数秒",
"seconds ago" : "数秒前",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ID: %sのモジュールは存在しません。アプリ設定で有効にするか、管理者に問い合わせてください。",
"File name is a reserved word" : "ファイル名が予約された単語です",
@@ -45,6 +58,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "空のファイル名は許可されていません",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "appinfoファイルが読み込めないため、アプリ名 \"%s\" がインストールできません。",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "\"%s\" アプリは、このバージョンのサーバーと互換性がないためインストールされませんでした。",
+ "__language_name__" : "Japanese (日本語)",
"This is an automatically sent email, please do not reply." : "これは自動的に生成されたメールです。返信しないでください。",
"Help" : "ヘルプ",
"Apps" : "アプリ",
@@ -52,18 +66,18 @@ OC.L10N.register(
"Log out" : "ログアウト",
"Users" : "ユーザー",
"Unknown user" : "不明なユーザー",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "作成",
+ "Change" : "変更",
+ "Delete" : "削除",
+ "Share" : "共有",
+ "Overview" : "概要",
"Basic settings" : "基本設定",
"Sharing" : "共有",
"Security" : "セキュリティ",
"Encryption" : "暗号化",
"Additional settings" : "追加設定",
- "Tips & tricks" : "ヒントとコツ",
"Personal info" : "個人情報",
- "Sync clients" : "同期クライアント",
"Unlimited" : "無制限",
- "__language_name__" : "Japanese (日本語)",
"Verifying" : "検証中",
"Verifying …" : "検証中",
"Verify" : "検証",
@@ -72,8 +86,8 @@ OC.L10N.register(
"%s enter the database name." : "%s のデータベース名を入力してください。",
"%s you may not use dots in the database name" : "%s ではデータベース名にドットを利用できないかもしれません。",
"Oracle connection could not be established" : "Oracleへの接続が確立できませんでした。",
- "Oracle username and/or password not valid" : "Oracleのユーザー名もしくはパスワードは有効ではありません",
- "PostgreSQL username and/or password not valid" : "PostgreSQLのユーザー名もしくはパスワードは有効ではありません",
+ "Oracle username and/or password not valid" : "Oracleのユーザー名またはパスワードが有効ではありません",
+ "PostgreSQL username and/or password not valid" : "PostgreSQLのユーザー名またはパスワードが有効ではありません",
"You need to enter details of an existing account." : "既存のアカウントの詳細を入力してください。",
"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X では、サポートされていません。このOSでは、%sは正常に動作しないかもしれません。ご自身の責任においてご利用ください。",
"For the best results, please consider using a GNU/Linux server instead." : "最も良い方法としては、代わりにGNU/Linuxサーバーを利用することをご検討ください。",
@@ -88,14 +102,14 @@ OC.L10N.register(
"You are not allowed to share %s" : "%s を共有することを許可されていません。",
"Sharing %s failed, because you can not share with yourself" : "%s を共有できませんでした。自分自身に共有することはできません。",
"Sharing %s failed, because the user %s does not exist" : "%s を共有できませんでした。ユーザー %s が存在しません。",
- "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "%s を共有できませんでした。ユーザー %s はどのグループにも属していません。%s は、??のメンバーです。",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "%s を共有できませんでした。ユーザー %s はどのグループにも属していません。%s は、次のグループのメンバーです",
"Sharing %s failed, because this item is already shared with %s" : "%s を共有できませんでした。このアイテムはすでに %s に共有されています。",
"Sharing %s failed, because this item is already shared with user %s" : "%s を共有できませんでした。このアイテムは、ユーザー %s によりすでに共有されています。",
"Sharing %s failed, because the group %s does not exist" : "%s を共有できませんでした。グループ %s は存在しません。",
"Sharing %s failed, because %s is not a member of the group %s" : "%s を共有できませんでした。%s は、グループ %s のメンバーではありません。",
"You need to provide a password to create a public link, only protected links are allowed" : "公開用リンクの作成にはパスワードの設定が必要です",
"Sharing %s failed, because sharing with links is not allowed" : "%s を共有できませんでした。リンクでの共有は許可されていません。",
- "Not allowed to create a federated share with the same user" : "同じユーザーでフェデレーション共有を作成することは出来ません",
+ "Not allowed to create a federated share with the same user" : "同じユーザーでフェデレーション共有は作成できません。",
"Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "%s を共有できませんでした。%s が見つかりませんでした。現在サーバーに接続できないようです。",
"Share type %s is not valid for %s" : "%s の共有方法は、%s には適用できません。",
"Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "有効期限を設定できません。共有開始から %s 以降に有効期限を設定することはできません。",
@@ -215,6 +229,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "設定が未完了のストレージです。 %s",
"Storage connection error. %s" : "ストレージへの接続エラー。 %s",
"Storage is temporarily not available" : "ストレージは一時的に利用できません",
- "Storage connection timeout. %s" : "ストレージへの接続がタイムアウト。 %s"
+ "Storage connection timeout. %s" : "ストレージへの接続がタイムアウト。 %s",
+ "Personal" : "パーソナル",
+ "Admin" : "管理者",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "ヒントとコツ",
+ "DB Error: \"%s\"" : "DBエラー: \"%s\"",
+ "Offending command was: \"%s\"" : "問題のあるコマンド: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "問題のあるコマンド: \"%s\", name: %s, password: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "%sのアクセス権を設定できません。%sの権限不足です ",
+ "Setting permissions for %s failed, because the item was not found" : "%sのアクセス権を設定できません。指定されたアイテムがありません ",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "有効期限は削除できません。共有には有効期限が必要です。",
+ "Cannot increase permissions of %s" : "%sの権限を付与できません ",
+ "Files can't be shared with delete permissions" : "削除権限付きでファイル共有はできません",
+ "Files can't be shared with create permissions" : "作成権限付きでファイル共有はできません",
+ "Cannot set expiration date more than %s days in the future" : "%s 日以上先の有効期限は設定できません ",
+ "No app name specified" : "アプリ名が指定されていません",
+ "App '%s' could not be installed!" : "アプリ名 %s はインストールできませんでした",
+ "Sync clients" : "同期クライアント"
},
"nplurals=1; plural=0;");
diff --git a/lib/l10n/ja.json b/lib/l10n/ja.json
index e6067d7ca21..9d5049baa79 100644
--- a/lib/l10n/ja.json
+++ b/lib/l10n/ja.json
@@ -11,6 +11,9 @@
"%1$s, %2$s, %3$s and %4$s" : "%1$s と %2$s、%3$s、%4$s",
"%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s と %2$s、%3$s、%4$s、%5$s",
"Education Edition" : "Education Edition",
+ "Enterprise bundle" : "エンタープライズ バンドル",
+ "Groupware bundle" : "グループウェア バンドル",
+ "Social sharing bundle" : "SNS バンドル",
"PHP %s or higher is required." : "PHP %s 以上が必要です。",
"PHP with a version lower than %s is required." : "%s 以前のバージョンのPHPが必要です。",
"%sbit or higher PHP required." : "%sbit 以上の新しいバージョンのPHPが必要です。",
@@ -22,18 +25,28 @@
"Following platforms are supported: %s" : "次のプラットフォームをサポートしています: %s",
"Server version %s or higher is required." : "サーバーの %s よりも高いバージョンが必要です。",
"Server version %s or lower is required." : "サーバーの %s よりも低いバージョンが必要です。",
+ "Logged in user must be an admin" : "ログインユーザーは管理者である必要があります",
"Unknown filetype" : "不明なファイルタイプ",
"Invalid image" : "無効な画像",
"Avatar image is not square" : "アバター画像が正方形ではありません",
"today" : "今日",
- "yesterday" : "1日前",
+ "tomorrow" : "明日",
+ "yesterday" : "昨日",
+ "_in %n day_::_in %n days_" : ["%n 日"],
"_%n day ago_::_%n days ago_" : ["%n 日前"],
- "last month" : "1ヶ月前",
- "_%n month ago_::_%n months ago_" : ["%nヶ月前"],
- "last year" : "1年前",
+ "next month" : "来月",
+ "last month" : "先月",
+ "_in %n month_::_in %n months_" : ["%n ヶ月"],
+ "_%n month ago_::_%n months ago_" : ["%n ヶ月前"],
+ "next year" : "来年",
+ "last year" : "去年",
+ "_in %n year_::_in %n years_" : ["%n 年"],
"_%n year ago_::_%n years ago_" : ["%n 年前"],
+ "_in %n hour_::_in %n hours_" : ["%n 時間"],
"_%n hour ago_::_%n hours ago_" : ["%n 時間前"],
+ "_in %n minute_::_in %n minutes_" : ["%n 分"],
"_%n minute ago_::_%n minutes ago_" : ["%n 分前"],
+ "in a few seconds" : "数秒",
"seconds ago" : "数秒前",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ID: %sのモジュールは存在しません。アプリ設定で有効にするか、管理者に問い合わせてください。",
"File name is a reserved word" : "ファイル名が予約された単語です",
@@ -43,6 +56,7 @@
"Empty filename is not allowed" : "空のファイル名は許可されていません",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "appinfoファイルが読み込めないため、アプリ名 \"%s\" がインストールできません。",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "\"%s\" アプリは、このバージョンのサーバーと互換性がないためインストールされませんでした。",
+ "__language_name__" : "Japanese (日本語)",
"This is an automatically sent email, please do not reply." : "これは自動的に生成されたメールです。返信しないでください。",
"Help" : "ヘルプ",
"Apps" : "アプリ",
@@ -50,18 +64,18 @@
"Log out" : "ログアウト",
"Users" : "ユーザー",
"Unknown user" : "不明なユーザー",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "作成",
+ "Change" : "変更",
+ "Delete" : "削除",
+ "Share" : "共有",
+ "Overview" : "概要",
"Basic settings" : "基本設定",
"Sharing" : "共有",
"Security" : "セキュリティ",
"Encryption" : "暗号化",
"Additional settings" : "追加設定",
- "Tips & tricks" : "ヒントとコツ",
"Personal info" : "個人情報",
- "Sync clients" : "同期クライアント",
"Unlimited" : "無制限",
- "__language_name__" : "Japanese (日本語)",
"Verifying" : "検証中",
"Verifying …" : "検証中",
"Verify" : "検証",
@@ -70,8 +84,8 @@
"%s enter the database name." : "%s のデータベース名を入力してください。",
"%s you may not use dots in the database name" : "%s ではデータベース名にドットを利用できないかもしれません。",
"Oracle connection could not be established" : "Oracleへの接続が確立できませんでした。",
- "Oracle username and/or password not valid" : "Oracleのユーザー名もしくはパスワードは有効ではありません",
- "PostgreSQL username and/or password not valid" : "PostgreSQLのユーザー名もしくはパスワードは有効ではありません",
+ "Oracle username and/or password not valid" : "Oracleのユーザー名またはパスワードが有効ではありません",
+ "PostgreSQL username and/or password not valid" : "PostgreSQLのユーザー名またはパスワードが有効ではありません",
"You need to enter details of an existing account." : "既存のアカウントの詳細を入力してください。",
"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X では、サポートされていません。このOSでは、%sは正常に動作しないかもしれません。ご自身の責任においてご利用ください。",
"For the best results, please consider using a GNU/Linux server instead." : "最も良い方法としては、代わりにGNU/Linuxサーバーを利用することをご検討ください。",
@@ -86,14 +100,14 @@
"You are not allowed to share %s" : "%s を共有することを許可されていません。",
"Sharing %s failed, because you can not share with yourself" : "%s を共有できませんでした。自分自身に共有することはできません。",
"Sharing %s failed, because the user %s does not exist" : "%s を共有できませんでした。ユーザー %s が存在しません。",
- "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "%s を共有できませんでした。ユーザー %s はどのグループにも属していません。%s は、??のメンバーです。",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "%s を共有できませんでした。ユーザー %s はどのグループにも属していません。%s は、次のグループのメンバーです",
"Sharing %s failed, because this item is already shared with %s" : "%s を共有できませんでした。このアイテムはすでに %s に共有されています。",
"Sharing %s failed, because this item is already shared with user %s" : "%s を共有できませんでした。このアイテムは、ユーザー %s によりすでに共有されています。",
"Sharing %s failed, because the group %s does not exist" : "%s を共有できませんでした。グループ %s は存在しません。",
"Sharing %s failed, because %s is not a member of the group %s" : "%s を共有できませんでした。%s は、グループ %s のメンバーではありません。",
"You need to provide a password to create a public link, only protected links are allowed" : "公開用リンクの作成にはパスワードの設定が必要です",
"Sharing %s failed, because sharing with links is not allowed" : "%s を共有できませんでした。リンクでの共有は許可されていません。",
- "Not allowed to create a federated share with the same user" : "同じユーザーでフェデレーション共有を作成することは出来ません",
+ "Not allowed to create a federated share with the same user" : "同じユーザーでフェデレーション共有は作成できません。",
"Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "%s を共有できませんでした。%s が見つかりませんでした。現在サーバーに接続できないようです。",
"Share type %s is not valid for %s" : "%s の共有方法は、%s には適用できません。",
"Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "有効期限を設定できません。共有開始から %s 以降に有効期限を設定することはできません。",
@@ -213,6 +227,24 @@
"Storage incomplete configuration. %s" : "設定が未完了のストレージです。 %s",
"Storage connection error. %s" : "ストレージへの接続エラー。 %s",
"Storage is temporarily not available" : "ストレージは一時的に利用できません",
- "Storage connection timeout. %s" : "ストレージへの接続がタイムアウト。 %s"
+ "Storage connection timeout. %s" : "ストレージへの接続がタイムアウト。 %s",
+ "Personal" : "パーソナル",
+ "Admin" : "管理者",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "ヒントとコツ",
+ "DB Error: \"%s\"" : "DBエラー: \"%s\"",
+ "Offending command was: \"%s\"" : "問題のあるコマンド: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "問題のあるコマンド: \"%s\", name: %s, password: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "%sのアクセス権を設定できません。%sの権限不足です ",
+ "Setting permissions for %s failed, because the item was not found" : "%sのアクセス権を設定できません。指定されたアイテムがありません ",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "有効期限は削除できません。共有には有効期限が必要です。",
+ "Cannot increase permissions of %s" : "%sの権限を付与できません ",
+ "Files can't be shared with delete permissions" : "削除権限付きでファイル共有はできません",
+ "Files can't be shared with create permissions" : "作成権限付きでファイル共有はできません",
+ "Cannot set expiration date more than %s days in the future" : "%s 日以上先の有効期限は設定できません ",
+ "No app name specified" : "アプリ名が指定されていません",
+ "App '%s' could not be installed!" : "アプリ名 %s はインストールできませんでした",
+ "Sync clients" : "同期クライアント"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/lib/l10n/ka_GE.js b/lib/l10n/ka_GE.js
index 9f34f56d86d..db25f68a2dd 100644
--- a/lib/l10n/ka_GE.js
+++ b/lib/l10n/ka_GE.js
@@ -27,26 +27,27 @@ OC.L10N.register(
"Following platforms are supported: %s" : "მხარდაჭერია შემდეგი პლატფორმები: %s",
"Server version %s or higher is required." : "საჭიროა სერვერი ვერსიით %s ან მეტი.",
"Server version %s or lower is required." : "საჭიროა სერვერი ვერსიით %s ან ნაკლები.",
+ "Logged in user must be an admin" : "ავტორიზირებული მომხმარებელი უნდა იყოს ადმინისტრატორი",
"Unknown filetype" : "ამოუცნობი ფაილის ტიპი",
"Invalid image" : "არასწორი სურათი",
"Avatar image is not square" : "ავატარის სურათი არაა კვადრატი",
"today" : "დღეს",
"tomorrow" : "ხვალ",
"yesterday" : "გუშინ",
- "_in %n day_::_in %n days_" : ["%n დღეში"],
- "_%n day ago_::_%n days ago_" : ["%n დღის წინ"],
+ "_in %n day_::_in %n days_" : ["%n დღეში","%n დღეში"],
+ "_%n day ago_::_%n days ago_" : ["%n დღის წინ","%n დღის წინ"],
"next month" : "შემდეგი თვე",
"last month" : "გასულ თვეში",
- "_in %n month_::_in %n months_" : ["%n თვეში"],
- "_%n month ago_::_%n months ago_" : ["%n თვის წინ"],
+ "_in %n month_::_in %n months_" : ["%n თვეში","%n თვეში"],
+ "_%n month ago_::_%n months ago_" : ["%n თვის წინ","%n თვის წინ"],
"next year" : "შემდეგი წელი",
"last year" : "გასულ წელს",
- "_in %n year_::_in %n years_" : ["%n წელიწადში"],
- "_%n year ago_::_%n years ago_" : ["%n წლის წინ"],
- "_in %n hour_::_in %n hours_" : ["%n საათში"],
- "_%n hour ago_::_%n hours ago_" : ["%n საათის წინ"],
- "_in %n minute_::_in %n minutes_" : ["%n წუთში"],
- "_%n minute ago_::_%n minutes ago_" : ["%n წუთის წინ"],
+ "_in %n year_::_in %n years_" : ["%n წელიწადში","%n წელიწადში"],
+ "_%n year ago_::_%n years ago_" : ["%n წლის წინ","%n წლის წინ"],
+ "_in %n hour_::_in %n hours_" : ["%n საათში","%n საათში"],
+ "_%n hour ago_::_%n hours ago_" : ["%n საათის წინ","%n საათის წინ"],
+ "_in %n minute_::_in %n minutes_" : ["%n წუთში","%n წუთში"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n წუთის წინ","%n წუთის წინ"],
"in a few seconds" : "რამდენიმე წამში",
"seconds ago" : "წამის წინ",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "მოდული ID-ით: %s არ არსებობს. გთხოვთ აამოქმედოთ ის აპლიკაციების პარამეტრებში ან დაუკავშირდეთ ადმინისტრატორს.",
@@ -57,6 +58,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "ცარიელი ფაილის სახელი არაა ნებადართული",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "აპლიკაცია \"%s\" ვერ ყენდება, რადგან appinfo ფაილი არ იკითხება.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "აპლიკაცია \"%s\" ვერ ყენდება, რადგან ის ამ სერვერის ვერსიასთან არაა თავსებადი.",
+ "__language_name__" : "ქართული",
"This is an automatically sent email, please do not reply." : "ეს ელ-წერილი გამოგზავნილია ავტომატურად, გთხოვთ არ უპასუხოთ.",
"Help" : "დახმარება",
"Apps" : "აპლიკაციები",
@@ -64,18 +66,17 @@ OC.L10N.register(
"Log out" : "გასვლა",
"Users" : "მომხმარებლები",
"Unknown user" : "ამოუცნობი მომხმარებელი",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "შექმნა",
+ "Change" : "შეცვლა",
+ "Delete" : "გაუქმება",
+ "Share" : "გაზიარება",
"Basic settings" : "ძირითადი პარამეტრები",
"Sharing" : "გაზიარება",
"Security" : "უსაფრთხოება",
"Encryption" : "შიფრაცია",
"Additional settings" : "დამატებითი პარამეტრები",
- "Tips & tricks" : "რჩევები და ხრიკები",
"Personal info" : "პირადი ინფორმაცია",
- "Sync clients" : "კლიენტების სინქრონიზაცია",
"Unlimited" : "ულიმიტო",
- "__language_name__" : "ქართული",
"Verifying" : "მოწმდება",
"Verifying …" : "მოწმდება …",
"Verify" : "დამოწმება",
@@ -230,6 +231,9 @@ OC.L10N.register(
"Storage connection timeout. %s" : "საცავის კავშირის დროის ამოწურვა. %s",
"Personal" : "პირადი",
"Admin" : "ადმინისტრატორი",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "რჩევები და ხრიკები",
"DB Error: \"%s\"" : "DB შეცდომა: \"%s\"",
"Offending command was: \"%s\"" : "შემაშფოთებელი ბრძანება იყო: \"%s\"",
"Offending command was: \"%s\", name: %s, password: %s" : "შემაშფოთებელი ბრძანება იყო: \"%s\", სახელი: %s, პაროლი: %s",
@@ -241,6 +245,7 @@ OC.L10N.register(
"Files can't be shared with create permissions" : "ფაილები შექმნის უფლებებით ვერ გაზიარდება",
"Cannot set expiration date more than %s days in the future" : "ვადის ამოწურვის თარიღი %s დღეზე მეტი მომავალში ვერ იქნება",
"No app name specified" : "აპლიკაციის სახელი არაა მოცემული",
- "App '%s' could not be installed!" : "აპლიკაცია '%s' ვერ ყენდება!"
+ "App '%s' could not be installed!" : "აპლიკაცია '%s' ვერ ყენდება!",
+ "Sync clients" : "კლიენტების სინქრონიზაცია"
},
-"nplurals=1; plural=0;");
+"nplurals=2; plural=(n!=1);");
diff --git a/lib/l10n/ka_GE.json b/lib/l10n/ka_GE.json
index 509e94340cd..2e81294b48c 100644
--- a/lib/l10n/ka_GE.json
+++ b/lib/l10n/ka_GE.json
@@ -25,26 +25,27 @@
"Following platforms are supported: %s" : "მხარდაჭერია შემდეგი პლატფორმები: %s",
"Server version %s or higher is required." : "საჭიროა სერვერი ვერსიით %s ან მეტი.",
"Server version %s or lower is required." : "საჭიროა სერვერი ვერსიით %s ან ნაკლები.",
+ "Logged in user must be an admin" : "ავტორიზირებული მომხმარებელი უნდა იყოს ადმინისტრატორი",
"Unknown filetype" : "ამოუცნობი ფაილის ტიპი",
"Invalid image" : "არასწორი სურათი",
"Avatar image is not square" : "ავატარის სურათი არაა კვადრატი",
"today" : "დღეს",
"tomorrow" : "ხვალ",
"yesterday" : "გუშინ",
- "_in %n day_::_in %n days_" : ["%n დღეში"],
- "_%n day ago_::_%n days ago_" : ["%n დღის წინ"],
+ "_in %n day_::_in %n days_" : ["%n დღეში","%n დღეში"],
+ "_%n day ago_::_%n days ago_" : ["%n დღის წინ","%n დღის წინ"],
"next month" : "შემდეგი თვე",
"last month" : "გასულ თვეში",
- "_in %n month_::_in %n months_" : ["%n თვეში"],
- "_%n month ago_::_%n months ago_" : ["%n თვის წინ"],
+ "_in %n month_::_in %n months_" : ["%n თვეში","%n თვეში"],
+ "_%n month ago_::_%n months ago_" : ["%n თვის წინ","%n თვის წინ"],
"next year" : "შემდეგი წელი",
"last year" : "გასულ წელს",
- "_in %n year_::_in %n years_" : ["%n წელიწადში"],
- "_%n year ago_::_%n years ago_" : ["%n წლის წინ"],
- "_in %n hour_::_in %n hours_" : ["%n საათში"],
- "_%n hour ago_::_%n hours ago_" : ["%n საათის წინ"],
- "_in %n minute_::_in %n minutes_" : ["%n წუთში"],
- "_%n minute ago_::_%n minutes ago_" : ["%n წუთის წინ"],
+ "_in %n year_::_in %n years_" : ["%n წელიწადში","%n წელიწადში"],
+ "_%n year ago_::_%n years ago_" : ["%n წლის წინ","%n წლის წინ"],
+ "_in %n hour_::_in %n hours_" : ["%n საათში","%n საათში"],
+ "_%n hour ago_::_%n hours ago_" : ["%n საათის წინ","%n საათის წინ"],
+ "_in %n minute_::_in %n minutes_" : ["%n წუთში","%n წუთში"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n წუთის წინ","%n წუთის წინ"],
"in a few seconds" : "რამდენიმე წამში",
"seconds ago" : "წამის წინ",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "მოდული ID-ით: %s არ არსებობს. გთხოვთ აამოქმედოთ ის აპლიკაციების პარამეტრებში ან დაუკავშირდეთ ადმინისტრატორს.",
@@ -55,6 +56,7 @@
"Empty filename is not allowed" : "ცარიელი ფაილის სახელი არაა ნებადართული",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "აპლიკაცია \"%s\" ვერ ყენდება, რადგან appinfo ფაილი არ იკითხება.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "აპლიკაცია \"%s\" ვერ ყენდება, რადგან ის ამ სერვერის ვერსიასთან არაა თავსებადი.",
+ "__language_name__" : "ქართული",
"This is an automatically sent email, please do not reply." : "ეს ელ-წერილი გამოგზავნილია ავტომატურად, გთხოვთ არ უპასუხოთ.",
"Help" : "დახმარება",
"Apps" : "აპლიკაციები",
@@ -62,18 +64,17 @@
"Log out" : "გასვლა",
"Users" : "მომხმარებლები",
"Unknown user" : "ამოუცნობი მომხმარებელი",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "შექმნა",
+ "Change" : "შეცვლა",
+ "Delete" : "გაუქმება",
+ "Share" : "გაზიარება",
"Basic settings" : "ძირითადი პარამეტრები",
"Sharing" : "გაზიარება",
"Security" : "უსაფრთხოება",
"Encryption" : "შიფრაცია",
"Additional settings" : "დამატებითი პარამეტრები",
- "Tips & tricks" : "რჩევები და ხრიკები",
"Personal info" : "პირადი ინფორმაცია",
- "Sync clients" : "კლიენტების სინქრონიზაცია",
"Unlimited" : "ულიმიტო",
- "__language_name__" : "ქართული",
"Verifying" : "მოწმდება",
"Verifying …" : "მოწმდება …",
"Verify" : "დამოწმება",
@@ -228,6 +229,9 @@
"Storage connection timeout. %s" : "საცავის კავშირის დროის ამოწურვა. %s",
"Personal" : "პირადი",
"Admin" : "ადმინისტრატორი",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "რჩევები და ხრიკები",
"DB Error: \"%s\"" : "DB შეცდომა: \"%s\"",
"Offending command was: \"%s\"" : "შემაშფოთებელი ბრძანება იყო: \"%s\"",
"Offending command was: \"%s\", name: %s, password: %s" : "შემაშფოთებელი ბრძანება იყო: \"%s\", სახელი: %s, პაროლი: %s",
@@ -239,6 +243,7 @@
"Files can't be shared with create permissions" : "ფაილები შექმნის უფლებებით ვერ გაზიარდება",
"Cannot set expiration date more than %s days in the future" : "ვადის ამოწურვის თარიღი %s დღეზე მეტი მომავალში ვერ იქნება",
"No app name specified" : "აპლიკაციის სახელი არაა მოცემული",
- "App '%s' could not be installed!" : "აპლიკაცია '%s' ვერ ყენდება!"
-},"pluralForm" :"nplurals=1; plural=0;"
+ "App '%s' could not be installed!" : "აპლიკაცია '%s' ვერ ყენდება!",
+ "Sync clients" : "კლიენტების სინქრონიზაცია"
+},"pluralForm" :"nplurals=2; plural=(n!=1);"
} \ No newline at end of file
diff --git a/lib/l10n/km.js b/lib/l10n/km.js
new file mode 100644
index 00000000000..2c2ac17ab41
--- /dev/null
+++ b/lib/l10n/km.js
@@ -0,0 +1,31 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Unknown filetype" : "មិន​ស្គាល់​ប្រភេទ​ឯកសារ",
+ "Invalid image" : "រូបភាព​មិន​ត្រឹម​ត្រូវ",
+ "today" : "ថ្ងៃនេះ",
+ "yesterday" : "ម្សិលមិញ",
+ "last month" : "ខែមុន",
+ "_%n month ago_::_%n months ago_" : ["%n ខែ​មុន"],
+ "last year" : "ឆ្នាំ​មុន",
+ "_%n hour ago_::_%n hours ago_" : ["%n ម៉ោង​មុន"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n នាទី​មុន"],
+ "seconds ago" : "វិនាទី​មុន",
+ "__language_name__" : "ភាសាខ្មែរ",
+ "Apps" : "កម្មវិធី",
+ "Users" : "អ្នកប្រើ",
+ "Unknown user" : "មិនស្គាល់អ្នកប្រើប្រាស់",
+ "%s enter the database username." : "%s វាយ​បញ្ចូល​ឈ្មោះ​អ្នក​ប្រើ​មូលដ្ឋាន​ទិន្នន័យ។",
+ "%s enter the database name." : "%s វាយ​បញ្ចូល​ឈ្មោះ​មូលដ្ឋាន​ទិន្នន័យ។",
+ "%s you may not use dots in the database name" : "%s អ្នក​អាច​មិន​ប្រើ​សញ្ញា​ចុច​នៅ​ក្នុង​ឈ្មោះ​មូលដ្ឋាន​ទិន្នន័យ",
+ "Oracle connection could not be established" : "មិន​អាច​បង្កើត​ការ​តភ្ជាប់ Oracle",
+ "PostgreSQL username and/or password not valid" : "ឈ្មោះ​អ្នក​ប្រើ និង/ឬ ពាក្យ​សម្ងាត់ PostgreSQL គឺ​មិន​ត្រូវ​ទេ",
+ "Set an admin username." : "កំណត់​ឈ្មោះ​អ្នក​គ្រប់គ្រង។",
+ "Set an admin password." : "កំណត់​ពាក្យ​សម្ងាត់​អ្នក​គ្រប់គ្រង។",
+ "Could not find category \"%s\"" : "រក​មិន​ឃើញ​ចំណាត់​ក្រុម \"%s\"",
+ "A valid username must be provided" : "ត្រូវ​ផ្ដល់​ឈ្មោះ​អ្នក​ប្រើ​ឲ្យ​បាន​ត្រឹម​ត្រូវ",
+ "A valid password must be provided" : "ត្រូវ​ផ្ដល់​ពាក្យ​សម្ងាត់​ឲ្យ​បាន​ត្រឹម​ត្រូវ",
+ "Application is not enabled" : "មិន​បាន​បើក​កម្មវិធី",
+ "Authentication error" : "កំហុស​ការ​ផ្ទៀង​ផ្ទាត់​ភាព​ត្រឹម​ត្រូវ"
+},
+"nplurals=1; plural=0;");
diff --git a/lib/l10n/km.json b/lib/l10n/km.json
new file mode 100644
index 00000000000..fe796ace7ad
--- /dev/null
+++ b/lib/l10n/km.json
@@ -0,0 +1,29 @@
+{ "translations": {
+ "Unknown filetype" : "មិន​ស្គាល់​ប្រភេទ​ឯកសារ",
+ "Invalid image" : "រូបភាព​មិន​ត្រឹម​ត្រូវ",
+ "today" : "ថ្ងៃនេះ",
+ "yesterday" : "ម្សិលមិញ",
+ "last month" : "ខែមុន",
+ "_%n month ago_::_%n months ago_" : ["%n ខែ​មុន"],
+ "last year" : "ឆ្នាំ​មុន",
+ "_%n hour ago_::_%n hours ago_" : ["%n ម៉ោង​មុន"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n នាទី​មុន"],
+ "seconds ago" : "វិនាទី​មុន",
+ "__language_name__" : "ភាសាខ្មែរ",
+ "Apps" : "កម្មវិធី",
+ "Users" : "អ្នកប្រើ",
+ "Unknown user" : "មិនស្គាល់អ្នកប្រើប្រាស់",
+ "%s enter the database username." : "%s វាយ​បញ្ចូល​ឈ្មោះ​អ្នក​ប្រើ​មូលដ្ឋាន​ទិន្នន័យ។",
+ "%s enter the database name." : "%s វាយ​បញ្ចូល​ឈ្មោះ​មូលដ្ឋាន​ទិន្នន័យ។",
+ "%s you may not use dots in the database name" : "%s អ្នក​អាច​មិន​ប្រើ​សញ្ញា​ចុច​នៅ​ក្នុង​ឈ្មោះ​មូលដ្ឋាន​ទិន្នន័យ",
+ "Oracle connection could not be established" : "មិន​អាច​បង្កើត​ការ​តភ្ជាប់ Oracle",
+ "PostgreSQL username and/or password not valid" : "ឈ្មោះ​អ្នក​ប្រើ និង/ឬ ពាក្យ​សម្ងាត់ PostgreSQL គឺ​មិន​ត្រូវ​ទេ",
+ "Set an admin username." : "កំណត់​ឈ្មោះ​អ្នក​គ្រប់គ្រង។",
+ "Set an admin password." : "កំណត់​ពាក្យ​សម្ងាត់​អ្នក​គ្រប់គ្រង។",
+ "Could not find category \"%s\"" : "រក​មិន​ឃើញ​ចំណាត់​ក្រុម \"%s\"",
+ "A valid username must be provided" : "ត្រូវ​ផ្ដល់​ឈ្មោះ​អ្នក​ប្រើ​ឲ្យ​បាន​ត្រឹម​ត្រូវ",
+ "A valid password must be provided" : "ត្រូវ​ផ្ដល់​ពាក្យ​សម្ងាត់​ឲ្យ​បាន​ត្រឹម​ត្រូវ",
+ "Application is not enabled" : "មិន​បាន​បើក​កម្មវិធី",
+ "Authentication error" : "កំហុស​ការ​ផ្ទៀង​ផ្ទាត់​ភាព​ត្រឹម​ត្រូវ"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/lib/l10n/kn.js b/lib/l10n/kn.js
new file mode 100644
index 00000000000..11c44964af9
--- /dev/null
+++ b/lib/l10n/kn.js
@@ -0,0 +1,13 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Unknown filetype" : "ಅಪರಿಚಿತ ಕಡತ ಮಾದರಿ",
+ "Invalid image" : "ಅಸಾಮರ್ಥ್ಯ ಚಿತ್ರ",
+ "__language_name__" : "ಕನ್ನಡ",
+ "Apps" : "ಕಾರ್ಯಕ್ರಮಗಳು",
+ "Users" : "ಬಳಕೆದಾರರು",
+ "A valid username must be provided" : "ಮಾನ್ಯ ಬಳಕೆದಾರ ಹೆಸರು ಒದಗಿಸಬೇಕಾಗುತ್ತದೆ",
+ "A valid password must be provided" : "ಸರಿಯಾದ ಬಳಕೆದಾರ ಗುಪ್ತಪದ ಒದಗಿಸಬೇಕಾಗಿದೆ",
+ "Authentication error" : "ದೃಢೀಕರಣ ದೋಷ"
+},
+"nplurals=2; plural=(n > 1);");
diff --git a/lib/l10n/kn.json b/lib/l10n/kn.json
new file mode 100644
index 00000000000..34d166cbce8
--- /dev/null
+++ b/lib/l10n/kn.json
@@ -0,0 +1,11 @@
+{ "translations": {
+ "Unknown filetype" : "ಅಪರಿಚಿತ ಕಡತ ಮಾದರಿ",
+ "Invalid image" : "ಅಸಾಮರ್ಥ್ಯ ಚಿತ್ರ",
+ "__language_name__" : "ಕನ್ನಡ",
+ "Apps" : "ಕಾರ್ಯಕ್ರಮಗಳು",
+ "Users" : "ಬಳಕೆದಾರರು",
+ "A valid username must be provided" : "ಮಾನ್ಯ ಬಳಕೆದಾರ ಹೆಸರು ಒದಗಿಸಬೇಕಾಗುತ್ತದೆ",
+ "A valid password must be provided" : "ಸರಿಯಾದ ಬಳಕೆದಾರ ಗುಪ್ತಪದ ಒದಗಿಸಬೇಕಾಗಿದೆ",
+ "Authentication error" : "ದೃಢೀಕರಣ ದೋಷ"
+},"pluralForm" :"nplurals=2; plural=(n > 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/ko.js b/lib/l10n/ko.js
index 5af670f8835..43c6f8baf5a 100644
--- a/lib/l10n/ko.js
+++ b/lib/l10n/ko.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "파일 이름을 비워 둘 수 없음",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "appinfo 파일을 읽을 수 없어서 앱 \"%s\"을(를) 설치할 수 없습니다.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "이 서버 버전과 호환되지 않아서 앱 \"%s\"을(를) 설치할 수 없습니다",
+ "__language_name__" : "한국어",
"This is an automatically sent email, please do not reply." : "자동으로 전송한 이메일입니다. 답장하지 마십시오.",
"Help" : "도움말",
"Apps" : "앱",
@@ -64,18 +65,13 @@ OC.L10N.register(
"Log out" : "로그아웃",
"Users" : "사용자",
"Unknown user" : "알려지지 않은 사용자",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "기본 설정",
"Sharing" : "공유",
"Security" : "보안",
"Encryption" : "암호화",
"Additional settings" : "고급 설정",
- "Tips & tricks" : "팁과 추가 정보",
"Personal info" : "개인 정보",
- "Sync clients" : "동기화 클라이언트",
"Unlimited" : "무제한",
- "__language_name__" : "한국어",
"Verifying" : "검사 중",
"Verifying …" : "검사 중…",
"Verify" : "검사",
@@ -230,6 +226,9 @@ OC.L10N.register(
"Storage connection timeout. %s" : "저장소 연결 시간이 초과되었습니다. %s",
"Personal" : "개인",
"Admin" : "관리자",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "팁과 추가 정보",
"DB Error: \"%s\"" : "DB 오류: \"%s\"",
"Offending command was: \"%s\"" : "잘못된 명령: \"%s\"",
"Offending command was: \"%s\", name: %s, password: %s" : "잘못된 명령: \"%s\", 이름: %s, 암호: %s",
@@ -241,6 +240,7 @@ OC.L10N.register(
"Files can't be shared with create permissions" : "파일을 생성 권한으로 공유할 수 없습니다",
"Cannot set expiration date more than %s days in the future" : "만료 날짜를 %s일 이상 이후로 설정할 수 없습니다",
"No app name specified" : "앱 이름이 지정되지 않았음",
- "App '%s' could not be installed!" : "앱 '%s'을(를) 설치할 수 없습니다!"
+ "App '%s' could not be installed!" : "앱 '%s'을(를) 설치할 수 없습니다!",
+ "Sync clients" : "동기화 클라이언트"
},
"nplurals=1; plural=0;");
diff --git a/lib/l10n/ko.json b/lib/l10n/ko.json
index 5235395f8dc..9356de01a07 100644
--- a/lib/l10n/ko.json
+++ b/lib/l10n/ko.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "파일 이름을 비워 둘 수 없음",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "appinfo 파일을 읽을 수 없어서 앱 \"%s\"을(를) 설치할 수 없습니다.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "이 서버 버전과 호환되지 않아서 앱 \"%s\"을(를) 설치할 수 없습니다",
+ "__language_name__" : "한국어",
"This is an automatically sent email, please do not reply." : "자동으로 전송한 이메일입니다. 답장하지 마십시오.",
"Help" : "도움말",
"Apps" : "앱",
@@ -62,18 +63,13 @@
"Log out" : "로그아웃",
"Users" : "사용자",
"Unknown user" : "알려지지 않은 사용자",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "기본 설정",
"Sharing" : "공유",
"Security" : "보안",
"Encryption" : "암호화",
"Additional settings" : "고급 설정",
- "Tips & tricks" : "팁과 추가 정보",
"Personal info" : "개인 정보",
- "Sync clients" : "동기화 클라이언트",
"Unlimited" : "무제한",
- "__language_name__" : "한국어",
"Verifying" : "검사 중",
"Verifying …" : "검사 중…",
"Verify" : "검사",
@@ -228,6 +224,9 @@
"Storage connection timeout. %s" : "저장소 연결 시간이 초과되었습니다. %s",
"Personal" : "개인",
"Admin" : "관리자",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "팁과 추가 정보",
"DB Error: \"%s\"" : "DB 오류: \"%s\"",
"Offending command was: \"%s\"" : "잘못된 명령: \"%s\"",
"Offending command was: \"%s\", name: %s, password: %s" : "잘못된 명령: \"%s\", 이름: %s, 암호: %s",
@@ -239,6 +238,7 @@
"Files can't be shared with create permissions" : "파일을 생성 권한으로 공유할 수 없습니다",
"Cannot set expiration date more than %s days in the future" : "만료 날짜를 %s일 이상 이후로 설정할 수 없습니다",
"No app name specified" : "앱 이름이 지정되지 않았음",
- "App '%s' could not be installed!" : "앱 '%s'을(를) 설치할 수 없습니다!"
+ "App '%s' could not be installed!" : "앱 '%s'을(를) 설치할 수 없습니다!",
+ "Sync clients" : "동기화 클라이언트"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/lib/l10n/lb.js b/lib/l10n/lb.js
new file mode 100644
index 00000000000..8b44be891f4
--- /dev/null
+++ b/lib/l10n/lb.js
@@ -0,0 +1,29 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Keng Schreiwreschter op d' 'config' Verzeechnis!",
+ "See %s" : "%s kucken",
+ "Sample configuration detected" : "Beispill-Konfiguratioun erkannt",
+ "PHP %s or higher is required." : "PHP %s oder méi nei ass néideg.",
+ "PHP with a version lower than %s is required." : "PHP mat enger Versioun %s oder méi kleng ass néideg.",
+ "Following databases are supported: %s" : "Dës Datebanke ginn ënnerstëtzt: %s",
+ "Unknown filetype" : "Onbekannten Fichier Typ",
+ "Invalid image" : "Ongülteg d'Bild",
+ "today" : "haut",
+ "yesterday" : "gëschter",
+ "_%n day ago_::_%n days ago_" : ["%n Dag hier","%n Deeg hier"],
+ "last month" : "Läschte Mount",
+ "_%n month ago_::_%n months ago_" : ["%n Mount hier","%n Méint hier"],
+ "last year" : "Läscht Joer",
+ "_%n year ago_::_%n years ago_" : ["%n Joer hier","%n Joer hier"],
+ "_%n hour ago_::_%n hours ago_" : ["%n Stonn hier","%n Stonnen hier"],
+ "seconds ago" : "Sekonnen hir",
+ "__language_name__" : "Lëtzebuergesch",
+ "Apps" : "Applikatiounen",
+ "Users" : "Benotzer",
+ "Set an admin password." : "Admin Passwuert setzen",
+ "%s shared »%s« with you" : "Den/D' %s huet »%s« mat dir gedeelt",
+ "Authentication error" : "Authentifikatioun's Fehler",
+ "Tips & tricks" : "Tipps an Tricks"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/lb.json b/lib/l10n/lb.json
new file mode 100644
index 00000000000..28503f3ede5
--- /dev/null
+++ b/lib/l10n/lb.json
@@ -0,0 +1,27 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Keng Schreiwreschter op d' 'config' Verzeechnis!",
+ "See %s" : "%s kucken",
+ "Sample configuration detected" : "Beispill-Konfiguratioun erkannt",
+ "PHP %s or higher is required." : "PHP %s oder méi nei ass néideg.",
+ "PHP with a version lower than %s is required." : "PHP mat enger Versioun %s oder méi kleng ass néideg.",
+ "Following databases are supported: %s" : "Dës Datebanke ginn ënnerstëtzt: %s",
+ "Unknown filetype" : "Onbekannten Fichier Typ",
+ "Invalid image" : "Ongülteg d'Bild",
+ "today" : "haut",
+ "yesterday" : "gëschter",
+ "_%n day ago_::_%n days ago_" : ["%n Dag hier","%n Deeg hier"],
+ "last month" : "Läschte Mount",
+ "_%n month ago_::_%n months ago_" : ["%n Mount hier","%n Méint hier"],
+ "last year" : "Läscht Joer",
+ "_%n year ago_::_%n years ago_" : ["%n Joer hier","%n Joer hier"],
+ "_%n hour ago_::_%n hours ago_" : ["%n Stonn hier","%n Stonnen hier"],
+ "seconds ago" : "Sekonnen hir",
+ "__language_name__" : "Lëtzebuergesch",
+ "Apps" : "Applikatiounen",
+ "Users" : "Benotzer",
+ "Set an admin password." : "Admin Passwuert setzen",
+ "%s shared »%s« with you" : "Den/D' %s huet »%s« mat dir gedeelt",
+ "Authentication error" : "Authentifikatioun's Fehler",
+ "Tips & tricks" : "Tipps an Tricks"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/lt_LT.js b/lib/l10n/lt_LT.js
index bb8c53361f9..08b0f6527b8 100644
--- a/lib/l10n/lt_LT.js
+++ b/lib/l10n/lt_LT.js
@@ -25,14 +25,15 @@ OC.L10N.register(
"Unknown filetype" : "Nežinomas failo tipas",
"Invalid image" : "Neteisingas paveikslas",
"today" : "šiandien",
+ "tomorrow" : "rytoj",
"yesterday" : "vakar",
- "_%n day ago_::_%n days ago_" : ["prieš %n dieną","prieš %n dienas","prieš %n dienų"],
+ "_%n day ago_::_%n days ago_" : ["prieš %n dieną","prieš %n dienas","prieš %n dienų","prieš %n dienų"],
"last month" : "praeitą mėnesį",
- "_%n month ago_::_%n months ago_" : ["prieš %n mėnesį","prieš %n mėnesius","prieš %n mėnesių"],
+ "_%n month ago_::_%n months ago_" : ["prieš %n mėnesį","prieš %n mėnesius","prieš %n mėnesių","prieš %n mėnesių"],
"last year" : "praeitais metais",
- "_%n year ago_::_%n years ago_" : ["prieš %n metus","prieš %n metus","prieš %n metų"],
- "_%n hour ago_::_%n hours ago_" : ["prieš %n valandą","prieš %n valandas","prieš %n valandų"],
- "_%n minute ago_::_%n minutes ago_" : ["prieš %n minutę","prieš % minutes","prieš %n minučių"],
+ "_%n year ago_::_%n years ago_" : ["prieš %n metus","prieš %n metus","prieš %n metų","prieš %n metų"],
+ "_%n hour ago_::_%n hours ago_" : ["prieš %n valandą","prieš %n valandas","prieš %n valandų","prieš %n valandų"],
+ "_%n minute ago_::_%n minutes ago_" : ["prieš %n minutę","prieš % minutes","prieš %n minučių","prieš %n minučių"],
"seconds ago" : "prieš keletą sekundžių",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modulio, kurio id: %s, nėra. Prašome jį įjungti savo programėlių nustatymuose arba susisiekti su savo administratoriumi.",
"File name is a reserved word" : "Failo pavadinimas negalimas, žodis rezervuotas",
@@ -41,6 +42,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Tuščias failo pavadinimas nėra leidžiamas",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Programėlė \"%s\" negali būti įdiegta, kadangi negalima perskaityti appinfo failo.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Programėlė \"%s\" negali būti įdiegta, kadangi ji nėra suderinama su serverio versija.",
+ "__language_name__" : "Lietuvių",
"This is an automatically sent email, please do not reply." : "Tai yra automatinis pranešimas, prašome neatsakyti.",
"Help" : "Pagalba",
"Apps" : "Programėlės",
@@ -48,18 +50,16 @@ OC.L10N.register(
"Log out" : "Atsijungti",
"Users" : "Naudotojai",
"Unknown user" : "Nežinomas naudotojas",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Sukurti",
+ "Delete" : "Ištrinti",
+ "Overview" : "Apžvalga",
"Basic settings" : "Pagrindiniai nustatymai",
"Sharing" : "Dalijimasis",
"Security" : "Saugumas",
"Encryption" : "Šifravimas",
"Additional settings" : "Papildomi nustatymai",
- "Tips & tricks" : "Patarimai ir gudrybės",
"Personal info" : "Asmeninė informacija",
- "Sync clients" : "Sinchronizavimo klientas",
"Unlimited" : "Neribota",
- "__language_name__" : "Lietuvių",
"Verifying" : "Tikrinimas",
"Verifying …" : "Tikrinama...",
"Verify" : "Patikrinti",
@@ -72,6 +72,7 @@ OC.L10N.register(
"PostgreSQL username and/or password not valid" : "Neteisingas PostgreSQL naudotojo vardas ir/arba slaptažodis",
"You need to enter details of an existing account." : "Jūs turite suvesti egzistuojančios paskyros duomenis.",
"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nėra palaikomas, %s neveiks tinkamai šioje platformoje. Naudodami prisiimate visą riziką !",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Pašalinkite savo php.ini faile open_basedir nustatymą arba persijunkite į 64-bitų PHP.",
"Set an admin username." : "Nustatyti administratoriaus naudotojo vardą.",
"Set an admin password." : "Nustatyti administratoriaus slaptažodį.",
"Can't create or write into the data directory %s" : "Negalima nuskaityti arba rašyti į duomenų katalogą. %s",
@@ -198,6 +199,15 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Nepilna saugyklos konfigūracija. %s",
"Storage connection error. %s" : "Saugyklos sujungimo ryšio klaida. %s",
"Storage is temporarily not available" : "Saugykla yra laikinai neprieinama",
- "Storage connection timeout. %s" : "Sujungimo su saugykla laikas baigėsi. %s"
+ "Storage connection timeout. %s" : "Sujungimo su saugykla laikas baigėsi. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Patarimai ir gudrybės",
+ "DB Error: \"%s\"" : "DB klaida: \"%s\"",
+ "Files can't be shared with delete permissions" : "Failai negali būti bendrinami su ištrynimo leidimais",
+ "Files can't be shared with create permissions" : "Failai negali būti bendrinami su sukūrimo leidimais",
+ "No app name specified" : "Nenurodytas programėlės pavadinimas",
+ "App '%s' could not be installed!" : "Nepavyko įdiegti \"%s\" programėlės!",
+ "Sync clients" : "Sinchronizavimo klientas"
},
-"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);");
+"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);");
diff --git a/lib/l10n/lt_LT.json b/lib/l10n/lt_LT.json
index 5548e6ceebe..2aa2b3ee25b 100644
--- a/lib/l10n/lt_LT.json
+++ b/lib/l10n/lt_LT.json
@@ -23,14 +23,15 @@
"Unknown filetype" : "Nežinomas failo tipas",
"Invalid image" : "Neteisingas paveikslas",
"today" : "šiandien",
+ "tomorrow" : "rytoj",
"yesterday" : "vakar",
- "_%n day ago_::_%n days ago_" : ["prieš %n dieną","prieš %n dienas","prieš %n dienų"],
+ "_%n day ago_::_%n days ago_" : ["prieš %n dieną","prieš %n dienas","prieš %n dienų","prieš %n dienų"],
"last month" : "praeitą mėnesį",
- "_%n month ago_::_%n months ago_" : ["prieš %n mėnesį","prieš %n mėnesius","prieš %n mėnesių"],
+ "_%n month ago_::_%n months ago_" : ["prieš %n mėnesį","prieš %n mėnesius","prieš %n mėnesių","prieš %n mėnesių"],
"last year" : "praeitais metais",
- "_%n year ago_::_%n years ago_" : ["prieš %n metus","prieš %n metus","prieš %n metų"],
- "_%n hour ago_::_%n hours ago_" : ["prieš %n valandą","prieš %n valandas","prieš %n valandų"],
- "_%n minute ago_::_%n minutes ago_" : ["prieš %n minutę","prieš % minutes","prieš %n minučių"],
+ "_%n year ago_::_%n years ago_" : ["prieš %n metus","prieš %n metus","prieš %n metų","prieš %n metų"],
+ "_%n hour ago_::_%n hours ago_" : ["prieš %n valandą","prieš %n valandas","prieš %n valandų","prieš %n valandų"],
+ "_%n minute ago_::_%n minutes ago_" : ["prieš %n minutę","prieš % minutes","prieš %n minučių","prieš %n minučių"],
"seconds ago" : "prieš keletą sekundžių",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modulio, kurio id: %s, nėra. Prašome jį įjungti savo programėlių nustatymuose arba susisiekti su savo administratoriumi.",
"File name is a reserved word" : "Failo pavadinimas negalimas, žodis rezervuotas",
@@ -39,6 +40,7 @@
"Empty filename is not allowed" : "Tuščias failo pavadinimas nėra leidžiamas",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Programėlė \"%s\" negali būti įdiegta, kadangi negalima perskaityti appinfo failo.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Programėlė \"%s\" negali būti įdiegta, kadangi ji nėra suderinama su serverio versija.",
+ "__language_name__" : "Lietuvių",
"This is an automatically sent email, please do not reply." : "Tai yra automatinis pranešimas, prašome neatsakyti.",
"Help" : "Pagalba",
"Apps" : "Programėlės",
@@ -46,18 +48,16 @@
"Log out" : "Atsijungti",
"Users" : "Naudotojai",
"Unknown user" : "Nežinomas naudotojas",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Sukurti",
+ "Delete" : "Ištrinti",
+ "Overview" : "Apžvalga",
"Basic settings" : "Pagrindiniai nustatymai",
"Sharing" : "Dalijimasis",
"Security" : "Saugumas",
"Encryption" : "Šifravimas",
"Additional settings" : "Papildomi nustatymai",
- "Tips & tricks" : "Patarimai ir gudrybės",
"Personal info" : "Asmeninė informacija",
- "Sync clients" : "Sinchronizavimo klientas",
"Unlimited" : "Neribota",
- "__language_name__" : "Lietuvių",
"Verifying" : "Tikrinimas",
"Verifying …" : "Tikrinama...",
"Verify" : "Patikrinti",
@@ -70,6 +70,7 @@
"PostgreSQL username and/or password not valid" : "Neteisingas PostgreSQL naudotojo vardas ir/arba slaptažodis",
"You need to enter details of an existing account." : "Jūs turite suvesti egzistuojančios paskyros duomenis.",
"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nėra palaikomas, %s neveiks tinkamai šioje platformoje. Naudodami prisiimate visą riziką !",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Pašalinkite savo php.ini faile open_basedir nustatymą arba persijunkite į 64-bitų PHP.",
"Set an admin username." : "Nustatyti administratoriaus naudotojo vardą.",
"Set an admin password." : "Nustatyti administratoriaus slaptažodį.",
"Can't create or write into the data directory %s" : "Negalima nuskaityti arba rašyti į duomenų katalogą. %s",
@@ -196,6 +197,15 @@
"Storage incomplete configuration. %s" : "Nepilna saugyklos konfigūracija. %s",
"Storage connection error. %s" : "Saugyklos sujungimo ryšio klaida. %s",
"Storage is temporarily not available" : "Saugykla yra laikinai neprieinama",
- "Storage connection timeout. %s" : "Sujungimo su saugykla laikas baigėsi. %s"
-},"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"
+ "Storage connection timeout. %s" : "Sujungimo su saugykla laikas baigėsi. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Patarimai ir gudrybės",
+ "DB Error: \"%s\"" : "DB klaida: \"%s\"",
+ "Files can't be shared with delete permissions" : "Failai negali būti bendrinami su ištrynimo leidimais",
+ "Files can't be shared with create permissions" : "Failai negali būti bendrinami su sukūrimo leidimais",
+ "No app name specified" : "Nenurodytas programėlės pavadinimas",
+ "App '%s' could not be installed!" : "Nepavyko įdiegti \"%s\" programėlės!",
+ "Sync clients" : "Sinchronizavimo klientas"
+},"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"
} \ No newline at end of file
diff --git a/lib/l10n/lv.js b/lib/l10n/lv.js
new file mode 100644
index 00000000000..aa175d49ee7
--- /dev/null
+++ b/lib/l10n/lv.js
@@ -0,0 +1,129 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Nevar rakstīt \"config\" mapē!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "To parasti var labot, dodot tīmekļa servera rakstīšanas piekļuvi config direktorijai",
+ "See %s" : "Skatīt %s",
+ "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Datnes no programmas %$1s netika aizvietotas pareizi. Pārliecinieties, vai tā ir versija, kas ir saderīga ar serveri.",
+ "Sample configuration detected" : "Atrasta konfigurācijas paraugs",
+ "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" : "Konstatēts, ka paraug konfigurācija ir nokopēta. Tas var izjaukt jūsu instalāciju un nav atbalstīts. Lūdzu, izlasiet dokumentāciju, pirms veicat izmaiņas config.php",
+ "%1$s and %2$s" : "%1$s un %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s un %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s un %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s un %5$s",
+ "PHP %s or higher is required." : "Ir nepieciešams PHP %s vai jaunāks.",
+ "PHP with a version lower than %s is required." : "Ir nepieciešams PHP vecāks kā %s.",
+ "%sbit or higher PHP required." : "Nepieciešams %sbit vai jaunāks PHP.",
+ "Following databases are supported: %s" : "Tiek atbalstītas šādas datu bāzes: %s",
+ "The command line tool %s could not be found" : "Komandrindas rīku %s nevarēja atrast",
+ "The library %s is not available." : "Bibliotēka %s nav pieejama.",
+ "Following platforms are supported: %s" : "Tiek atbalstītas šādas platformas: %s",
+ "Server version %s or higher is required." : "Ir vajadzīga servera versija %s vai jaunāka.",
+ "Server version %s or lower is required." : "Ir vajadzīga servera versija %s vai vecāka.",
+ "Unknown filetype" : "Nezināms datnes tips",
+ "Invalid image" : "Nederīgs attēls",
+ "Avatar image is not square" : "Avatar attēls nav kvadrāts",
+ "today" : "šodien",
+ "yesterday" : "vakar",
+ "_%n day ago_::_%n days ago_" : ["%n dienas atpakaļ","%n dienas atpakaļ","%n dienām"],
+ "last month" : "pagājušajā mēnesī",
+ "_%n month ago_::_%n months ago_" : ["%n mēneši atpakaļ","%n mēneši atpakaļ","%n mēnešiem"],
+ "last year" : "gājušajā gadā",
+ "_%n year ago_::_%n years ago_" : ["%n gadiem","%n gadiem","%n gadiem"],
+ "_%n hour ago_::_%n hours ago_" : ["%n stundas atpakaļ","%n stundas atpakaļ","%n stundām"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n minūtes atpakaļ","%n minūtes atpakaļ","%n minūtēm"],
+ "seconds ago" : "sekundēm",
+ "File name is too long" : "Faila nosaukums ir pārāk garš",
+ "Empty filename is not allowed" : "Tukšs faila nosaukums nav atļauts",
+ "__language_name__" : "Latviešu",
+ "Help" : "Palīdzība",
+ "Apps" : "Programmas",
+ "Users" : "Lietotāji",
+ "Unknown user" : "Nezināms lietotājs",
+ "Sharing" : "Koplietošana",
+ "Encryption" : "Šifrēšana",
+ "Additional settings" : "Papildu iestatījumi",
+ "%s enter the database username." : "%s ievadiet datubāzes lietotājvārdu.",
+ "%s enter the database name." : "%s ievadiet datubāzes nosaukumu.",
+ "%s you may not use dots in the database name" : "%s datubāžu nosaukumos nedrīkst izmantot punktus",
+ "Oracle connection could not be established" : "Nevar izveidot savienojumu ar Oracle",
+ "Oracle username and/or password not valid" : "Nav derīga Oracle parole un/vai lietotājvārds",
+ "PostgreSQL username and/or password not valid" : "Nav derīga PostgreSQL parole un/vai lietotājvārds",
+ "Set an admin username." : "Iestatiet administratora lietotājvārdu.",
+ "Set an admin password." : "Iestatiet administratora paroli.",
+ "Invalid Federated Cloud ID" : "Nederīgs Federated Cloud ID",
+ "%s shared »%s« with you" : "%s kopīgots »%s« ar jums",
+ "%s via %s" : "%s ar %s",
+ "Could not find category \"%s\"" : "Nevarēja atrast kategoriju “%s”",
+ "Sunday" : "Svētdiena",
+ "Monday" : "Pirmdiena",
+ "Tuesday" : "Otrdiena",
+ "Wednesday" : "Trešdiena",
+ "Thursday" : "Ceturtdiena",
+ "Friday" : "Piektdiena",
+ "Saturday" : "Sestdiena",
+ "Sun." : "Sv.",
+ "Mon." : "Pr.",
+ "Tue." : "Ot.",
+ "Wed." : "Tr.",
+ "Thu." : "Ce.",
+ "Fri." : "Pk.",
+ "Sat." : "Se.",
+ "Su" : "Sv",
+ "Mo" : "Pr",
+ "Tu" : "Ot",
+ "We" : "Tr",
+ "Th" : "Ce",
+ "Fr" : "Pi",
+ "Sa" : "Se",
+ "January" : "Janvāris",
+ "February" : "Februāris",
+ "March" : "Marts",
+ "April" : "Aprīlis",
+ "May" : "Maijs",
+ "June" : "Jūnijs",
+ "July" : "Jūlijs",
+ "August" : "Augusts",
+ "September" : "Septembris",
+ "October" : "Oktobris",
+ "November" : "Novembris",
+ "December" : "Decembris",
+ "Jan." : "Jan.",
+ "Feb." : "Feb.",
+ "Mar." : "Mar.",
+ "Apr." : "Apr.",
+ "May." : "Mai.",
+ "Jun." : "Jūn.",
+ "Jul." : "Jūl.",
+ "Aug." : "Aug.",
+ "Sep." : "Sep.",
+ "Oct." : "Okt.",
+ "Nov." : "Nov.",
+ "Dec." : "Dec.",
+ "A valid username must be provided" : "Jānorāda derīgs lietotājvārds",
+ "A valid password must be provided" : "Jānorāda derīga parole",
+ "The username is already being used" : "Šāds lietotājvārds jau tiek izmantots",
+ "User disabled" : "Lietotājs deaktivizēts",
+ "Login canceled by app" : "Pieteikšanās atcelta ar programmu",
+ "a safe home for all your data" : "droša vieta visiem jūsu datiem",
+ "File is currently busy, please try again later" : "Fails pašlaik ir aizņemts. lūdzu, vēlāk mēģiniet vēlreiz",
+ "Can't read file" : "Nevar nolasīt failu",
+ "Application is not enabled" : "Programma nav aktivēta",
+ "Authentication error" : "Autentifikācijas kļūda",
+ "Token expired. Please reload page." : "Pilnvarai ir beidzies termiņš. Lūdzu, pārlādējiet lapu.",
+ "Please ask your server administrator to install the module." : "Lūdzu, palūdziet savam servera administratoram, lai instalē moduli.",
+ "PHP module %s not installed." : "PHP modulis %s nav instalēts.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Tas ir iespējams, kešatmiņa / paātrinātājs, piemēram, Zend OPcache vai eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "PHP modulis ir uzstādīts, taču tas joprojām ir uzskatāms kā trūkstošs, pazudis?",
+ "Please ask your server administrator to restart the web server." : "Lūdzu, palūdziet savam servera administratoram, restartēt Web serveri.",
+ "PostgreSQL >= 9 required" : "PostgreSQL >= 9 nepieciešams",
+ "Please upgrade your database version" : "Lūdzu, atjauniniet datu bāzes versiju",
+ "Storage unauthorized. %s" : "Krātuve neautorizēta. %s",
+ "Storage incomplete configuration. %s" : "Storage incomplete configuration. %s",
+ "Storage connection error. %s" : "Datu savienojuma kļūda. %s",
+ "Storage is temporarily not available" : "Glabātuve īslaicīgi nav pieejama",
+ "Storage connection timeout. %s" : "Datu savienojuma taimauts. %s",
+ "APCu" : "APCu",
+ "Tips & tricks" : "Padomi un ieteikumi"
+},
+"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);");
diff --git a/lib/l10n/lv.json b/lib/l10n/lv.json
new file mode 100644
index 00000000000..a48d497552c
--- /dev/null
+++ b/lib/l10n/lv.json
@@ -0,0 +1,127 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Nevar rakstīt \"config\" mapē!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "To parasti var labot, dodot tīmekļa servera rakstīšanas piekļuvi config direktorijai",
+ "See %s" : "Skatīt %s",
+ "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Datnes no programmas %$1s netika aizvietotas pareizi. Pārliecinieties, vai tā ir versija, kas ir saderīga ar serveri.",
+ "Sample configuration detected" : "Atrasta konfigurācijas paraugs",
+ "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" : "Konstatēts, ka paraug konfigurācija ir nokopēta. Tas var izjaukt jūsu instalāciju un nav atbalstīts. Lūdzu, izlasiet dokumentāciju, pirms veicat izmaiņas config.php",
+ "%1$s and %2$s" : "%1$s un %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s un %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s un %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s un %5$s",
+ "PHP %s or higher is required." : "Ir nepieciešams PHP %s vai jaunāks.",
+ "PHP with a version lower than %s is required." : "Ir nepieciešams PHP vecāks kā %s.",
+ "%sbit or higher PHP required." : "Nepieciešams %sbit vai jaunāks PHP.",
+ "Following databases are supported: %s" : "Tiek atbalstītas šādas datu bāzes: %s",
+ "The command line tool %s could not be found" : "Komandrindas rīku %s nevarēja atrast",
+ "The library %s is not available." : "Bibliotēka %s nav pieejama.",
+ "Following platforms are supported: %s" : "Tiek atbalstītas šādas platformas: %s",
+ "Server version %s or higher is required." : "Ir vajadzīga servera versija %s vai jaunāka.",
+ "Server version %s or lower is required." : "Ir vajadzīga servera versija %s vai vecāka.",
+ "Unknown filetype" : "Nezināms datnes tips",
+ "Invalid image" : "Nederīgs attēls",
+ "Avatar image is not square" : "Avatar attēls nav kvadrāts",
+ "today" : "šodien",
+ "yesterday" : "vakar",
+ "_%n day ago_::_%n days ago_" : ["%n dienas atpakaļ","%n dienas atpakaļ","%n dienām"],
+ "last month" : "pagājušajā mēnesī",
+ "_%n month ago_::_%n months ago_" : ["%n mēneši atpakaļ","%n mēneši atpakaļ","%n mēnešiem"],
+ "last year" : "gājušajā gadā",
+ "_%n year ago_::_%n years ago_" : ["%n gadiem","%n gadiem","%n gadiem"],
+ "_%n hour ago_::_%n hours ago_" : ["%n stundas atpakaļ","%n stundas atpakaļ","%n stundām"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n minūtes atpakaļ","%n minūtes atpakaļ","%n minūtēm"],
+ "seconds ago" : "sekundēm",
+ "File name is too long" : "Faila nosaukums ir pārāk garš",
+ "Empty filename is not allowed" : "Tukšs faila nosaukums nav atļauts",
+ "__language_name__" : "Latviešu",
+ "Help" : "Palīdzība",
+ "Apps" : "Programmas",
+ "Users" : "Lietotāji",
+ "Unknown user" : "Nezināms lietotājs",
+ "Sharing" : "Koplietošana",
+ "Encryption" : "Šifrēšana",
+ "Additional settings" : "Papildu iestatījumi",
+ "%s enter the database username." : "%s ievadiet datubāzes lietotājvārdu.",
+ "%s enter the database name." : "%s ievadiet datubāzes nosaukumu.",
+ "%s you may not use dots in the database name" : "%s datubāžu nosaukumos nedrīkst izmantot punktus",
+ "Oracle connection could not be established" : "Nevar izveidot savienojumu ar Oracle",
+ "Oracle username and/or password not valid" : "Nav derīga Oracle parole un/vai lietotājvārds",
+ "PostgreSQL username and/or password not valid" : "Nav derīga PostgreSQL parole un/vai lietotājvārds",
+ "Set an admin username." : "Iestatiet administratora lietotājvārdu.",
+ "Set an admin password." : "Iestatiet administratora paroli.",
+ "Invalid Federated Cloud ID" : "Nederīgs Federated Cloud ID",
+ "%s shared »%s« with you" : "%s kopīgots »%s« ar jums",
+ "%s via %s" : "%s ar %s",
+ "Could not find category \"%s\"" : "Nevarēja atrast kategoriju “%s”",
+ "Sunday" : "Svētdiena",
+ "Monday" : "Pirmdiena",
+ "Tuesday" : "Otrdiena",
+ "Wednesday" : "Trešdiena",
+ "Thursday" : "Ceturtdiena",
+ "Friday" : "Piektdiena",
+ "Saturday" : "Sestdiena",
+ "Sun." : "Sv.",
+ "Mon." : "Pr.",
+ "Tue." : "Ot.",
+ "Wed." : "Tr.",
+ "Thu." : "Ce.",
+ "Fri." : "Pk.",
+ "Sat." : "Se.",
+ "Su" : "Sv",
+ "Mo" : "Pr",
+ "Tu" : "Ot",
+ "We" : "Tr",
+ "Th" : "Ce",
+ "Fr" : "Pi",
+ "Sa" : "Se",
+ "January" : "Janvāris",
+ "February" : "Februāris",
+ "March" : "Marts",
+ "April" : "Aprīlis",
+ "May" : "Maijs",
+ "June" : "Jūnijs",
+ "July" : "Jūlijs",
+ "August" : "Augusts",
+ "September" : "Septembris",
+ "October" : "Oktobris",
+ "November" : "Novembris",
+ "December" : "Decembris",
+ "Jan." : "Jan.",
+ "Feb." : "Feb.",
+ "Mar." : "Mar.",
+ "Apr." : "Apr.",
+ "May." : "Mai.",
+ "Jun." : "Jūn.",
+ "Jul." : "Jūl.",
+ "Aug." : "Aug.",
+ "Sep." : "Sep.",
+ "Oct." : "Okt.",
+ "Nov." : "Nov.",
+ "Dec." : "Dec.",
+ "A valid username must be provided" : "Jānorāda derīgs lietotājvārds",
+ "A valid password must be provided" : "Jānorāda derīga parole",
+ "The username is already being used" : "Šāds lietotājvārds jau tiek izmantots",
+ "User disabled" : "Lietotājs deaktivizēts",
+ "Login canceled by app" : "Pieteikšanās atcelta ar programmu",
+ "a safe home for all your data" : "droša vieta visiem jūsu datiem",
+ "File is currently busy, please try again later" : "Fails pašlaik ir aizņemts. lūdzu, vēlāk mēģiniet vēlreiz",
+ "Can't read file" : "Nevar nolasīt failu",
+ "Application is not enabled" : "Programma nav aktivēta",
+ "Authentication error" : "Autentifikācijas kļūda",
+ "Token expired. Please reload page." : "Pilnvarai ir beidzies termiņš. Lūdzu, pārlādējiet lapu.",
+ "Please ask your server administrator to install the module." : "Lūdzu, palūdziet savam servera administratoram, lai instalē moduli.",
+ "PHP module %s not installed." : "PHP modulis %s nav instalēts.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Tas ir iespējams, kešatmiņa / paātrinātājs, piemēram, Zend OPcache vai eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "PHP modulis ir uzstādīts, taču tas joprojām ir uzskatāms kā trūkstošs, pazudis?",
+ "Please ask your server administrator to restart the web server." : "Lūdzu, palūdziet savam servera administratoram, restartēt Web serveri.",
+ "PostgreSQL >= 9 required" : "PostgreSQL >= 9 nepieciešams",
+ "Please upgrade your database version" : "Lūdzu, atjauniniet datu bāzes versiju",
+ "Storage unauthorized. %s" : "Krātuve neautorizēta. %s",
+ "Storage incomplete configuration. %s" : "Storage incomplete configuration. %s",
+ "Storage connection error. %s" : "Datu savienojuma kļūda. %s",
+ "Storage is temporarily not available" : "Glabātuve īslaicīgi nav pieejama",
+ "Storage connection timeout. %s" : "Datu savienojuma taimauts. %s",
+ "APCu" : "APCu",
+ "Tips & tricks" : "Padomi un ieteikumi"
+},"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"
+} \ No newline at end of file
diff --git a/lib/l10n/mk.js b/lib/l10n/mk.js
new file mode 100644
index 00000000000..b3e874b9250
--- /dev/null
+++ b/lib/l10n/mk.js
@@ -0,0 +1,32 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Не можам да впишувам во \"config\" директориумот!",
+ "Unknown filetype" : "Непознат тип на датотека",
+ "Invalid image" : "Невалидна фотографија",
+ "today" : "денеска",
+ "yesterday" : "вчера",
+ "last month" : "минатиот месец",
+ "last year" : "минатата година",
+ "seconds ago" : "пред секунди",
+ "__language_name__" : "македонски",
+ "Apps" : "Аппликации",
+ "Users" : "Корисници",
+ "Unknown user" : "Непознат корисник",
+ "%s enter the database username." : "%s внеси го корисничкото име за базата.",
+ "%s enter the database name." : "%s внеси го името на базата.",
+ "%s you may not use dots in the database name" : "%s не можеш да користиш точки во името на базата",
+ "Oracle username and/or password not valid" : "Oracle корисничкото име и/или лозинката не се валидни",
+ "PostgreSQL username and/or password not valid" : "PostgreSQL корисничкото име и/или лозинка не се валидни",
+ "Set an admin username." : "Постави администраторско корисничко име",
+ "Set an admin password." : "Постави администраторска лозинка.",
+ "%s shared »%s« with you" : "%s споделено »%s« со вас",
+ "Could not find category \"%s\"" : "Не можам да најдам категорија „%s“",
+ "A valid username must be provided" : "Мора да се обезбеди валидно корисничко име ",
+ "A valid password must be provided" : "Мора да се обезбеди валидна лозинка",
+ "The username is already being used" : "Корисничкото име е веќе во употреба",
+ "Application is not enabled" : "Апликацијата не е овозможена",
+ "Authentication error" : "Грешка во автентикација",
+ "Token expired. Please reload page." : "Жетонот е истечен. Ве молам превчитајте ја страницата."
+},
+"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;");
diff --git a/lib/l10n/mk.json b/lib/l10n/mk.json
new file mode 100644
index 00000000000..c29ee660421
--- /dev/null
+++ b/lib/l10n/mk.json
@@ -0,0 +1,30 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Не можам да впишувам во \"config\" директориумот!",
+ "Unknown filetype" : "Непознат тип на датотека",
+ "Invalid image" : "Невалидна фотографија",
+ "today" : "денеска",
+ "yesterday" : "вчера",
+ "last month" : "минатиот месец",
+ "last year" : "минатата година",
+ "seconds ago" : "пред секунди",
+ "__language_name__" : "македонски",
+ "Apps" : "Аппликации",
+ "Users" : "Корисници",
+ "Unknown user" : "Непознат корисник",
+ "%s enter the database username." : "%s внеси го корисничкото име за базата.",
+ "%s enter the database name." : "%s внеси го името на базата.",
+ "%s you may not use dots in the database name" : "%s не можеш да користиш точки во името на базата",
+ "Oracle username and/or password not valid" : "Oracle корисничкото име и/или лозинката не се валидни",
+ "PostgreSQL username and/or password not valid" : "PostgreSQL корисничкото име и/или лозинка не се валидни",
+ "Set an admin username." : "Постави администраторско корисничко име",
+ "Set an admin password." : "Постави администраторска лозинка.",
+ "%s shared »%s« with you" : "%s споделено »%s« со вас",
+ "Could not find category \"%s\"" : "Не можам да најдам категорија „%s“",
+ "A valid username must be provided" : "Мора да се обезбеди валидно корисничко име ",
+ "A valid password must be provided" : "Мора да се обезбеди валидна лозинка",
+ "The username is already being used" : "Корисничкото име е веќе во употреба",
+ "Application is not enabled" : "Апликацијата не е овозможена",
+ "Authentication error" : "Грешка во автентикација",
+ "Token expired. Please reload page." : "Жетонот е истечен. Ве молам превчитајте ја страницата."
+},"pluralForm" :"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"
+} \ No newline at end of file
diff --git a/lib/l10n/mn.js b/lib/l10n/mn.js
new file mode 100644
index 00000000000..d2539ab0791
--- /dev/null
+++ b/lib/l10n/mn.js
@@ -0,0 +1,20 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "\"config\" хавтас руу бичих боломжгүй байна!",
+ "Invalid image" : "буруу зураг",
+ "Avatar image is not square" : "Хөрөг зураг дөрвөлжин биш",
+ "today" : "өнөөдөр",
+ "yesterday" : "өчигдөр",
+ "last month" : "сүүлийн сар",
+ "last year" : "сүүлийн жил",
+ "seconds ago" : "секундийн өмнө",
+ "File name is a reserved word" : "Файлын нэр нь нийцгүй үг",
+ "File name contains at least one invalid character" : "файлын нэр нь хамгийн багадаа нэг нь хүчингүй тэмдэгт агуулж байна",
+ "File name is too long" : "Файлын нэр хэтэрхий урт байна",
+ "Dot files are not allowed" : "Dot файлууд зөвшөөрөл байхгүй байна",
+ "__language_name__" : "хэлний нэр",
+ "June" : "Зургадугаар сар",
+ "November" : "Арван нэгдүгээр сар"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/mn.json b/lib/l10n/mn.json
new file mode 100644
index 00000000000..10ed4980ac8
--- /dev/null
+++ b/lib/l10n/mn.json
@@ -0,0 +1,18 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "\"config\" хавтас руу бичих боломжгүй байна!",
+ "Invalid image" : "буруу зураг",
+ "Avatar image is not square" : "Хөрөг зураг дөрвөлжин биш",
+ "today" : "өнөөдөр",
+ "yesterday" : "өчигдөр",
+ "last month" : "сүүлийн сар",
+ "last year" : "сүүлийн жил",
+ "seconds ago" : "секундийн өмнө",
+ "File name is a reserved word" : "Файлын нэр нь нийцгүй үг",
+ "File name contains at least one invalid character" : "файлын нэр нь хамгийн багадаа нэг нь хүчингүй тэмдэгт агуулж байна",
+ "File name is too long" : "Файлын нэр хэтэрхий урт байна",
+ "Dot files are not allowed" : "Dot файлууд зөвшөөрөл байхгүй байна",
+ "__language_name__" : "хэлний нэр",
+ "June" : "Зургадугаар сар",
+ "November" : "Арван нэгдүгээр сар"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/ms_MY.js b/lib/l10n/ms_MY.js
new file mode 100644
index 00000000000..5a09b3f3d85
--- /dev/null
+++ b/lib/l10n/ms_MY.js
@@ -0,0 +1,9 @@
+OC.L10N.register(
+ "lib",
+ {
+ "__language_name__" : "Bahasa Melayu",
+ "Apps" : "Aplikasi",
+ "Users" : "Pengguna",
+ "Authentication error" : "Ralat pengesahan"
+},
+"nplurals=1; plural=0;");
diff --git a/lib/l10n/ms_MY.json b/lib/l10n/ms_MY.json
new file mode 100644
index 00000000000..a68af8c01fa
--- /dev/null
+++ b/lib/l10n/ms_MY.json
@@ -0,0 +1,7 @@
+{ "translations": {
+ "__language_name__" : "Bahasa Melayu",
+ "Apps" : "Aplikasi",
+ "Users" : "Pengguna",
+ "Authentication error" : "Ralat pengesahan"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/lib/l10n/nb.js b/lib/l10n/nb.js
index 261ecd7d1c2..f8a2efe333a 100644
--- a/lib/l10n/nb.js
+++ b/lib/l10n/nb.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Tomt filnavn er ikke tillatt",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Programmet \"%s\" kan ikke installeres på grunn av at appinfo-filen ikke kan leses.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Programmet \"%s\" kan ikke installere fordi det ikke er kompatibel med denne tjenerversjonen.",
+ "__language_name__" : "Norsk bokmål",
"This is an automatically sent email, please do not reply." : "Dette er en automatisk sendt e-post, ikke svar.",
"Help" : "Hjelp",
"Apps" : "Programmer",
@@ -64,18 +65,17 @@ OC.L10N.register(
"Log out" : "Logg ut",
"Users" : "Brukere",
"Unknown user" : "Ukjent bruker",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Opprett",
+ "Change" : "Endre",
+ "Delete" : "Slett",
+ "Share" : "Del",
"Basic settings" : "Grunninnstillinger",
"Sharing" : "Deling",
"Security" : "Sikkerhet",
"Encryption" : "Kryptering",
"Additional settings" : "Flere innstillinger",
- "Tips & tricks" : "Tips og triks",
"Personal info" : "Personlig informasjon",
- "Sync clients" : "Synkroniser klienter",
"Unlimited" : "Ubegrenset",
- "__language_name__" : "Norsk bokmål",
"Verifying" : "Bekrefter",
"Verifying …" : "Bekrefter…",
"Verify" : "Bekreft",
@@ -196,7 +196,7 @@ OC.L10N.register(
"No database drivers (sqlite, mysql, or postgresql) installed." : "Ingen databasedrivere (sqlite, mysql, or postgresql) installert.",
"Cannot write into \"config\" directory" : "Kan ikke skrive i \"config\"-mappen",
"Cannot write into \"apps\" directory" : "Kan ikke skrive i \"apps\"-mappen",
- "This can usually be fixed by giving the webserver write access to the apps directory or disabling the appstore in the config file. See %s" : "Dette kan vanligvis ordnes ved å gi vev-tjeneren skrivetilgang til apps-mappen eller ved å skru av programbutikken i config-fila. Se %s",
+ "This can usually be fixed by giving the webserver write access to the apps directory or disabling the appstore in the config file. See %s" : "Dette kan vanligvis ordnes ved å gi vev-tjeneren skrivetilgang til apps-mappen eller ved å skru av programbutikken i config-filen. Se %s",
"Cannot create \"data\" directory" : "Kan ikke opprette \"data\"-mappe",
"This can usually be fixed by giving the webserver write access to the root directory. See %s" : "Dette kan vanligvis ordnes ved å gi vev-tjeneren skrivetilgang til root-mappen. Se %s",
"Permissions can usually be fixed by giving the webserver write access to the root directory. See %s." : "Tillatelser kan vanligvis ordnes ved å gi vevtjeneren skrivetilgang til rotmappa. Se %s.",
@@ -227,6 +227,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Ikke komplett oppsett for lager. %s",
"Storage connection error. %s" : "Tilkoblingsfeil for lager. %s",
"Storage is temporarily not available" : "Lagring er midlertidig utilgjengelig",
- "Storage connection timeout. %s" : "Tidsavbrudd ved tilkobling av lager: %s"
+ "Storage connection timeout. %s" : "Tidsavbrudd ved tilkobling av lager: %s",
+ "Personal" : "Personlig",
+ "Admin" : "Administrator",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tips og triks",
+ "DB Error: \"%s\"" : "Databasefeil: \"%s\"",
+ "Offending command was: \"%s\"" : "Kommandoen som mislyktes: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "Kommandoen som mislyktes var: \"%s\", navn: %s, passord: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Setting av tillatelser for %s mislyktes, fordi tillatelsene gikk ut over tillatelsene som er gitt til %s",
+ "Setting permissions for %s failed, because the item was not found" : "Setting av tillatelser for %s mislyktes, fordi elementet ikke ble funnet",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Kan ikke fjerne utløpsdato. Delinger må ha en utløpsdato.",
+ "Cannot increase permissions of %s" : "Kan ikke øke tillatelser for %s",
+ "Files can't be shared with delete permissions" : "Filer kan ikke deles med rettigheter til sletting",
+ "Files can't be shared with create permissions" : "Filer kan ikke deles med rettigheter til å opprette",
+ "Cannot set expiration date more than %s days in the future" : "Kan ikke sette utløpsdato mer enn %s dager fram i tid",
+ "No app name specified" : "Intet programnavn spesifisert",
+ "App '%s' could not be installed!" : "Programmet '%s' kunne ikke installeres!",
+ "Sync clients" : "Synkroniser klienter"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/nb.json b/lib/l10n/nb.json
index 238bcde7a2c..8333ef492ef 100644
--- a/lib/l10n/nb.json
+++ b/lib/l10n/nb.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "Tomt filnavn er ikke tillatt",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Programmet \"%s\" kan ikke installeres på grunn av at appinfo-filen ikke kan leses.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Programmet \"%s\" kan ikke installere fordi det ikke er kompatibel med denne tjenerversjonen.",
+ "__language_name__" : "Norsk bokmål",
"This is an automatically sent email, please do not reply." : "Dette er en automatisk sendt e-post, ikke svar.",
"Help" : "Hjelp",
"Apps" : "Programmer",
@@ -62,18 +63,17 @@
"Log out" : "Logg ut",
"Users" : "Brukere",
"Unknown user" : "Ukjent bruker",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Opprett",
+ "Change" : "Endre",
+ "Delete" : "Slett",
+ "Share" : "Del",
"Basic settings" : "Grunninnstillinger",
"Sharing" : "Deling",
"Security" : "Sikkerhet",
"Encryption" : "Kryptering",
"Additional settings" : "Flere innstillinger",
- "Tips & tricks" : "Tips og triks",
"Personal info" : "Personlig informasjon",
- "Sync clients" : "Synkroniser klienter",
"Unlimited" : "Ubegrenset",
- "__language_name__" : "Norsk bokmål",
"Verifying" : "Bekrefter",
"Verifying …" : "Bekrefter…",
"Verify" : "Bekreft",
@@ -194,7 +194,7 @@
"No database drivers (sqlite, mysql, or postgresql) installed." : "Ingen databasedrivere (sqlite, mysql, or postgresql) installert.",
"Cannot write into \"config\" directory" : "Kan ikke skrive i \"config\"-mappen",
"Cannot write into \"apps\" directory" : "Kan ikke skrive i \"apps\"-mappen",
- "This can usually be fixed by giving the webserver write access to the apps directory or disabling the appstore in the config file. See %s" : "Dette kan vanligvis ordnes ved å gi vev-tjeneren skrivetilgang til apps-mappen eller ved å skru av programbutikken i config-fila. Se %s",
+ "This can usually be fixed by giving the webserver write access to the apps directory or disabling the appstore in the config file. See %s" : "Dette kan vanligvis ordnes ved å gi vev-tjeneren skrivetilgang til apps-mappen eller ved å skru av programbutikken i config-filen. Se %s",
"Cannot create \"data\" directory" : "Kan ikke opprette \"data\"-mappe",
"This can usually be fixed by giving the webserver write access to the root directory. See %s" : "Dette kan vanligvis ordnes ved å gi vev-tjeneren skrivetilgang til root-mappen. Se %s",
"Permissions can usually be fixed by giving the webserver write access to the root directory. See %s." : "Tillatelser kan vanligvis ordnes ved å gi vevtjeneren skrivetilgang til rotmappa. Se %s.",
@@ -225,6 +225,24 @@
"Storage incomplete configuration. %s" : "Ikke komplett oppsett for lager. %s",
"Storage connection error. %s" : "Tilkoblingsfeil for lager. %s",
"Storage is temporarily not available" : "Lagring er midlertidig utilgjengelig",
- "Storage connection timeout. %s" : "Tidsavbrudd ved tilkobling av lager: %s"
+ "Storage connection timeout. %s" : "Tidsavbrudd ved tilkobling av lager: %s",
+ "Personal" : "Personlig",
+ "Admin" : "Administrator",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tips og triks",
+ "DB Error: \"%s\"" : "Databasefeil: \"%s\"",
+ "Offending command was: \"%s\"" : "Kommandoen som mislyktes: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "Kommandoen som mislyktes var: \"%s\", navn: %s, passord: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Setting av tillatelser for %s mislyktes, fordi tillatelsene gikk ut over tillatelsene som er gitt til %s",
+ "Setting permissions for %s failed, because the item was not found" : "Setting av tillatelser for %s mislyktes, fordi elementet ikke ble funnet",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Kan ikke fjerne utløpsdato. Delinger må ha en utløpsdato.",
+ "Cannot increase permissions of %s" : "Kan ikke øke tillatelser for %s",
+ "Files can't be shared with delete permissions" : "Filer kan ikke deles med rettigheter til sletting",
+ "Files can't be shared with create permissions" : "Filer kan ikke deles med rettigheter til å opprette",
+ "Cannot set expiration date more than %s days in the future" : "Kan ikke sette utløpsdato mer enn %s dager fram i tid",
+ "No app name specified" : "Intet programnavn spesifisert",
+ "App '%s' could not be installed!" : "Programmet '%s' kunne ikke installeres!",
+ "Sync clients" : "Synkroniser klienter"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/nl.js b/lib/l10n/nl.js
index 41f9a528b5f..512924b2416 100644
--- a/lib/l10n/nl.js
+++ b/lib/l10n/nl.js
@@ -27,6 +27,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "De volgende platformen worden ondersteund: %s",
"Server version %s or higher is required." : "Serverversie %s of hoger vereist.",
"Server version %s or lower is required." : "Serverversie %s of lager vereist.",
+ "Logged in user must be an admin" : "Ingelogde gebruiker moet een beheerder zijn",
"Unknown filetype" : "Onbekend bestandsformaat",
"Invalid image" : "Ongeldige afbeelding",
"Avatar image is not square" : "Avatar afbeelding is niet vierkant",
@@ -57,6 +58,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Een lege bestandsnaam is niet toegestaan",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "App \"%s\" kan niet worden geïnstalleerd, omdat het app info bestand niet gelezen kan worden.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "App \"%s\" kan niet worden geïnstalleerd, omdat deze niet compatible is met deze versie van de server.",
+ "__language_name__" : "Nederlands",
"This is an automatically sent email, please do not reply." : "Dit is een automatisch gegenereerde e-mail, dus reageren is niet mogelijk.",
"Help" : "Help",
"Apps" : "Apps",
@@ -64,18 +66,17 @@ OC.L10N.register(
"Log out" : "Uitloggen",
"Users" : "Gebruikers",
"Unknown user" : "Onbekende gebruiker",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Aanmaken",
+ "Change" : "Wijzigen",
+ "Delete" : "Verwijderen",
+ "Share" : "Delen",
"Basic settings" : "Basis-instellingen",
"Sharing" : "Delen",
"Security" : "Beveiliging",
"Encryption" : "Versleuteling",
"Additional settings" : "Aanvullende instellingen",
- "Tips & tricks" : "Tips & trucs",
"Personal info" : "Persoonlijke informatie",
- "Sync clients" : "Synchronisatie clients",
"Unlimited" : "Ongelimiteerd",
- "__language_name__" : "Nederlands",
"Verifying" : "Verifiëren",
"Verifying …" : "Verifiëren...",
"Verify" : "Verifieer",
@@ -227,6 +228,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Incomplete opslag configuratie. %s",
"Storage connection error. %s" : "Opslag verbindingsfout. %s",
"Storage is temporarily not available" : "Opslag is tijdelijk niet beschikbaar",
- "Storage connection timeout. %s" : "Opslag verbinding time-out. %s"
+ "Storage connection timeout. %s" : "Opslag verbinding time-out. %s",
+ "Personal" : "Persoonlijk",
+ "Admin" : "Beheerder",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tips & trucs",
+ "DB Error: \"%s\"" : "DB Fout: \"%s\"",
+ "Offending command was: \"%s\"" : "Onjuiste commando was: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "Onjuiste commando was: \"%s\", naam: %s, wachtwoord: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Instellen van de gebruik rechten voor %s is mislukt, omdat de rechten hoger zijn dan de aan %s toegekende gebruik rechten",
+ "Setting permissions for %s failed, because the item was not found" : "Instellen van de gebruik rechten voor %s is mislukt, omdat het object niet is gevonden",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Kan verval datum niet weghalen. Gedeelte folders moeten een vervaldatum hebben.",
+ "Cannot increase permissions of %s" : "Kan de rechten van %s niet verhogen.",
+ "Files can't be shared with delete permissions" : "Bestanden kunnen niet gedeeld worden met 'verwijder' rechten",
+ "Files can't be shared with create permissions" : "Bestanden kunnen niet gedeeld worden met 'creëer' rechten",
+ "Cannot set expiration date more than %s days in the future" : "Kan de vervaldatum niet meer dan %s dagen in de toekomst instellen",
+ "No app name specified" : "Geen app naam gespecificeerd",
+ "App '%s' could not be installed!" : "App '%s' kon niet geïnstalleerd worden!",
+ "Sync clients" : "Synchronisatie clients"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/nl.json b/lib/l10n/nl.json
index d33e10b0c7a..8e8cd0ee92c 100644
--- a/lib/l10n/nl.json
+++ b/lib/l10n/nl.json
@@ -25,6 +25,7 @@
"Following platforms are supported: %s" : "De volgende platformen worden ondersteund: %s",
"Server version %s or higher is required." : "Serverversie %s of hoger vereist.",
"Server version %s or lower is required." : "Serverversie %s of lager vereist.",
+ "Logged in user must be an admin" : "Ingelogde gebruiker moet een beheerder zijn",
"Unknown filetype" : "Onbekend bestandsformaat",
"Invalid image" : "Ongeldige afbeelding",
"Avatar image is not square" : "Avatar afbeelding is niet vierkant",
@@ -55,6 +56,7 @@
"Empty filename is not allowed" : "Een lege bestandsnaam is niet toegestaan",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "App \"%s\" kan niet worden geïnstalleerd, omdat het app info bestand niet gelezen kan worden.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "App \"%s\" kan niet worden geïnstalleerd, omdat deze niet compatible is met deze versie van de server.",
+ "__language_name__" : "Nederlands",
"This is an automatically sent email, please do not reply." : "Dit is een automatisch gegenereerde e-mail, dus reageren is niet mogelijk.",
"Help" : "Help",
"Apps" : "Apps",
@@ -62,18 +64,17 @@
"Log out" : "Uitloggen",
"Users" : "Gebruikers",
"Unknown user" : "Onbekende gebruiker",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Aanmaken",
+ "Change" : "Wijzigen",
+ "Delete" : "Verwijderen",
+ "Share" : "Delen",
"Basic settings" : "Basis-instellingen",
"Sharing" : "Delen",
"Security" : "Beveiliging",
"Encryption" : "Versleuteling",
"Additional settings" : "Aanvullende instellingen",
- "Tips & tricks" : "Tips & trucs",
"Personal info" : "Persoonlijke informatie",
- "Sync clients" : "Synchronisatie clients",
"Unlimited" : "Ongelimiteerd",
- "__language_name__" : "Nederlands",
"Verifying" : "Verifiëren",
"Verifying …" : "Verifiëren...",
"Verify" : "Verifieer",
@@ -225,6 +226,24 @@
"Storage incomplete configuration. %s" : "Incomplete opslag configuratie. %s",
"Storage connection error. %s" : "Opslag verbindingsfout. %s",
"Storage is temporarily not available" : "Opslag is tijdelijk niet beschikbaar",
- "Storage connection timeout. %s" : "Opslag verbinding time-out. %s"
+ "Storage connection timeout. %s" : "Opslag verbinding time-out. %s",
+ "Personal" : "Persoonlijk",
+ "Admin" : "Beheerder",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tips & trucs",
+ "DB Error: \"%s\"" : "DB Fout: \"%s\"",
+ "Offending command was: \"%s\"" : "Onjuiste commando was: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "Onjuiste commando was: \"%s\", naam: %s, wachtwoord: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Instellen van de gebruik rechten voor %s is mislukt, omdat de rechten hoger zijn dan de aan %s toegekende gebruik rechten",
+ "Setting permissions for %s failed, because the item was not found" : "Instellen van de gebruik rechten voor %s is mislukt, omdat het object niet is gevonden",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Kan verval datum niet weghalen. Gedeelte folders moeten een vervaldatum hebben.",
+ "Cannot increase permissions of %s" : "Kan de rechten van %s niet verhogen.",
+ "Files can't be shared with delete permissions" : "Bestanden kunnen niet gedeeld worden met 'verwijder' rechten",
+ "Files can't be shared with create permissions" : "Bestanden kunnen niet gedeeld worden met 'creëer' rechten",
+ "Cannot set expiration date more than %s days in the future" : "Kan de vervaldatum niet meer dan %s dagen in de toekomst instellen",
+ "No app name specified" : "Geen app naam gespecificeerd",
+ "App '%s' could not be installed!" : "App '%s' kon niet geïnstalleerd worden!",
+ "Sync clients" : "Synchronisatie clients"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/nn_NO.js b/lib/l10n/nn_NO.js
new file mode 100644
index 00000000000..357b3154277
--- /dev/null
+++ b/lib/l10n/nn_NO.js
@@ -0,0 +1,19 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Unknown filetype" : "Ukjend filtype",
+ "Invalid image" : "Ugyldig bilete",
+ "today" : "i dag",
+ "yesterday" : "i går",
+ "last month" : "førre månad",
+ "last year" : "i fjor",
+ "seconds ago" : "sekund sidan",
+ "__language_name__" : "Nynorsk",
+ "Apps" : "Program",
+ "Users" : "Brukarar",
+ "%s shared »%s« with you" : "%s delte «%s» med deg",
+ "A valid username must be provided" : "Du må oppgje eit gyldig brukarnamn",
+ "A valid password must be provided" : "Du må oppgje eit gyldig passord",
+ "Authentication error" : "Feil i autentisering"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/nn_NO.json b/lib/l10n/nn_NO.json
new file mode 100644
index 00000000000..8ce7a266bd2
--- /dev/null
+++ b/lib/l10n/nn_NO.json
@@ -0,0 +1,17 @@
+{ "translations": {
+ "Unknown filetype" : "Ukjend filtype",
+ "Invalid image" : "Ugyldig bilete",
+ "today" : "i dag",
+ "yesterday" : "i går",
+ "last month" : "førre månad",
+ "last year" : "i fjor",
+ "seconds ago" : "sekund sidan",
+ "__language_name__" : "Nynorsk",
+ "Apps" : "Program",
+ "Users" : "Brukarar",
+ "%s shared »%s« with you" : "%s delte «%s» med deg",
+ "A valid username must be provided" : "Du må oppgje eit gyldig brukarnamn",
+ "A valid password must be provided" : "Du må oppgje eit gyldig passord",
+ "Authentication error" : "Feil i autentisering"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/pl.js b/lib/l10n/pl.js
index c58bcb150b6..eb0e65e28f1 100644
--- a/lib/l10n/pl.js
+++ b/lib/l10n/pl.js
@@ -52,6 +52,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Pusta nazwa nie jest dozwolona.",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Aplikacja \"%s\" nie może zostać zainstalowana, ponieważ plik informacyjny nie może zostać odczytany.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Aplikacja \"%s\" nie może zostać zainstalowana, ponieważ jest niekompatybilna z obecną wersją serwera.",
+ "__language_name__" : "polski",
"This is an automatically sent email, please do not reply." : "To jest automatycznie wysłany e-mail, proszę nie odpowiadać na niego.",
"Help" : "Pomoc",
"Apps" : "Aplikacje",
@@ -59,20 +60,18 @@ OC.L10N.register(
"Log out" : "Wyloguj",
"Users" : "Użytkownicy",
"Unknown user" : "Nieznany użytkownik",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Utwórz",
+ "Change" : "Zmień",
+ "Delete" : "Usuń",
"Basic settings" : "Ustawienia podstawowe",
"Sharing" : "Udostępnianie",
"Security" : "Bepieczeństwo",
"Encryption" : "Szyfrowanie",
"Additional settings" : "Ustawienia dodatkowe",
- "Tips & tricks" : "Porady i wskazówki",
"Personal info" : "Informacje Osobiste",
- "Sync clients" : "Synchronizuj z klientami",
"Unlimited" : "Nielimitowane",
- "__language_name__" : "__nazwa_języka__",
"Verifying" : "Weryfikacja",
- "Verifying …" : "Weryfikacja...",
+ "Verifying …" : "Weryfikacja…",
"Verify" : "Zweryfikuj",
"%s enter the database username and name." : "Podaj nazwę bazy danych i nazwę użytkownika %s",
"%s enter the database username." : "Podaj nazwę użytkownika %s",
@@ -222,6 +221,10 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Niekompletna konfiguracja magazynu. %s",
"Storage connection error. %s" : "Błąd połączenia z magazynem. %s",
"Storage is temporarily not available" : "Magazyn jest tymczasowo niedostępny",
- "Storage connection timeout. %s" : "Limit czasu połączenia do magazynu został przekroczony. %s"
+ "Storage connection timeout. %s" : "Limit czasu połączenia do magazynu został przekroczony. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Porady i wskazówki",
+ "Sync clients" : "Synchronizuj z klientami"
},
"nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);");
diff --git a/lib/l10n/pl.json b/lib/l10n/pl.json
index be3165da463..7c70d4dd1f5 100644
--- a/lib/l10n/pl.json
+++ b/lib/l10n/pl.json
@@ -50,6 +50,7 @@
"Empty filename is not allowed" : "Pusta nazwa nie jest dozwolona.",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Aplikacja \"%s\" nie może zostać zainstalowana, ponieważ plik informacyjny nie może zostać odczytany.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Aplikacja \"%s\" nie może zostać zainstalowana, ponieważ jest niekompatybilna z obecną wersją serwera.",
+ "__language_name__" : "polski",
"This is an automatically sent email, please do not reply." : "To jest automatycznie wysłany e-mail, proszę nie odpowiadać na niego.",
"Help" : "Pomoc",
"Apps" : "Aplikacje",
@@ -57,20 +58,18 @@
"Log out" : "Wyloguj",
"Users" : "Użytkownicy",
"Unknown user" : "Nieznany użytkownik",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Utwórz",
+ "Change" : "Zmień",
+ "Delete" : "Usuń",
"Basic settings" : "Ustawienia podstawowe",
"Sharing" : "Udostępnianie",
"Security" : "Bepieczeństwo",
"Encryption" : "Szyfrowanie",
"Additional settings" : "Ustawienia dodatkowe",
- "Tips & tricks" : "Porady i wskazówki",
"Personal info" : "Informacje Osobiste",
- "Sync clients" : "Synchronizuj z klientami",
"Unlimited" : "Nielimitowane",
- "__language_name__" : "__nazwa_języka__",
"Verifying" : "Weryfikacja",
- "Verifying …" : "Weryfikacja...",
+ "Verifying …" : "Weryfikacja…",
"Verify" : "Zweryfikuj",
"%s enter the database username and name." : "Podaj nazwę bazy danych i nazwę użytkownika %s",
"%s enter the database username." : "Podaj nazwę użytkownika %s",
@@ -220,6 +219,10 @@
"Storage incomplete configuration. %s" : "Niekompletna konfiguracja magazynu. %s",
"Storage connection error. %s" : "Błąd połączenia z magazynem. %s",
"Storage is temporarily not available" : "Magazyn jest tymczasowo niedostępny",
- "Storage connection timeout. %s" : "Limit czasu połączenia do magazynu został przekroczony. %s"
+ "Storage connection timeout. %s" : "Limit czasu połączenia do magazynu został przekroczony. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Porady i wskazówki",
+ "Sync clients" : "Synchronizuj z klientami"
},"pluralForm" :"nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);"
} \ No newline at end of file
diff --git a/lib/l10n/pt_BR.js b/lib/l10n/pt_BR.js
index c1a9321d0b7..7b650244b3d 100644
--- a/lib/l10n/pt_BR.js
+++ b/lib/l10n/pt_BR.js
@@ -4,7 +4,9 @@ OC.L10N.register(
"Cannot write into \"config\" directory!" : "Não é possível gravar no diretório \"config\"!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Isso geralmente pode ser corrigido dando o acesso de escritura ao webserver para o diretório de configuração",
"See %s" : "Ver %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Ou, se você preferir manter o arquivo config.php somente para leitura, defina a opção \"config_is_read_only\" como true.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Normalmente isso pode ser resolvido dando ao webserver permissão de escritura no diretório config. Veja %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Ou, se você preferir manter o arquivo config.php somente para leitura, defina a opção \"config_is_read_only\" como true. Veja %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Os arquivos do aplicativo %$1s não foram substituídos corretamente. Certifique-se de que é uma versão compatível com o servidor.",
"Sample configuration detected" : "Configuração de exemplo detectada",
"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" : "Foi detectado que a configuração de exemplo foi copiada. Isso pode terminar sua instalação e não é suportado. Por favor leia a documentação antes de realizar mudanças no config.php",
@@ -27,6 +29,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "As seguintes plataformas são suportadas: %s",
"Server version %s or higher is required." : "É requerido um servidor da versão %s ou superior.",
"Server version %s or lower is required." : "É requerido um servidor da versão %s ou abaixo.",
+ "Logged in user must be an admin" : "O usuário conectado deve ser um administrador",
"Unknown filetype" : "Tipo de arquivo desconhecido",
"Invalid image" : "Imagem inválida",
"Avatar image is not square" : "A imagem do avatar não é quadrada",
@@ -57,6 +60,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Nome vazio para arquivo não é permitido.",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "O aplicativo \"%s\" não pode ser instalado pois o arquivo appinfo não pôde ser lido.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "O aplicativo \"%s\" não pode ser instalado pois não é compatível com a versão do servidor.",
+ "__language_name__" : "Português Brasileiro",
"This is an automatically sent email, please do not reply." : "Este é um e-mail enviado automaticamente. Por favor, não responda.",
"Help" : "Ajuda",
"Apps" : "Aplicativos",
@@ -64,18 +68,20 @@ OC.L10N.register(
"Log out" : "Sair",
"Users" : "Usuários",
"Unknown user" : "Usuário desconhecido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Criar",
+ "Change" : "Mudar",
+ "Delete" : "Excluir",
+ "Share" : "Compartilhar",
+ "Overview" : "Visão Geral",
"Basic settings" : "Configurações básicas",
"Sharing" : "Compartilhamento",
"Security" : "Segurança",
"Encryption" : "Criptografia",
+ "Groupware" : "Groupware",
"Additional settings" : "Configurações adicionais",
- "Tips & tricks" : "Dicas & truques",
"Personal info" : "Informação Pessoal",
- "Sync clients" : "Clientes de sincronização",
+ "Mobile & desktop" : "Móvel & desktop",
"Unlimited" : "Ilimitado",
- "__language_name__" : "__language_name__",
"Verifying" : "Verificando",
"Verifying …" : "Verificando...",
"Verify" : "Verificar",
@@ -222,6 +228,11 @@ OC.L10N.register(
"Check the value of \"datadirectory\" in your configuration" : "Verifique o valor do \"datadirectory\" na sua configuração",
"Your data directory is invalid" : "Seu diretório de dados é inválido",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assegure-se que exista um arquivo chamado \".ocdata\" na raiz do diretório \"data\".",
+ "Action \"%s\" not supported or implemented." : "Ação \"%s\" não suportada ou implementada.",
+ "Authentication failed, wrong token or provider ID given" : "Falha na autenticação, token ou ID do provedor errados",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Parâmetros ausentes para concluir a solicitação: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "Id \"%s\" já usada pelo provedor de federação na nuvem \"%s\"",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Provedor da Federação de Nuvem com ID: \"%s\" não existe.",
"Could not obtain lock type %d on \"%s\"." : "Não foi possível obter tipo de bloqueio %d em \"%s\".",
"Storage unauthorized. %s" : "Armazenamento não autorizado. %s",
"Storage incomplete configuration. %s" : "Configuração incompleta do armazenamento. %s",
@@ -230,6 +241,9 @@ OC.L10N.register(
"Storage connection timeout. %s" : "Esgotado o tempo de conexão ao armazenamento. %s",
"Personal" : "Pessoal",
"Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Dicas & truques",
"DB Error: \"%s\"" : "Erro no BD: \"%s\"",
"Offending command was: \"%s\"" : "Comando incorreto foi: \"%s\"",
"Offending command was: \"%s\", name: %s, password: %s" : "Comando incorreto foi: \"%s\", nome: %s, senha: %s",
@@ -241,6 +255,7 @@ OC.L10N.register(
"Files can't be shared with create permissions" : "Arquivos não podem ser compartilhados com permissões de criação",
"Cannot set expiration date more than %s days in the future" : "Não foi possível definir uma data maior que %s dias no futuro",
"No app name specified" : "Nenhum nome de aplicativo especificado",
- "App '%s' could not be installed!" : "Aplicativo '%s' não pôde ser instalado!"
+ "App '%s' could not be installed!" : "Aplicativo '%s' não pôde ser instalado!",
+ "Sync clients" : "Clientes de sincronização"
},
"nplurals=2; plural=(n > 1);");
diff --git a/lib/l10n/pt_BR.json b/lib/l10n/pt_BR.json
index 4b5d8717675..c7d579f0858 100644
--- a/lib/l10n/pt_BR.json
+++ b/lib/l10n/pt_BR.json
@@ -2,7 +2,9 @@
"Cannot write into \"config\" directory!" : "Não é possível gravar no diretório \"config\"!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Isso geralmente pode ser corrigido dando o acesso de escritura ao webserver para o diretório de configuração",
"See %s" : "Ver %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Ou, se você preferir manter o arquivo config.php somente para leitura, defina a opção \"config_is_read_only\" como true.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Normalmente isso pode ser resolvido dando ao webserver permissão de escritura no diretório config. Veja %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Ou, se você preferir manter o arquivo config.php somente para leitura, defina a opção \"config_is_read_only\" como true. Veja %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Os arquivos do aplicativo %$1s não foram substituídos corretamente. Certifique-se de que é uma versão compatível com o servidor.",
"Sample configuration detected" : "Configuração de exemplo detectada",
"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" : "Foi detectado que a configuração de exemplo foi copiada. Isso pode terminar sua instalação e não é suportado. Por favor leia a documentação antes de realizar mudanças no config.php",
@@ -25,6 +27,7 @@
"Following platforms are supported: %s" : "As seguintes plataformas são suportadas: %s",
"Server version %s or higher is required." : "É requerido um servidor da versão %s ou superior.",
"Server version %s or lower is required." : "É requerido um servidor da versão %s ou abaixo.",
+ "Logged in user must be an admin" : "O usuário conectado deve ser um administrador",
"Unknown filetype" : "Tipo de arquivo desconhecido",
"Invalid image" : "Imagem inválida",
"Avatar image is not square" : "A imagem do avatar não é quadrada",
@@ -55,6 +58,7 @@
"Empty filename is not allowed" : "Nome vazio para arquivo não é permitido.",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "O aplicativo \"%s\" não pode ser instalado pois o arquivo appinfo não pôde ser lido.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "O aplicativo \"%s\" não pode ser instalado pois não é compatível com a versão do servidor.",
+ "__language_name__" : "Português Brasileiro",
"This is an automatically sent email, please do not reply." : "Este é um e-mail enviado automaticamente. Por favor, não responda.",
"Help" : "Ajuda",
"Apps" : "Aplicativos",
@@ -62,18 +66,20 @@
"Log out" : "Sair",
"Users" : "Usuários",
"Unknown user" : "Usuário desconhecido",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Criar",
+ "Change" : "Mudar",
+ "Delete" : "Excluir",
+ "Share" : "Compartilhar",
+ "Overview" : "Visão Geral",
"Basic settings" : "Configurações básicas",
"Sharing" : "Compartilhamento",
"Security" : "Segurança",
"Encryption" : "Criptografia",
+ "Groupware" : "Groupware",
"Additional settings" : "Configurações adicionais",
- "Tips & tricks" : "Dicas & truques",
"Personal info" : "Informação Pessoal",
- "Sync clients" : "Clientes de sincronização",
+ "Mobile & desktop" : "Móvel & desktop",
"Unlimited" : "Ilimitado",
- "__language_name__" : "__language_name__",
"Verifying" : "Verificando",
"Verifying …" : "Verificando...",
"Verify" : "Verificar",
@@ -220,6 +226,11 @@
"Check the value of \"datadirectory\" in your configuration" : "Verifique o valor do \"datadirectory\" na sua configuração",
"Your data directory is invalid" : "Seu diretório de dados é inválido",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assegure-se que exista um arquivo chamado \".ocdata\" na raiz do diretório \"data\".",
+ "Action \"%s\" not supported or implemented." : "Ação \"%s\" não suportada ou implementada.",
+ "Authentication failed, wrong token or provider ID given" : "Falha na autenticação, token ou ID do provedor errados",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Parâmetros ausentes para concluir a solicitação: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "Id \"%s\" já usada pelo provedor de federação na nuvem \"%s\"",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Provedor da Federação de Nuvem com ID: \"%s\" não existe.",
"Could not obtain lock type %d on \"%s\"." : "Não foi possível obter tipo de bloqueio %d em \"%s\".",
"Storage unauthorized. %s" : "Armazenamento não autorizado. %s",
"Storage incomplete configuration. %s" : "Configuração incompleta do armazenamento. %s",
@@ -228,6 +239,9 @@
"Storage connection timeout. %s" : "Esgotado o tempo de conexão ao armazenamento. %s",
"Personal" : "Pessoal",
"Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Dicas & truques",
"DB Error: \"%s\"" : "Erro no BD: \"%s\"",
"Offending command was: \"%s\"" : "Comando incorreto foi: \"%s\"",
"Offending command was: \"%s\", name: %s, password: %s" : "Comando incorreto foi: \"%s\", nome: %s, senha: %s",
@@ -239,6 +253,7 @@
"Files can't be shared with create permissions" : "Arquivos não podem ser compartilhados com permissões de criação",
"Cannot set expiration date more than %s days in the future" : "Não foi possível definir uma data maior que %s dias no futuro",
"No app name specified" : "Nenhum nome de aplicativo especificado",
- "App '%s' could not be installed!" : "Aplicativo '%s' não pôde ser instalado!"
+ "App '%s' could not be installed!" : "Aplicativo '%s' não pôde ser instalado!",
+ "Sync clients" : "Clientes de sincronização"
},"pluralForm" :"nplurals=2; plural=(n > 1);"
} \ No newline at end of file
diff --git a/lib/l10n/pt_PT.js b/lib/l10n/pt_PT.js
new file mode 100644
index 00000000000..e2a3388743d
--- /dev/null
+++ b/lib/l10n/pt_PT.js
@@ -0,0 +1,246 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Não é possível gravar no directório \"config\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Isto normalmente pode ser resolvido, dando ao servidor da Web direitos de gravação para a diretoria de configuração",
+ "See %s" : "Ver %s",
+ "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Isto pode geralmente ser corrigido ao adicionar permissões de escrita à pasta de configuração ao servidor web. Ver %s.",
+ "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Os ficheiros na aplicação %$1s não foram correctamente substituídos. Garanta que é uma versão compatível com o servidor.",
+ "Sample configuration detected" : "Detetado exemplo de configuração",
+ "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" : "Foi detectado que a configuração de amostra foi copiada. Isso pode danificar a sua instalação e não é suportado. Por favor, leia a documentação antes de realizar mudanças no config.php",
+ "%1$s and %2$s" : "%1$s e %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s e %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s e %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s e %5$s",
+ "Education Edition" : "Edição Educação",
+ "Enterprise bundle" : "Pacote Empresa",
+ "Groupware bundle" : "Pacote Colaborativo",
+ "Social sharing bundle" : "Pacote Partilha Social",
+ "PHP %s or higher is required." : "Necessário PHP %s ou superior.",
+ "PHP with a version lower than %s is required." : "É necessário um PHP com uma versão inferir a %s.",
+ "%sbit or higher PHP required." : "Necessário PHP %sbit ou superior.",
+ "Following databases are supported: %s" : "São suportadas as seguintes bases de dados: %s",
+ "The command line tool %s could not be found" : "Não foi encontrada a ferramenta de linha de comando %s",
+ "The library %s is not available." : "A biblioteca %s não está disponível.",
+ "Library %s with a version higher than %s is required - available version %s." : "É necessário a biblioteca %s com uma versão superior a %s - versão disponível: %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "É necessário a biblioteca %s com uma versão inferior a %s - versão disponível: %s.",
+ "Following platforms are supported: %s" : "São suportadas as seguintes plataformas: %s",
+ "Server version %s or higher is required." : "É necessária versão do servidor %s or superior. ",
+ "Server version %s or lower is required." : "É necessária versão do servidor %s or inferior.",
+ "Unknown filetype" : "Tipo de ficheiro desconhecido",
+ "Invalid image" : "Imagem inválida",
+ "Avatar image is not square" : "A imagem do avatar não é quadrada.",
+ "today" : "hoje",
+ "tomorrow" : "Amanhã",
+ "yesterday" : "ontem",
+ "_in %n day_::_in %n days_" : ["em %n dia","em %n dias"],
+ "_%n day ago_::_%n days ago_" : ["%n dia atrás","%n dias atrás"],
+ "next month" : "Próximo mês",
+ "last month" : "ultimo mês",
+ "_in %n month_::_in %n months_" : ["em %n mês","em %n meses"],
+ "_%n month ago_::_%n months ago_" : ["%n mês atrás","%n meses atrás"],
+ "next year" : "Próximo ano",
+ "last year" : "ano passado",
+ "_in %n year_::_in %n years_" : ["dentro de%n ano","dentro de%n anos"],
+ "_%n year ago_::_%n years ago_" : ["%n ano atrás","%n anos atrás"],
+ "_in %n hour_::_in %n hours_" : ["dentro de %n hora","dentro de %n horas"],
+ "_%n hour ago_::_%n hours ago_" : ["%n hora atrás","%n horas atrás"],
+ "_in %n minute_::_in %n minutes_" : ["dentro de %n minuto","dentro de %n minutos"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n minuto atrás","%n minutos atrás"],
+ "in a few seconds" : "em breves segundos",
+ "seconds ago" : "Minutos atrás",
+ "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Módulo com ID: %s não existe. Por favor active-o nas definições da aplicação ou contacte o administrador.",
+ "File name is a reserved word" : "Nome de ficheiro é uma palavra reservada",
+ "File name contains at least one invalid character" : "Nome de ficheiro contém pelo menos um caráter inválido",
+ "File name is too long" : "Nome do ficheiro demasiado longo",
+ "Dot files are not allowed" : "Ficheiros dot não são permitidos",
+ "Empty filename is not allowed" : "Não é permitido um ficheiro sem nome",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "A app \"%s\" não pode ser instalada porque o ficheiro appinfo não pode ser lido.",
+ "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "A aplicação \"%s\" não pode ser instada porque não é compatível com esta versão do servidor.",
+ "__language_name__" : "Português",
+ "This is an automatically sent email, please do not reply." : "Este e-mail foi enviado automaticamente, por favor não responda a este e-mail.",
+ "Help" : "Ajuda",
+ "Apps" : "Apps",
+ "Settings" : "Definições",
+ "Log out" : "Sair",
+ "Users" : "Utilizadores",
+ "Unknown user" : "Utilizador desconhecido",
+ "Basic settings" : "Definições básicas",
+ "Sharing" : "Partilhar",
+ "Security" : "Segurança",
+ "Encryption" : "Encriptação",
+ "Additional settings" : "Definições adicionais",
+ "Personal info" : "Informação pessoal",
+ "Unlimited" : "Ilimitado",
+ "Verifying" : "A verificar",
+ "Verifying …" : "A verificar...",
+ "Verify" : "Verificar",
+ "%s enter the database username and name." : "%s introduza o nome de utilizador da base de dados e o nome da base de dados.",
+ "%s enter the database username." : "%s introduza o nome de utilizador da base de dados",
+ "%s enter the database name." : "%s introduza o nome da base de dados",
+ "%s you may not use dots in the database name" : "%s não é permitido utilizar pontos (.) no nome da base de dados",
+ "Oracle connection could not be established" : "Não foi possível estabelecer a ligação Oracle",
+ "Oracle username and/or password not valid" : "Nome de utilizador/password do Oracle inválida",
+ "PostgreSQL username and/or password not valid" : "Nome de utilizador/password do PostgreSQL inválido",
+ "You need to enter details of an existing account." : "Precisa de introduzir detalhes de uma conta existente.",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Esta plataforma não suporta o sistema operativo Mac OS X e o %s poderá não funcionar correctamente. Utilize por sua conta e risco.",
+ "For the best results, please consider using a GNU/Linux server instead." : "Para um melhor resultado, utilize antes o servidor GNU/Linux.",
+ "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." : "Parece que a instância %s está a ser executada num ambiente PHP de 32-bits e o open_basedir foi configurado no php.ini. Isto levará a problemas com ficheiros de tamanho superior a 4 GB e é altamente desencorajado.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor, remova a definição open_basedir do seu php.ini ou altere o seu PHP para 64-bits.",
+ "Set an admin username." : "Definir um nome de utilizador de administrador",
+ "Set an admin password." : "Definiar uma password de administrador",
+ "Can't create or write into the data directory %s" : "Não é possível criar ou escrever a directoria data %s",
+ "Invalid Federated Cloud ID" : "Id. de Nuvem Federada Inválida",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "A partilha de %s falhou porque a interface não permite as partilhas do tipo %i",
+ "Sharing %s failed, because the file does not exist" : "A partilha de %s falhou, porque o ficheiro não existe",
+ "You are not allowed to share %s" : "Não está autorizado a partilhar %s",
+ "Sharing %s failed, because you can not share with yourself" : "A partilha de %s falhou, porque não é possível partilhar consigo mesmo",
+ "Sharing %s failed, because the user %s does not exist" : "A partilha %s falhou, porque o utilizador %s nao existe",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "A partilha %s falhou, porque o utilizador %s não pertence a nenhum dos grupos que %s é membro de",
+ "Sharing %s failed, because this item is already shared with %s" : "A partilha %s falhou, porque o item já está a ser partilhado com %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "A partilha de %s falhou, porque este item já está a ser partilhado com o utilizador %s",
+ "Sharing %s failed, because the group %s does not exist" : "A partilha %s falhou, porque o grupo %s não existe",
+ "Sharing %s failed, because %s is not a member of the group %s" : "A partilha %s falhou, porque o utilizador %s não é membro do grupo %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Necessita de fornecer a senha para criar um link publico, só são permitidos links protegidos",
+ "Sharing %s failed, because sharing with links is not allowed" : "A partilha de %s falhou, porque partilhar com links não é permitido",
+ "Not allowed to create a federated share with the same user" : "Não é possível criar uma partilha federada com o mesmo utilizador",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "A partilha de %s falhou, não foi possível encontrar %s. É possível que o servidor esteja inacessível.",
+ "Share type %s is not valid for %s" : "O tipo de partilha %s não é válido para %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Não é possível definir data de expiração. As partilhas não podem expirar mais de %s depois de terem sido partilhadas",
+ "Cannot set expiration date. Expiration date is in the past" : "Não é possivel definir data de expiração. A data de expiração está no passado",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Ao partilhar a interface %s deve implementar a interface OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Não foi encontrada a partilha da interface %s",
+ "Sharing backend for %s not found" : "Não foi encontrada a partilha da interface para %s",
+ "Sharing failed, because the user %s is the original sharer" : "A partilha falhou, porque o utilizador %s é o distribuidor original",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Definir permissões para %s falhou, porque as permissões excedem as permissões concedidas a %s",
+ "Sharing %s failed, because resharing is not allowed" : "A partilha %s falhou, porque repartilhar não é permitido",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "A partilha %s falhou porque a partilha da interface para %s não conseguiu encontrar a sua fonte",
+ "Sharing %s failed, because the file could not be found in the file cache" : "A partilha %s falhou, devido ao ficheiro não poder ser encontrado na cache de ficheiros",
+ "Can’t increase permissions of %s" : "Não é possível aumentar as permissões de %s",
+ "Files can’t be shared with delete permissions" : "Ficheiros não podem ser partilhados com permissões de apagar",
+ "Files can’t be shared with create permissions" : "Ficheiros não podem ser partilhados com permissões de criação",
+ "Expiration date is in the past" : "A data de expiração está no passado",
+ "Can’t set expiration date more than %s days in the future" : "Não é possível definir data de expiração a mais de %s dias no futuro",
+ "%s shared »%s« with you" : "%s partilhado »%s« consigo",
+ "%s shared »%s« with you." : "%s partilhou »%s« consigo.",
+ "Click the button below to open it." : "Clicar no botão abaixo para abrir.",
+ "Open »%s«" : "Abrir »%s«",
+ "%s via %s" : "%s via %s",
+ "The requested share does not exist anymore" : "A partilha requisitada já não existe",
+ "Could not find category \"%s\"" : "Não foi encontrado a categoria \"%s\"",
+ "Sunday" : "Domingo",
+ "Monday" : "Segunda-feira",
+ "Tuesday" : "Terça-feira",
+ "Wednesday" : "Quarta-feira",
+ "Thursday" : "Quinta-feira",
+ "Friday" : "Sexta-feira",
+ "Saturday" : "Sábado",
+ "Sun." : "Dom.",
+ "Mon." : "Seg.",
+ "Tue." : "Ter.",
+ "Wed." : "Qua.",
+ "Thu." : "Qui.",
+ "Fri." : "Sex.",
+ "Sat." : "Sáb.",
+ "Su" : "Dom",
+ "Mo" : "Seg",
+ "Tu" : "Ter",
+ "We" : "Qua",
+ "Th" : "Qui",
+ "Fr" : "Sex",
+ "Sa" : "Sáb",
+ "January" : "Janeiro",
+ "February" : "Fevereiro",
+ "March" : "Março",
+ "April" : "Abril",
+ "May" : "Maio",
+ "June" : "Junho",
+ "July" : "Julho",
+ "August" : "Agosto",
+ "September" : "Setembro",
+ "October" : "Outubro",
+ "November" : "Novembro",
+ "December" : "Dezembro",
+ "Jan." : "Jan.",
+ "Feb." : "Fev.",
+ "Mar." : "Mar.",
+ "Apr." : "Abr.",
+ "May." : "Mai.",
+ "Jun." : "Jun.",
+ "Jul." : "Jul.",
+ "Aug." : "Ago.",
+ "Sep." : "Set.",
+ "Oct." : "Out.",
+ "Nov." : "Nov.",
+ "Dec." : "Dez.",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Apenas os seguintes caracteres são permitidos num nome de utilizador: \"a-z\", \"A-Z\", \"0-9\", e \"_.@-'\"",
+ "A valid username must be provided" : "Um nome de utilizador válido deve ser fornecido",
+ "Username contains whitespace at the beginning or at the end" : "Nome de utilizador contém espaço em branco no início ou no fim",
+ "Username must not consist of dots only" : "O utilizador não pode consistir de apenas pontos",
+ "A valid password must be provided" : "Uma password válida deve ser fornecida",
+ "The username is already being used" : "O nome de utilizador já está a ser usado",
+ "Could not create user" : "Não foi possível criar o utilizador",
+ "User disabled" : "Utilizador desativado",
+ "Login canceled by app" : "Sessão cancelada pela app",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "A aplicação \"%s\" não pode ser instalada porque as seguintes dependências não podem ser realizadas: %s",
+ "a safe home for all your data" : "Um lugar seguro para todos os seus dados",
+ "File is currently busy, please try again later" : "O ficheiro está ocupado, por favor, tente mais tarde",
+ "Can't read file" : "Não é possível ler o ficheiro",
+ "Application is not enabled" : "A aplicação não está activada",
+ "Authentication error" : "Erro na autenticação",
+ "Token expired. Please reload page." : "O token expirou. Por favor recarregue a página.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Nenhuma base de dados de drivers (sqlite, mysql, or postgresql) instaladas.",
+ "Cannot write into \"config\" directory" : "Não é possível escrever na directoria \"configurar\"",
+ "Cannot write into \"apps\" directory" : "Não é possivel escrever na directoria \"aplicações\"",
+ "This can usually be fixed by giving the webserver write access to the apps directory or disabling the appstore in the config file. See %s" : "Isto pode ser normalmente resolvido dando ao servidor web direito de escrita para o directório de aplicação ou desactivando a loja de aplicações no ficheiro de configuração. Ver %s",
+ "Cannot create \"data\" directory" : "Não é possivel criar a directoria \"data\"",
+ "This can usually be fixed by giving the webserver write access to the root directory. See %s" : "Isto pode geralmente ser corrigido ao adicionar permissões de escrita à pasta de raiz. Ver %s",
+ "Permissions can usually be fixed by giving the webserver write access to the root directory. See %s." : "As permissões podem geralmente ser corrigidas dando ao servidor web permissões de escrita na pasta de raiz. Ver %s.",
+ "Setting locale to %s failed" : "Definindo local para %s falhado",
+ "Please install one of these locales on your system and restart your webserver." : "Por favor instale um destes locais no seu sistema e reinicie o seu servidor web.",
+ "Please ask your server administrator to install the module." : "Por favor pergunte ao seu administrador do servidor para instalar o modulo.",
+ "PHP module %s not installed." : "O modulo %s PHP não está instalado.",
+ "PHP setting \"%s\" is not set to \"%s\"." : "Configuração PHP \"%s\" não está definida para \"%s\".",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "Ajustar esta definição no php.ini fará com que o Nextcloud inicie novamente",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload está configurado para \"%s\" invés do valor habitual de \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Para corrigir este problema altere o <code>mbstring.func_overload</code> para <code>0</code> no seu php.ini",
+ "libxml2 2.7.0 is at least required. Currently %s is installed." : "Necessária pelo menos libxml2 2.7.0. Atualmente %s está instalada.",
+ "To fix this issue update your libxml2 version and restart your web server." : "Para corrigir este problema actualize a versão da libxml2 e reinicie o seu servidor web.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP está aparentemente configurado a remover blocos doc em linha. Isto vai tornar algumas aplicações básicas inacessíveis.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Isto é provavelmente causado por uma cache/acelerador como o Zend OPcache or eAcelerador.",
+ "PHP modules have been installed, but they are still listed as missing?" : "Os módulos PHP foram instalados, mas eles ainda estão listados como desaparecidos?",
+ "Please ask your server administrator to restart the web server." : "Pro favor pergunte ao seu administrador do servidor para reiniciar o servidor da internet.",
+ "PostgreSQL >= 9 required" : "Necessita PostgreSQL >= 9",
+ "Please upgrade your database version" : "Por favor actualize a sua versão da base de dados",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor altere as permissões para 0770 para que esse directório não possa ser listado por outros utilizadores.",
+ "Your data directory is readable by other users" : "O seu directório de dados é legível por outros utilizadores",
+ "Your data directory must be an absolute path" : "O seu directório de dados deve ser um caminho absoluto",
+ "Check the value of \"datadirectory\" in your configuration" : "Verifique o valor de \"datadirectory\" na sua configuração",
+ "Your data directory is invalid" : "O seu directório de dados é inválido",
+ "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Garanta que existe um ficheiro chamado \".occdata\" na raiz do directório de dados",
+ "Could not obtain lock type %d on \"%s\"." : "Não foi possível obter o tipo de bloqueio %d em \"%s\".",
+ "Storage unauthorized. %s" : "Armazenamento desautorizado. %s",
+ "Storage incomplete configuration. %s" : "Configuração incompleta do armazenamento. %s",
+ "Storage connection error. %s" : "Erro de ligação ao armazenamento. %s",
+ "Storage is temporarily not available" : "Armazenamento temporariamente indisponível",
+ "Storage connection timeout. %s" : "Tempo de ligação ao armazenamento expirou. %s",
+ "Personal" : "Pessoal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Dicas e truques",
+ "DB Error: \"%s\"" : "Erro de BD:\"%s\"",
+ "Offending command was: \"%s\"" : "O comando transgressor foi:\"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "O comando transgressor foi: \"%s\", nome: %s, password: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Definição das permissões para %s falhou porque excedem as permissões concedidas a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Definição das permissões para %s falhou porque o item não foi encontrado",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Não é possível remover a data de expiração. Partilhas precisam de ter data de expiração.",
+ "Cannot increase permissions of %s" : "Não é possível aumentar as permissões de %s",
+ "Files can't be shared with delete permissions" : "Ficheiros não podem ser partilhados com permissões para apagar",
+ "Files can't be shared with create permissions" : "Ficheiros não podem ser partilhados com permissões para criar",
+ "Cannot set expiration date more than %s days in the future" : "Não é possível definir data de expiração superior a %s dias no futuro",
+ "No app name specified" : "Nome da aplicação não especificado",
+ "App '%s' could not be installed!" : "Aplicação '%s' não pôde ser instalada",
+ "Sync clients" : "Sincronizar clientes"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/pt_PT.json b/lib/l10n/pt_PT.json
new file mode 100644
index 00000000000..64b68498b86
--- /dev/null
+++ b/lib/l10n/pt_PT.json
@@ -0,0 +1,244 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Não é possível gravar no directório \"config\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Isto normalmente pode ser resolvido, dando ao servidor da Web direitos de gravação para a diretoria de configuração",
+ "See %s" : "Ver %s",
+ "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Isto pode geralmente ser corrigido ao adicionar permissões de escrita à pasta de configuração ao servidor web. Ver %s.",
+ "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Os ficheiros na aplicação %$1s não foram correctamente substituídos. Garanta que é uma versão compatível com o servidor.",
+ "Sample configuration detected" : "Detetado exemplo de configuração",
+ "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" : "Foi detectado que a configuração de amostra foi copiada. Isso pode danificar a sua instalação e não é suportado. Por favor, leia a documentação antes de realizar mudanças no config.php",
+ "%1$s and %2$s" : "%1$s e %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s e %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s e %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s e %5$s",
+ "Education Edition" : "Edição Educação",
+ "Enterprise bundle" : "Pacote Empresa",
+ "Groupware bundle" : "Pacote Colaborativo",
+ "Social sharing bundle" : "Pacote Partilha Social",
+ "PHP %s or higher is required." : "Necessário PHP %s ou superior.",
+ "PHP with a version lower than %s is required." : "É necessário um PHP com uma versão inferir a %s.",
+ "%sbit or higher PHP required." : "Necessário PHP %sbit ou superior.",
+ "Following databases are supported: %s" : "São suportadas as seguintes bases de dados: %s",
+ "The command line tool %s could not be found" : "Não foi encontrada a ferramenta de linha de comando %s",
+ "The library %s is not available." : "A biblioteca %s não está disponível.",
+ "Library %s with a version higher than %s is required - available version %s." : "É necessário a biblioteca %s com uma versão superior a %s - versão disponível: %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "É necessário a biblioteca %s com uma versão inferior a %s - versão disponível: %s.",
+ "Following platforms are supported: %s" : "São suportadas as seguintes plataformas: %s",
+ "Server version %s or higher is required." : "É necessária versão do servidor %s or superior. ",
+ "Server version %s or lower is required." : "É necessária versão do servidor %s or inferior.",
+ "Unknown filetype" : "Tipo de ficheiro desconhecido",
+ "Invalid image" : "Imagem inválida",
+ "Avatar image is not square" : "A imagem do avatar não é quadrada.",
+ "today" : "hoje",
+ "tomorrow" : "Amanhã",
+ "yesterday" : "ontem",
+ "_in %n day_::_in %n days_" : ["em %n dia","em %n dias"],
+ "_%n day ago_::_%n days ago_" : ["%n dia atrás","%n dias atrás"],
+ "next month" : "Próximo mês",
+ "last month" : "ultimo mês",
+ "_in %n month_::_in %n months_" : ["em %n mês","em %n meses"],
+ "_%n month ago_::_%n months ago_" : ["%n mês atrás","%n meses atrás"],
+ "next year" : "Próximo ano",
+ "last year" : "ano passado",
+ "_in %n year_::_in %n years_" : ["dentro de%n ano","dentro de%n anos"],
+ "_%n year ago_::_%n years ago_" : ["%n ano atrás","%n anos atrás"],
+ "_in %n hour_::_in %n hours_" : ["dentro de %n hora","dentro de %n horas"],
+ "_%n hour ago_::_%n hours ago_" : ["%n hora atrás","%n horas atrás"],
+ "_in %n minute_::_in %n minutes_" : ["dentro de %n minuto","dentro de %n minutos"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n minuto atrás","%n minutos atrás"],
+ "in a few seconds" : "em breves segundos",
+ "seconds ago" : "Minutos atrás",
+ "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Módulo com ID: %s não existe. Por favor active-o nas definições da aplicação ou contacte o administrador.",
+ "File name is a reserved word" : "Nome de ficheiro é uma palavra reservada",
+ "File name contains at least one invalid character" : "Nome de ficheiro contém pelo menos um caráter inválido",
+ "File name is too long" : "Nome do ficheiro demasiado longo",
+ "Dot files are not allowed" : "Ficheiros dot não são permitidos",
+ "Empty filename is not allowed" : "Não é permitido um ficheiro sem nome",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "A app \"%s\" não pode ser instalada porque o ficheiro appinfo não pode ser lido.",
+ "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "A aplicação \"%s\" não pode ser instada porque não é compatível com esta versão do servidor.",
+ "__language_name__" : "Português",
+ "This is an automatically sent email, please do not reply." : "Este e-mail foi enviado automaticamente, por favor não responda a este e-mail.",
+ "Help" : "Ajuda",
+ "Apps" : "Apps",
+ "Settings" : "Definições",
+ "Log out" : "Sair",
+ "Users" : "Utilizadores",
+ "Unknown user" : "Utilizador desconhecido",
+ "Basic settings" : "Definições básicas",
+ "Sharing" : "Partilhar",
+ "Security" : "Segurança",
+ "Encryption" : "Encriptação",
+ "Additional settings" : "Definições adicionais",
+ "Personal info" : "Informação pessoal",
+ "Unlimited" : "Ilimitado",
+ "Verifying" : "A verificar",
+ "Verifying …" : "A verificar...",
+ "Verify" : "Verificar",
+ "%s enter the database username and name." : "%s introduza o nome de utilizador da base de dados e o nome da base de dados.",
+ "%s enter the database username." : "%s introduza o nome de utilizador da base de dados",
+ "%s enter the database name." : "%s introduza o nome da base de dados",
+ "%s you may not use dots in the database name" : "%s não é permitido utilizar pontos (.) no nome da base de dados",
+ "Oracle connection could not be established" : "Não foi possível estabelecer a ligação Oracle",
+ "Oracle username and/or password not valid" : "Nome de utilizador/password do Oracle inválida",
+ "PostgreSQL username and/or password not valid" : "Nome de utilizador/password do PostgreSQL inválido",
+ "You need to enter details of an existing account." : "Precisa de introduzir detalhes de uma conta existente.",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Esta plataforma não suporta o sistema operativo Mac OS X e o %s poderá não funcionar correctamente. Utilize por sua conta e risco.",
+ "For the best results, please consider using a GNU/Linux server instead." : "Para um melhor resultado, utilize antes o servidor GNU/Linux.",
+ "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." : "Parece que a instância %s está a ser executada num ambiente PHP de 32-bits e o open_basedir foi configurado no php.ini. Isto levará a problemas com ficheiros de tamanho superior a 4 GB e é altamente desencorajado.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor, remova a definição open_basedir do seu php.ini ou altere o seu PHP para 64-bits.",
+ "Set an admin username." : "Definir um nome de utilizador de administrador",
+ "Set an admin password." : "Definiar uma password de administrador",
+ "Can't create or write into the data directory %s" : "Não é possível criar ou escrever a directoria data %s",
+ "Invalid Federated Cloud ID" : "Id. de Nuvem Federada Inválida",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "A partilha de %s falhou porque a interface não permite as partilhas do tipo %i",
+ "Sharing %s failed, because the file does not exist" : "A partilha de %s falhou, porque o ficheiro não existe",
+ "You are not allowed to share %s" : "Não está autorizado a partilhar %s",
+ "Sharing %s failed, because you can not share with yourself" : "A partilha de %s falhou, porque não é possível partilhar consigo mesmo",
+ "Sharing %s failed, because the user %s does not exist" : "A partilha %s falhou, porque o utilizador %s nao existe",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "A partilha %s falhou, porque o utilizador %s não pertence a nenhum dos grupos que %s é membro de",
+ "Sharing %s failed, because this item is already shared with %s" : "A partilha %s falhou, porque o item já está a ser partilhado com %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "A partilha de %s falhou, porque este item já está a ser partilhado com o utilizador %s",
+ "Sharing %s failed, because the group %s does not exist" : "A partilha %s falhou, porque o grupo %s não existe",
+ "Sharing %s failed, because %s is not a member of the group %s" : "A partilha %s falhou, porque o utilizador %s não é membro do grupo %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Necessita de fornecer a senha para criar um link publico, só são permitidos links protegidos",
+ "Sharing %s failed, because sharing with links is not allowed" : "A partilha de %s falhou, porque partilhar com links não é permitido",
+ "Not allowed to create a federated share with the same user" : "Não é possível criar uma partilha federada com o mesmo utilizador",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "A partilha de %s falhou, não foi possível encontrar %s. É possível que o servidor esteja inacessível.",
+ "Share type %s is not valid for %s" : "O tipo de partilha %s não é válido para %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Não é possível definir data de expiração. As partilhas não podem expirar mais de %s depois de terem sido partilhadas",
+ "Cannot set expiration date. Expiration date is in the past" : "Não é possivel definir data de expiração. A data de expiração está no passado",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Ao partilhar a interface %s deve implementar a interface OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Não foi encontrada a partilha da interface %s",
+ "Sharing backend for %s not found" : "Não foi encontrada a partilha da interface para %s",
+ "Sharing failed, because the user %s is the original sharer" : "A partilha falhou, porque o utilizador %s é o distribuidor original",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Definir permissões para %s falhou, porque as permissões excedem as permissões concedidas a %s",
+ "Sharing %s failed, because resharing is not allowed" : "A partilha %s falhou, porque repartilhar não é permitido",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "A partilha %s falhou porque a partilha da interface para %s não conseguiu encontrar a sua fonte",
+ "Sharing %s failed, because the file could not be found in the file cache" : "A partilha %s falhou, devido ao ficheiro não poder ser encontrado na cache de ficheiros",
+ "Can’t increase permissions of %s" : "Não é possível aumentar as permissões de %s",
+ "Files can’t be shared with delete permissions" : "Ficheiros não podem ser partilhados com permissões de apagar",
+ "Files can’t be shared with create permissions" : "Ficheiros não podem ser partilhados com permissões de criação",
+ "Expiration date is in the past" : "A data de expiração está no passado",
+ "Can’t set expiration date more than %s days in the future" : "Não é possível definir data de expiração a mais de %s dias no futuro",
+ "%s shared »%s« with you" : "%s partilhado »%s« consigo",
+ "%s shared »%s« with you." : "%s partilhou »%s« consigo.",
+ "Click the button below to open it." : "Clicar no botão abaixo para abrir.",
+ "Open »%s«" : "Abrir »%s«",
+ "%s via %s" : "%s via %s",
+ "The requested share does not exist anymore" : "A partilha requisitada já não existe",
+ "Could not find category \"%s\"" : "Não foi encontrado a categoria \"%s\"",
+ "Sunday" : "Domingo",
+ "Monday" : "Segunda-feira",
+ "Tuesday" : "Terça-feira",
+ "Wednesday" : "Quarta-feira",
+ "Thursday" : "Quinta-feira",
+ "Friday" : "Sexta-feira",
+ "Saturday" : "Sábado",
+ "Sun." : "Dom.",
+ "Mon." : "Seg.",
+ "Tue." : "Ter.",
+ "Wed." : "Qua.",
+ "Thu." : "Qui.",
+ "Fri." : "Sex.",
+ "Sat." : "Sáb.",
+ "Su" : "Dom",
+ "Mo" : "Seg",
+ "Tu" : "Ter",
+ "We" : "Qua",
+ "Th" : "Qui",
+ "Fr" : "Sex",
+ "Sa" : "Sáb",
+ "January" : "Janeiro",
+ "February" : "Fevereiro",
+ "March" : "Março",
+ "April" : "Abril",
+ "May" : "Maio",
+ "June" : "Junho",
+ "July" : "Julho",
+ "August" : "Agosto",
+ "September" : "Setembro",
+ "October" : "Outubro",
+ "November" : "Novembro",
+ "December" : "Dezembro",
+ "Jan." : "Jan.",
+ "Feb." : "Fev.",
+ "Mar." : "Mar.",
+ "Apr." : "Abr.",
+ "May." : "Mai.",
+ "Jun." : "Jun.",
+ "Jul." : "Jul.",
+ "Aug." : "Ago.",
+ "Sep." : "Set.",
+ "Oct." : "Out.",
+ "Nov." : "Nov.",
+ "Dec." : "Dez.",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Apenas os seguintes caracteres são permitidos num nome de utilizador: \"a-z\", \"A-Z\", \"0-9\", e \"_.@-'\"",
+ "A valid username must be provided" : "Um nome de utilizador válido deve ser fornecido",
+ "Username contains whitespace at the beginning or at the end" : "Nome de utilizador contém espaço em branco no início ou no fim",
+ "Username must not consist of dots only" : "O utilizador não pode consistir de apenas pontos",
+ "A valid password must be provided" : "Uma password válida deve ser fornecida",
+ "The username is already being used" : "O nome de utilizador já está a ser usado",
+ "Could not create user" : "Não foi possível criar o utilizador",
+ "User disabled" : "Utilizador desativado",
+ "Login canceled by app" : "Sessão cancelada pela app",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "A aplicação \"%s\" não pode ser instalada porque as seguintes dependências não podem ser realizadas: %s",
+ "a safe home for all your data" : "Um lugar seguro para todos os seus dados",
+ "File is currently busy, please try again later" : "O ficheiro está ocupado, por favor, tente mais tarde",
+ "Can't read file" : "Não é possível ler o ficheiro",
+ "Application is not enabled" : "A aplicação não está activada",
+ "Authentication error" : "Erro na autenticação",
+ "Token expired. Please reload page." : "O token expirou. Por favor recarregue a página.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Nenhuma base de dados de drivers (sqlite, mysql, or postgresql) instaladas.",
+ "Cannot write into \"config\" directory" : "Não é possível escrever na directoria \"configurar\"",
+ "Cannot write into \"apps\" directory" : "Não é possivel escrever na directoria \"aplicações\"",
+ "This can usually be fixed by giving the webserver write access to the apps directory or disabling the appstore in the config file. See %s" : "Isto pode ser normalmente resolvido dando ao servidor web direito de escrita para o directório de aplicação ou desactivando a loja de aplicações no ficheiro de configuração. Ver %s",
+ "Cannot create \"data\" directory" : "Não é possivel criar a directoria \"data\"",
+ "This can usually be fixed by giving the webserver write access to the root directory. See %s" : "Isto pode geralmente ser corrigido ao adicionar permissões de escrita à pasta de raiz. Ver %s",
+ "Permissions can usually be fixed by giving the webserver write access to the root directory. See %s." : "As permissões podem geralmente ser corrigidas dando ao servidor web permissões de escrita na pasta de raiz. Ver %s.",
+ "Setting locale to %s failed" : "Definindo local para %s falhado",
+ "Please install one of these locales on your system and restart your webserver." : "Por favor instale um destes locais no seu sistema e reinicie o seu servidor web.",
+ "Please ask your server administrator to install the module." : "Por favor pergunte ao seu administrador do servidor para instalar o modulo.",
+ "PHP module %s not installed." : "O modulo %s PHP não está instalado.",
+ "PHP setting \"%s\" is not set to \"%s\"." : "Configuração PHP \"%s\" não está definida para \"%s\".",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "Ajustar esta definição no php.ini fará com que o Nextcloud inicie novamente",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload está configurado para \"%s\" invés do valor habitual de \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Para corrigir este problema altere o <code>mbstring.func_overload</code> para <code>0</code> no seu php.ini",
+ "libxml2 2.7.0 is at least required. Currently %s is installed." : "Necessária pelo menos libxml2 2.7.0. Atualmente %s está instalada.",
+ "To fix this issue update your libxml2 version and restart your web server." : "Para corrigir este problema actualize a versão da libxml2 e reinicie o seu servidor web.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP está aparentemente configurado a remover blocos doc em linha. Isto vai tornar algumas aplicações básicas inacessíveis.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Isto é provavelmente causado por uma cache/acelerador como o Zend OPcache or eAcelerador.",
+ "PHP modules have been installed, but they are still listed as missing?" : "Os módulos PHP foram instalados, mas eles ainda estão listados como desaparecidos?",
+ "Please ask your server administrator to restart the web server." : "Pro favor pergunte ao seu administrador do servidor para reiniciar o servidor da internet.",
+ "PostgreSQL >= 9 required" : "Necessita PostgreSQL >= 9",
+ "Please upgrade your database version" : "Por favor actualize a sua versão da base de dados",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor altere as permissões para 0770 para que esse directório não possa ser listado por outros utilizadores.",
+ "Your data directory is readable by other users" : "O seu directório de dados é legível por outros utilizadores",
+ "Your data directory must be an absolute path" : "O seu directório de dados deve ser um caminho absoluto",
+ "Check the value of \"datadirectory\" in your configuration" : "Verifique o valor de \"datadirectory\" na sua configuração",
+ "Your data directory is invalid" : "O seu directório de dados é inválido",
+ "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Garanta que existe um ficheiro chamado \".occdata\" na raiz do directório de dados",
+ "Could not obtain lock type %d on \"%s\"." : "Não foi possível obter o tipo de bloqueio %d em \"%s\".",
+ "Storage unauthorized. %s" : "Armazenamento desautorizado. %s",
+ "Storage incomplete configuration. %s" : "Configuração incompleta do armazenamento. %s",
+ "Storage connection error. %s" : "Erro de ligação ao armazenamento. %s",
+ "Storage is temporarily not available" : "Armazenamento temporariamente indisponível",
+ "Storage connection timeout. %s" : "Tempo de ligação ao armazenamento expirou. %s",
+ "Personal" : "Pessoal",
+ "Admin" : "Admin",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Dicas e truques",
+ "DB Error: \"%s\"" : "Erro de BD:\"%s\"",
+ "Offending command was: \"%s\"" : "O comando transgressor foi:\"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "O comando transgressor foi: \"%s\", nome: %s, password: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Definição das permissões para %s falhou porque excedem as permissões concedidas a %s",
+ "Setting permissions for %s failed, because the item was not found" : "Definição das permissões para %s falhou porque o item não foi encontrado",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Não é possível remover a data de expiração. Partilhas precisam de ter data de expiração.",
+ "Cannot increase permissions of %s" : "Não é possível aumentar as permissões de %s",
+ "Files can't be shared with delete permissions" : "Ficheiros não podem ser partilhados com permissões para apagar",
+ "Files can't be shared with create permissions" : "Ficheiros não podem ser partilhados com permissões para criar",
+ "Cannot set expiration date more than %s days in the future" : "Não é possível definir data de expiração superior a %s dias no futuro",
+ "No app name specified" : "Nome da aplicação não especificado",
+ "App '%s' could not be installed!" : "Aplicação '%s' não pôde ser instalada",
+ "Sync clients" : "Sincronizar clientes"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/ro.js b/lib/l10n/ro.js
new file mode 100644
index 00000000000..cf1fc4c1e45
--- /dev/null
+++ b/lib/l10n/ro.js
@@ -0,0 +1,144 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Nu se poate scrie în folderul \"config\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Aceasta se poate repara de obicei prin permiterea accesului de scriere la dosarul de configurare al serverului Web",
+ "See %s" : "Vezi %s",
+ "Sample configuration detected" : "A fost detectată o configurație exemplu",
+ "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" : "S-a detectat copierea configurației exemplu. Acest lucru poate duce la oprirea instanței tale și nu este suportat. Te rugăm să citești documentația înainte de a face modificări în fișierul config.php",
+ "%1$s and %2$s" : "%1$s și %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s și %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s și %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s și %5$s",
+ "PHP %s or higher is required." : "Versiunea PHP %s sau mai mare este necesară.",
+ "PHP with a version lower than %s is required." : "Este necesară o versiune PHP mai mică decât %s",
+ "%sbit or higher PHP required." : "Este necesar PHP %sbit sau mai mare.",
+ "Following databases are supported: %s" : "Următoarele baze de date sunt suportate: %s",
+ "The command line tool %s could not be found" : "Unealta în linie de comandă %s nu a fost găsită",
+ "The library %s is not available." : "Biblioteca %s nu este disponibilă.",
+ "Following platforms are supported: %s" : "Sunt suportate următoarele platforme: %s",
+ "Unknown filetype" : "Tip fișier necunoscut",
+ "Invalid image" : "Imagine invalidă",
+ "today" : "astăzi",
+ "tomorrow" : "mâine",
+ "yesterday" : "ieri",
+ "_%n day ago_::_%n days ago_" : ["Acum o zi","Acum %n zile","Acum %n zile"],
+ "last month" : "ultima lună",
+ "_%n month ago_::_%n months ago_" : ["%n lună în urmă","%n luni în urmă","%n luni în urmă"],
+ "last year" : "ultimul an",
+ "_%n year ago_::_%n years ago_" : ["%n an în urmă","%n ani în urmâ","%n ani în urmâ"],
+ "in a few seconds" : "în câteva secunde",
+ "seconds ago" : "secunde în urmă",
+ "File name is a reserved word" : "Numele fișierului este un cuvânt rezervat",
+ "File name contains at least one invalid character" : "Numele fișierului conține măcar un caracter invalid",
+ "File name is too long" : "Numele fișierului este prea lung",
+ "Dot files are not allowed" : "Fișierele care încep cu caracterul punct nu sunt permise",
+ "Empty filename is not allowed" : "Nu este permis fișier fără nume",
+ "__language_name__" : "Română",
+ "Help" : "Ajutor",
+ "Apps" : "Aplicații",
+ "Settings" : "Setări",
+ "Log out" : "Ieșire",
+ "Users" : "Utilizatori",
+ "Unknown user" : "Utilizator necunoscut",
+ "Basic settings" : "Setări de bază",
+ "Sharing" : "Partajare",
+ "Security" : "Securitate",
+ "Encryption" : "Încriptare",
+ "Additional settings" : "Setări adiționale",
+ "Personal info" : "Informații personale",
+ "Verifying …" : "Se verifică ...",
+ "Verify" : "Verifică",
+ "%s enter the database username and name." : "%s introdu numele de utilizator și parola pentru baza de date.",
+ "%s enter the database username." : "%s introdu utilizatorul bazei de date.",
+ "%s enter the database name." : "%s introduceți numele bazei de date",
+ "Oracle connection could not be established" : "Conexiunea Oracle nu a putut fi stabilită",
+ "Oracle username and/or password not valid" : "Numele de utilizator sau / și parola Oracle nu sunt valide",
+ "PostgreSQL username and/or password not valid" : "Nume utilizator și/sau parolă PostgreSQL greșită",
+ "For the best results, please consider using a GNU/Linux server instead." : "Pentru cele mai bune rezultate, ia în calcul folosirea unui server care rulează un sistem de operare GNU/Linux.",
+ "Set an admin username." : "Setează un nume de administrator.",
+ "Set an admin password." : "Setează o parolă de administrator.",
+ "Invalid Federated Cloud ID" : "ID invalid cloud federalizat",
+ "Sharing %s failed, because the file does not exist" : "Partajarea %s a eșuat deoarece fișierul nu există",
+ "You are not allowed to share %s" : "Nu există permisiunea de partajare %s",
+ "Sharing %s failed, because you can not share with yourself" : "Partajarea %s a eșuat deoarece nu-l poți partaja cu tine însuți",
+ "Sharing %s failed, because the user %s does not exist" : "Partajarea %s a eșuat deoarece utilizatorul %s nu există",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Partajarea %s a eșuat deoarece utilizatorul %s nu face parte din niciunul din grupurile din care %s face parte",
+ "Sharing %s failed, because this item is already shared with %s" : "Partajarea %s a eșuat deoarece acest element este deja partajat cu %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "Partajarea %s a eșuat deoarece acest element este deja partajat cu utilizatorul %s",
+ "Sharing %s failed, because the group %s does not exist" : "Partajarea %s a eșuat deoarece grupul %s nu există",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Partajarea %s a eșuat deoarce %s nu face parte din grupul %s",
+ "Not allowed to create a federated share with the same user" : "Nu este permisă crearea unei partajări federalizate cu acelaşi utilizator",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Partajarea %s a eşuat, nu pot găsi %s, poate serverul nu poate fi contactat.",
+ "Share type %s is not valid for %s" : "Tipul partajării %s nu este valid pentru %s",
+ "Files can’t be shared with delete permissions" : "Fișierele nu pot fi partajate cu permisiuni de ștergere",
+ "Expiration date is in the past" : "Data expirării este în trecut",
+ "%s shared »%s« with you" : "%s Partajat »%s« cu tine de",
+ "%s shared »%s« with you." : "%s a partajat »%s« cu tine.",
+ "%s via %s" : "%s via %s",
+ "Could not find category \"%s\"" : "Cloud nu a gasit categoria \"%s\"",
+ "Sunday" : "Duminică",
+ "Monday" : "Luni",
+ "Tuesday" : "Marți",
+ "Wednesday" : "Miercuri",
+ "Thursday" : "Joi",
+ "Friday" : "Vineri",
+ "Saturday" : "Sâmbătă",
+ "Sun." : "Dum.",
+ "Mon." : "Lun.",
+ "Tue." : "Mar.",
+ "Wed." : "Mie.",
+ "Thu." : "Joi",
+ "Fri." : "Vin.",
+ "Sat." : "Sâm.",
+ "Su" : "Du",
+ "Mo" : "Lu",
+ "Tu" : "Ma",
+ "We" : "Mi",
+ "Th" : "Jo",
+ "Fr" : "Vi",
+ "Sa" : "Sâ",
+ "January" : "Ianuarie",
+ "February" : "Februarie",
+ "March" : "Martie",
+ "April" : "Aprilie",
+ "May" : "Mai",
+ "June" : "Iunie",
+ "July" : "Iulie",
+ "August" : "August",
+ "September" : "Septembrie",
+ "October" : "Octombrie",
+ "November" : "Noiembrie",
+ "December" : "Decembrie",
+ "Jan." : "Ian.",
+ "Feb." : "Feb.",
+ "Mar." : "Mar.",
+ "Apr." : "Apr.",
+ "May." : "Mai",
+ "Jun." : "Iun.",
+ "Jul." : "Iul.",
+ "Aug." : "Aug.",
+ "Sep." : "Sep.",
+ "Oct." : "Oct.",
+ "Nov." : "Noi.",
+ "Dec." : "Dec.",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Numai următoarele caractere sunt permise în numele utilizatorului: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"",
+ "A valid username must be provided" : "Trebuie să furnizaţi un nume de utilizator valid",
+ "Username contains whitespace at the beginning or at the end" : "Utilizatorul contine spațiu liber la început sau la sfârșit",
+ "Username must not consist of dots only" : "Numele utilizatorului nu poate conține numai puncte",
+ "A valid password must be provided" : "Trebuie să furnizaţi o parolă validă",
+ "The username is already being used" : "Numele de utilizator este deja folosit",
+ "Could not create user" : "Nu s-a putut crea utilizatorul",
+ "User disabled" : "Utilizator dezactivat",
+ "Application is not enabled" : "Aplicația nu este activată",
+ "Authentication error" : "Eroare la autentificare",
+ "Token expired. Please reload page." : "Token expirat. Te rugăm să reîncarci pagina.",
+ "Cannot write into \"config\" directory" : "Nu se poate scrie în folderul \"config\"",
+ "Cannot write into \"apps\" directory" : "Nu se poate scrie în folderul \"apps\"",
+ "PHP module %s not installed." : "Modulul PHP %s nu este instalat.",
+ "PHP modules have been installed, but they are still listed as missing?" : "Modulele PHP au fost instalate, dar apar ca lipsind?",
+ "PostgreSQL >= 9 required" : "Este necesară versiunea 9 sau mai mare a PostgreSQL",
+ "Please upgrade your database version" : "Actualizați baza de date la o versiune mai nouă",
+ "Tips & tricks" : "Sfaturi & trucuri"
+},
+"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));");
diff --git a/lib/l10n/ro.json b/lib/l10n/ro.json
new file mode 100644
index 00000000000..102f1bb5f39
--- /dev/null
+++ b/lib/l10n/ro.json
@@ -0,0 +1,142 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Nu se poate scrie în folderul \"config\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Aceasta se poate repara de obicei prin permiterea accesului de scriere la dosarul de configurare al serverului Web",
+ "See %s" : "Vezi %s",
+ "Sample configuration detected" : "A fost detectată o configurație exemplu",
+ "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" : "S-a detectat copierea configurației exemplu. Acest lucru poate duce la oprirea instanței tale și nu este suportat. Te rugăm să citești documentația înainte de a face modificări în fișierul config.php",
+ "%1$s and %2$s" : "%1$s și %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s și %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s și %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s și %5$s",
+ "PHP %s or higher is required." : "Versiunea PHP %s sau mai mare este necesară.",
+ "PHP with a version lower than %s is required." : "Este necesară o versiune PHP mai mică decât %s",
+ "%sbit or higher PHP required." : "Este necesar PHP %sbit sau mai mare.",
+ "Following databases are supported: %s" : "Următoarele baze de date sunt suportate: %s",
+ "The command line tool %s could not be found" : "Unealta în linie de comandă %s nu a fost găsită",
+ "The library %s is not available." : "Biblioteca %s nu este disponibilă.",
+ "Following platforms are supported: %s" : "Sunt suportate următoarele platforme: %s",
+ "Unknown filetype" : "Tip fișier necunoscut",
+ "Invalid image" : "Imagine invalidă",
+ "today" : "astăzi",
+ "tomorrow" : "mâine",
+ "yesterday" : "ieri",
+ "_%n day ago_::_%n days ago_" : ["Acum o zi","Acum %n zile","Acum %n zile"],
+ "last month" : "ultima lună",
+ "_%n month ago_::_%n months ago_" : ["%n lună în urmă","%n luni în urmă","%n luni în urmă"],
+ "last year" : "ultimul an",
+ "_%n year ago_::_%n years ago_" : ["%n an în urmă","%n ani în urmâ","%n ani în urmâ"],
+ "in a few seconds" : "în câteva secunde",
+ "seconds ago" : "secunde în urmă",
+ "File name is a reserved word" : "Numele fișierului este un cuvânt rezervat",
+ "File name contains at least one invalid character" : "Numele fișierului conține măcar un caracter invalid",
+ "File name is too long" : "Numele fișierului este prea lung",
+ "Dot files are not allowed" : "Fișierele care încep cu caracterul punct nu sunt permise",
+ "Empty filename is not allowed" : "Nu este permis fișier fără nume",
+ "__language_name__" : "Română",
+ "Help" : "Ajutor",
+ "Apps" : "Aplicații",
+ "Settings" : "Setări",
+ "Log out" : "Ieșire",
+ "Users" : "Utilizatori",
+ "Unknown user" : "Utilizator necunoscut",
+ "Basic settings" : "Setări de bază",
+ "Sharing" : "Partajare",
+ "Security" : "Securitate",
+ "Encryption" : "Încriptare",
+ "Additional settings" : "Setări adiționale",
+ "Personal info" : "Informații personale",
+ "Verifying …" : "Se verifică ...",
+ "Verify" : "Verifică",
+ "%s enter the database username and name." : "%s introdu numele de utilizator și parola pentru baza de date.",
+ "%s enter the database username." : "%s introdu utilizatorul bazei de date.",
+ "%s enter the database name." : "%s introduceți numele bazei de date",
+ "Oracle connection could not be established" : "Conexiunea Oracle nu a putut fi stabilită",
+ "Oracle username and/or password not valid" : "Numele de utilizator sau / și parola Oracle nu sunt valide",
+ "PostgreSQL username and/or password not valid" : "Nume utilizator și/sau parolă PostgreSQL greșită",
+ "For the best results, please consider using a GNU/Linux server instead." : "Pentru cele mai bune rezultate, ia în calcul folosirea unui server care rulează un sistem de operare GNU/Linux.",
+ "Set an admin username." : "Setează un nume de administrator.",
+ "Set an admin password." : "Setează o parolă de administrator.",
+ "Invalid Federated Cloud ID" : "ID invalid cloud federalizat",
+ "Sharing %s failed, because the file does not exist" : "Partajarea %s a eșuat deoarece fișierul nu există",
+ "You are not allowed to share %s" : "Nu există permisiunea de partajare %s",
+ "Sharing %s failed, because you can not share with yourself" : "Partajarea %s a eșuat deoarece nu-l poți partaja cu tine însuți",
+ "Sharing %s failed, because the user %s does not exist" : "Partajarea %s a eșuat deoarece utilizatorul %s nu există",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Partajarea %s a eșuat deoarece utilizatorul %s nu face parte din niciunul din grupurile din care %s face parte",
+ "Sharing %s failed, because this item is already shared with %s" : "Partajarea %s a eșuat deoarece acest element este deja partajat cu %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "Partajarea %s a eșuat deoarece acest element este deja partajat cu utilizatorul %s",
+ "Sharing %s failed, because the group %s does not exist" : "Partajarea %s a eșuat deoarece grupul %s nu există",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Partajarea %s a eșuat deoarce %s nu face parte din grupul %s",
+ "Not allowed to create a federated share with the same user" : "Nu este permisă crearea unei partajări federalizate cu acelaşi utilizator",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Partajarea %s a eşuat, nu pot găsi %s, poate serverul nu poate fi contactat.",
+ "Share type %s is not valid for %s" : "Tipul partajării %s nu este valid pentru %s",
+ "Files can’t be shared with delete permissions" : "Fișierele nu pot fi partajate cu permisiuni de ștergere",
+ "Expiration date is in the past" : "Data expirării este în trecut",
+ "%s shared »%s« with you" : "%s Partajat »%s« cu tine de",
+ "%s shared »%s« with you." : "%s a partajat »%s« cu tine.",
+ "%s via %s" : "%s via %s",
+ "Could not find category \"%s\"" : "Cloud nu a gasit categoria \"%s\"",
+ "Sunday" : "Duminică",
+ "Monday" : "Luni",
+ "Tuesday" : "Marți",
+ "Wednesday" : "Miercuri",
+ "Thursday" : "Joi",
+ "Friday" : "Vineri",
+ "Saturday" : "Sâmbătă",
+ "Sun." : "Dum.",
+ "Mon." : "Lun.",
+ "Tue." : "Mar.",
+ "Wed." : "Mie.",
+ "Thu." : "Joi",
+ "Fri." : "Vin.",
+ "Sat." : "Sâm.",
+ "Su" : "Du",
+ "Mo" : "Lu",
+ "Tu" : "Ma",
+ "We" : "Mi",
+ "Th" : "Jo",
+ "Fr" : "Vi",
+ "Sa" : "Sâ",
+ "January" : "Ianuarie",
+ "February" : "Februarie",
+ "March" : "Martie",
+ "April" : "Aprilie",
+ "May" : "Mai",
+ "June" : "Iunie",
+ "July" : "Iulie",
+ "August" : "August",
+ "September" : "Septembrie",
+ "October" : "Octombrie",
+ "November" : "Noiembrie",
+ "December" : "Decembrie",
+ "Jan." : "Ian.",
+ "Feb." : "Feb.",
+ "Mar." : "Mar.",
+ "Apr." : "Apr.",
+ "May." : "Mai",
+ "Jun." : "Iun.",
+ "Jul." : "Iul.",
+ "Aug." : "Aug.",
+ "Sep." : "Sep.",
+ "Oct." : "Oct.",
+ "Nov." : "Noi.",
+ "Dec." : "Dec.",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Numai următoarele caractere sunt permise în numele utilizatorului: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"",
+ "A valid username must be provided" : "Trebuie să furnizaţi un nume de utilizator valid",
+ "Username contains whitespace at the beginning or at the end" : "Utilizatorul contine spațiu liber la început sau la sfârșit",
+ "Username must not consist of dots only" : "Numele utilizatorului nu poate conține numai puncte",
+ "A valid password must be provided" : "Trebuie să furnizaţi o parolă validă",
+ "The username is already being used" : "Numele de utilizator este deja folosit",
+ "Could not create user" : "Nu s-a putut crea utilizatorul",
+ "User disabled" : "Utilizator dezactivat",
+ "Application is not enabled" : "Aplicația nu este activată",
+ "Authentication error" : "Eroare la autentificare",
+ "Token expired. Please reload page." : "Token expirat. Te rugăm să reîncarci pagina.",
+ "Cannot write into \"config\" directory" : "Nu se poate scrie în folderul \"config\"",
+ "Cannot write into \"apps\" directory" : "Nu se poate scrie în folderul \"apps\"",
+ "PHP module %s not installed." : "Modulul PHP %s nu este instalat.",
+ "PHP modules have been installed, but they are still listed as missing?" : "Modulele PHP au fost instalate, dar apar ca lipsind?",
+ "PostgreSQL >= 9 required" : "Este necesară versiunea 9 sau mai mare a PostgreSQL",
+ "Please upgrade your database version" : "Actualizați baza de date la o versiune mai nouă",
+ "Tips & tricks" : "Sfaturi & trucuri"
+},"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"
+} \ No newline at end of file
diff --git a/lib/l10n/ru.js b/lib/l10n/ru.js
index 084a79561bb..f32dca2dd0a 100644
--- a/lib/l10n/ru.js
+++ b/lib/l10n/ru.js
@@ -4,7 +4,9 @@ OC.L10N.register(
"Cannot write into \"config\" directory!" : "Запись в каталог «config» невозможна!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Обычно это можно исправить, предоставив веб-серверу права на запись в каталог конфигурации",
"See %s" : "Смотрите %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Или, если вы предпочитаете хранить файл config.php только для чтения, установите для него параметр «config_is_read_only» в true.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Обычно это можно исправить, предоставив веб-серверу права на запись в каталог конфигурации. Смотрите %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Или, если вы предпочитаете хранить файл config.php только для чтения, установите для него параметр «config_is_read_only» в true. Смотрите %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Файлы приложения %$1s не заменены корректно. Проверьте что его версия совместима с версией сервера.",
"Sample configuration detected" : "Обнаружена конфигурация из примера",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Была обнаружена конфигурация из примера. Такая конфигурация не поддерживается и может повредить вашей системе. Прочтите документацию перед внесением изменений в файл config.php",
@@ -27,6 +29,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Поддерживаются следующие платформы: %s",
"Server version %s or higher is required." : "Требуется сервер версии %s или выше.",
"Server version %s or lower is required." : "Требуется сервер версии %s или ниже.",
+ "Logged in user must be an admin" : "Залогинившийся пользователь должен быть администратором",
"Unknown filetype" : "Неизвестный тип файла",
"Invalid image" : "Изображение повреждено",
"Avatar image is not square" : "Изображение аватара не квадратное",
@@ -57,6 +60,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Пустое имя файла не допускается",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Приложение «%s» не может быть установлено, так как файл с информацией о приложении не может быть прочтен.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Приложение «%s» не может быть установлено, потому что оно несовместимо с этой версией сервера",
+ "__language_name__" : "Русский",
"This is an automatically sent email, please do not reply." : "Это соощение отправлено автоматически, пожалуйста, не отвечайте на него.",
"Help" : "Помощь",
"Apps" : "Приложения",
@@ -64,18 +68,20 @@ OC.L10N.register(
"Log out" : "Выйти",
"Users" : "Пользователи",
"Unknown user" : "Неизвестный пользователь",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Создать",
+ "Change" : "Изменить",
+ "Delete" : "Удалить",
+ "Share" : "Поделиться",
+ "Overview" : "Обзор",
"Basic settings" : "Основные настройки",
"Sharing" : "Общий доступ",
"Security" : "Безопасность",
"Encryption" : "Шифрование",
+ "Groupware" : "ПО совместного использования",
"Additional settings" : "Дополнительные настройки",
- "Tips & tricks" : "Советы и трюки",
"Personal info" : "Личная информация",
- "Sync clients" : "Клиенты синхронизации",
+ "Mobile & desktop" : "Мобильный и настольный",
"Unlimited" : "Неограничено",
- "__language_name__" : "Русский",
"Verifying" : "Производится проверка",
"Verifying …" : "Производится проверка…",
"Verify" : "Проверить",
@@ -113,8 +119,8 @@ OC.L10N.register(
"Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Невозможно установить дату истечения. Общие ресурсы не могут устареть позже %s с момента их публикации.",
"Cannot set expiration date. Expiration date is in the past" : "Невозможно установить дату окончания. Дата окончания в прошлом.",
"Sharing backend %s must implement the interface OCP\\Share_Backend" : "Бэкенд общего доступа %s должен реализовывать интерфейс OCP\\Share_Backend",
- "Sharing backend %s not found" : "Бэкенд общего доступа %s не найден",
- "Sharing backend for %s not found" : "Бэкенд общего доступа для %s не найден",
+ "Sharing backend %s not found" : "Механизм предоставления общего доступа %s не найден",
+ "Sharing backend for %s not found" : "Не найден механизм предоставления общего доступа для %s ",
"Sharing failed, because the user %s is the original sharer" : "Не удалось поделиться, потому что пользователь %s владелец этого элемента",
"Sharing %s failed, because the permissions exceed permissions granted to %s" : "Не удалось поделиться %s, права превышают предоставленные права доступа %s",
"Sharing %s failed, because resharing is not allowed" : "Не удалось поделиться %s, повторное открытие доступа запрещено",
@@ -125,10 +131,10 @@ OC.L10N.register(
"Files can’t be shared with create permissions" : "Файлы не могут иметь общий доступ с правами на создание",
"Expiration date is in the past" : "Дата окончания срока действия уже прошла",
"Can’t set expiration date more than %s days in the future" : "Невозможно установить дату окончания срока действия более %s дней",
- "%s shared »%s« with you" : "%s поделился »%s« с вами",
- "%s shared »%s« with you." : "%s поделился »%s« с вами.",
- "Click the button below to open it." : "Для открытия нажмите на кнопку ниже.",
- "Open »%s«" : "Открыть »%s«",
+ "%s shared »%s« with you" : "%s предоставил(а) Вам доступ к «%s»",
+ "%s shared »%s« with you." : "%s предоставил(а) Вам доступ к «%s».",
+ "Click the button below to open it." : "Нажмите расположенную ниже кнопку для перехода к полученному общему ресурсу.",
+ "Open »%s«" : "Открыть «%s»",
"%s via %s" : "%s через %s",
"The requested share does not exist anymore" : "Запрошенный общий ресурс более не существует.",
"Could not find category \"%s\"" : "Категория «%s» не найдена",
@@ -202,10 +208,10 @@ OC.L10N.register(
"Permissions can usually be fixed by giving the webserver write access to the root directory. See %s." : "Разрешения обычно можно исправить, предоставив веб-серверу право на запись в корневой каталог. Смотрите %s.",
"Setting locale to %s failed" : "Установка локали %s не удалась",
"Please install one of these locales on your system and restart your webserver." : "Установите один из этих языковых пакетов на вашу систему и перезапустите веб-сервер.",
- "Please ask your server administrator to install the module." : "Пожалуйста, попростите администратора сервера установить модуль.",
+ "Please ask your server administrator to install the module." : "Попросите администратора сервера установить этот модуль.",
"PHP module %s not installed." : "Не установлен PHP-модуль %s.",
"PHP setting \"%s\" is not set to \"%s\"." : "Параметру PHP «%s» не присвоено значение «%s».",
- "Adjusting this setting in php.ini will make Nextcloud run again" : "Настройка этого параметра в php.ini поможет Nextcloud работать снова",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "Настройка этого параметра в файле php.ini восстановит работоспособность Nextcloud",
"mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload установлен в «%s», при этом требуется «0»",
"To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Чтобы исправить эту проблему установите параметр <code>mbstring.func_overload</code> в значение <code>0</code> в php.ini",
"libxml2 2.7.0 is at least required. Currently %s is installed." : "Требуется как минимум libxml2 версии 2.7.0. На данный момент установлена %s.",
@@ -219,14 +225,37 @@ OC.L10N.register(
"Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Измените права доступа на 0770, чтобы другие пользователи не могли получить список файлов этого каталога.",
"Your data directory is readable by other users" : "Каталог данных доступен для чтения другим пользователям",
"Your data directory must be an absolute path" : "Каталог данных должен быть указан в виде абсолютного пути",
- "Check the value of \"datadirectory\" in your configuration" : "Проверьте значение «datadirectory» в настройках.",
+ "Check the value of \"datadirectory\" in your configuration" : "Проверьте в значение параметра «datadirectory» в файле конфигурации.",
"Your data directory is invalid" : "Каталог данных не верен",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Убедитесь, что в корне каталога данных присутствует файл «.ocdata».",
+ "Action \"%s\" not supported or implemented." : "Действие \"%s\" не поддерживается или не реализовано.",
+ "Authentication failed, wrong token or provider ID given" : "Ошибка аутентификации, неверный токен или идентификатор провайдера",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Отсутствуют параметры для завершения запроса. Отсутствующие параметры: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "Идентификатор \"%s\" уже используется провайдером облачной федерации \"%s\"",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Провайдер облачной федерации с идентификатором: \"%s\" не существует.",
"Could not obtain lock type %d on \"%s\"." : "Не удалось получить блокировку типа %d для «%s»",
"Storage unauthorized. %s" : "Хранилище неавторизовано. %s",
"Storage incomplete configuration. %s" : "Неполная конфигурация хранилища. %s",
"Storage connection error. %s" : "Ошибка подключения к хранилищу. %s",
"Storage is temporarily not available" : "Хранилище временно недоступно",
- "Storage connection timeout. %s" : "Истекло время ожидания подключения к хранилищу. %s"
+ "Storage connection timeout. %s" : "Истекло время ожидания подключения к хранилищу. %s",
+ "Personal" : "Личное",
+ "Admin" : "Администратор",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Советы и трюки",
+ "DB Error: \"%s\"" : "Ошибка БД: «%s»",
+ "Offending command was: \"%s\"" : "Нарушившая команда была: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "Нарушившая команда была: \"%s\", имя: %s, пароль: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Не удалось настроить права доступа для %s, указанные права доступа превышают предоставленные для %s",
+ "Setting permissions for %s failed, because the item was not found" : "Не удалось настроить права доступа для «%s», объект не найден.",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Невозможно очистить дату истечения срока действия. Общие ресурсы должны иметь срок действия.",
+ "Cannot increase permissions of %s" : "Невозможно повысить права доступа %s",
+ "Files can't be shared with delete permissions" : "Права на удаление файлов не позволяют открывать общий доступ к ним",
+ "Files can't be shared with create permissions" : "Права на создание файлов не позволяют открывать общий доступ к ним",
+ "Cannot set expiration date more than %s days in the future" : "Срок окончания не может быть более %s дней (дня)",
+ "No app name specified" : "Не указано имя приложения",
+ "App '%s' could not be installed!" : "Приложение «%s» не может быть установлено!",
+ "Sync clients" : "Клиенты синхронизации"
},
"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);");
diff --git a/lib/l10n/ru.json b/lib/l10n/ru.json
index f9bd45402e8..1bda68e2afc 100644
--- a/lib/l10n/ru.json
+++ b/lib/l10n/ru.json
@@ -2,7 +2,9 @@
"Cannot write into \"config\" directory!" : "Запись в каталог «config» невозможна!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Обычно это можно исправить, предоставив веб-серверу права на запись в каталог конфигурации",
"See %s" : "Смотрите %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Или, если вы предпочитаете хранить файл config.php только для чтения, установите для него параметр «config_is_read_only» в true.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Обычно это можно исправить, предоставив веб-серверу права на запись в каталог конфигурации. Смотрите %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Или, если вы предпочитаете хранить файл config.php только для чтения, установите для него параметр «config_is_read_only» в true. Смотрите %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Файлы приложения %$1s не заменены корректно. Проверьте что его версия совместима с версией сервера.",
"Sample configuration detected" : "Обнаружена конфигурация из примера",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Была обнаружена конфигурация из примера. Такая конфигурация не поддерживается и может повредить вашей системе. Прочтите документацию перед внесением изменений в файл config.php",
@@ -25,6 +27,7 @@
"Following platforms are supported: %s" : "Поддерживаются следующие платформы: %s",
"Server version %s or higher is required." : "Требуется сервер версии %s или выше.",
"Server version %s or lower is required." : "Требуется сервер версии %s или ниже.",
+ "Logged in user must be an admin" : "Залогинившийся пользователь должен быть администратором",
"Unknown filetype" : "Неизвестный тип файла",
"Invalid image" : "Изображение повреждено",
"Avatar image is not square" : "Изображение аватара не квадратное",
@@ -55,6 +58,7 @@
"Empty filename is not allowed" : "Пустое имя файла не допускается",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Приложение «%s» не может быть установлено, так как файл с информацией о приложении не может быть прочтен.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Приложение «%s» не может быть установлено, потому что оно несовместимо с этой версией сервера",
+ "__language_name__" : "Русский",
"This is an automatically sent email, please do not reply." : "Это соощение отправлено автоматически, пожалуйста, не отвечайте на него.",
"Help" : "Помощь",
"Apps" : "Приложения",
@@ -62,18 +66,20 @@
"Log out" : "Выйти",
"Users" : "Пользователи",
"Unknown user" : "Неизвестный пользователь",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Создать",
+ "Change" : "Изменить",
+ "Delete" : "Удалить",
+ "Share" : "Поделиться",
+ "Overview" : "Обзор",
"Basic settings" : "Основные настройки",
"Sharing" : "Общий доступ",
"Security" : "Безопасность",
"Encryption" : "Шифрование",
+ "Groupware" : "ПО совместного использования",
"Additional settings" : "Дополнительные настройки",
- "Tips & tricks" : "Советы и трюки",
"Personal info" : "Личная информация",
- "Sync clients" : "Клиенты синхронизации",
+ "Mobile & desktop" : "Мобильный и настольный",
"Unlimited" : "Неограничено",
- "__language_name__" : "Русский",
"Verifying" : "Производится проверка",
"Verifying …" : "Производится проверка…",
"Verify" : "Проверить",
@@ -111,8 +117,8 @@
"Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Невозможно установить дату истечения. Общие ресурсы не могут устареть позже %s с момента их публикации.",
"Cannot set expiration date. Expiration date is in the past" : "Невозможно установить дату окончания. Дата окончания в прошлом.",
"Sharing backend %s must implement the interface OCP\\Share_Backend" : "Бэкенд общего доступа %s должен реализовывать интерфейс OCP\\Share_Backend",
- "Sharing backend %s not found" : "Бэкенд общего доступа %s не найден",
- "Sharing backend for %s not found" : "Бэкенд общего доступа для %s не найден",
+ "Sharing backend %s not found" : "Механизм предоставления общего доступа %s не найден",
+ "Sharing backend for %s not found" : "Не найден механизм предоставления общего доступа для %s ",
"Sharing failed, because the user %s is the original sharer" : "Не удалось поделиться, потому что пользователь %s владелец этого элемента",
"Sharing %s failed, because the permissions exceed permissions granted to %s" : "Не удалось поделиться %s, права превышают предоставленные права доступа %s",
"Sharing %s failed, because resharing is not allowed" : "Не удалось поделиться %s, повторное открытие доступа запрещено",
@@ -123,10 +129,10 @@
"Files can’t be shared with create permissions" : "Файлы не могут иметь общий доступ с правами на создание",
"Expiration date is in the past" : "Дата окончания срока действия уже прошла",
"Can’t set expiration date more than %s days in the future" : "Невозможно установить дату окончания срока действия более %s дней",
- "%s shared »%s« with you" : "%s поделился »%s« с вами",
- "%s shared »%s« with you." : "%s поделился »%s« с вами.",
- "Click the button below to open it." : "Для открытия нажмите на кнопку ниже.",
- "Open »%s«" : "Открыть »%s«",
+ "%s shared »%s« with you" : "%s предоставил(а) Вам доступ к «%s»",
+ "%s shared »%s« with you." : "%s предоставил(а) Вам доступ к «%s».",
+ "Click the button below to open it." : "Нажмите расположенную ниже кнопку для перехода к полученному общему ресурсу.",
+ "Open »%s«" : "Открыть «%s»",
"%s via %s" : "%s через %s",
"The requested share does not exist anymore" : "Запрошенный общий ресурс более не существует.",
"Could not find category \"%s\"" : "Категория «%s» не найдена",
@@ -200,10 +206,10 @@
"Permissions can usually be fixed by giving the webserver write access to the root directory. See %s." : "Разрешения обычно можно исправить, предоставив веб-серверу право на запись в корневой каталог. Смотрите %s.",
"Setting locale to %s failed" : "Установка локали %s не удалась",
"Please install one of these locales on your system and restart your webserver." : "Установите один из этих языковых пакетов на вашу систему и перезапустите веб-сервер.",
- "Please ask your server administrator to install the module." : "Пожалуйста, попростите администратора сервера установить модуль.",
+ "Please ask your server administrator to install the module." : "Попросите администратора сервера установить этот модуль.",
"PHP module %s not installed." : "Не установлен PHP-модуль %s.",
"PHP setting \"%s\" is not set to \"%s\"." : "Параметру PHP «%s» не присвоено значение «%s».",
- "Adjusting this setting in php.ini will make Nextcloud run again" : "Настройка этого параметра в php.ini поможет Nextcloud работать снова",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "Настройка этого параметра в файле php.ini восстановит работоспособность Nextcloud",
"mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload установлен в «%s», при этом требуется «0»",
"To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Чтобы исправить эту проблему установите параметр <code>mbstring.func_overload</code> в значение <code>0</code> в php.ini",
"libxml2 2.7.0 is at least required. Currently %s is installed." : "Требуется как минимум libxml2 версии 2.7.0. На данный момент установлена %s.",
@@ -217,14 +223,37 @@
"Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Измените права доступа на 0770, чтобы другие пользователи не могли получить список файлов этого каталога.",
"Your data directory is readable by other users" : "Каталог данных доступен для чтения другим пользователям",
"Your data directory must be an absolute path" : "Каталог данных должен быть указан в виде абсолютного пути",
- "Check the value of \"datadirectory\" in your configuration" : "Проверьте значение «datadirectory» в настройках.",
+ "Check the value of \"datadirectory\" in your configuration" : "Проверьте в значение параметра «datadirectory» в файле конфигурации.",
"Your data directory is invalid" : "Каталог данных не верен",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Убедитесь, что в корне каталога данных присутствует файл «.ocdata».",
+ "Action \"%s\" not supported or implemented." : "Действие \"%s\" не поддерживается или не реализовано.",
+ "Authentication failed, wrong token or provider ID given" : "Ошибка аутентификации, неверный токен или идентификатор провайдера",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Отсутствуют параметры для завершения запроса. Отсутствующие параметры: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "Идентификатор \"%s\" уже используется провайдером облачной федерации \"%s\"",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Провайдер облачной федерации с идентификатором: \"%s\" не существует.",
"Could not obtain lock type %d on \"%s\"." : "Не удалось получить блокировку типа %d для «%s»",
"Storage unauthorized. %s" : "Хранилище неавторизовано. %s",
"Storage incomplete configuration. %s" : "Неполная конфигурация хранилища. %s",
"Storage connection error. %s" : "Ошибка подключения к хранилищу. %s",
"Storage is temporarily not available" : "Хранилище временно недоступно",
- "Storage connection timeout. %s" : "Истекло время ожидания подключения к хранилищу. %s"
+ "Storage connection timeout. %s" : "Истекло время ожидания подключения к хранилищу. %s",
+ "Personal" : "Личное",
+ "Admin" : "Администратор",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Советы и трюки",
+ "DB Error: \"%s\"" : "Ошибка БД: «%s»",
+ "Offending command was: \"%s\"" : "Нарушившая команда была: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "Нарушившая команда была: \"%s\", имя: %s, пароль: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Не удалось настроить права доступа для %s, указанные права доступа превышают предоставленные для %s",
+ "Setting permissions for %s failed, because the item was not found" : "Не удалось настроить права доступа для «%s», объект не найден.",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Невозможно очистить дату истечения срока действия. Общие ресурсы должны иметь срок действия.",
+ "Cannot increase permissions of %s" : "Невозможно повысить права доступа %s",
+ "Files can't be shared with delete permissions" : "Права на удаление файлов не позволяют открывать общий доступ к ним",
+ "Files can't be shared with create permissions" : "Права на создание файлов не позволяют открывать общий доступ к ним",
+ "Cannot set expiration date more than %s days in the future" : "Срок окончания не может быть более %s дней (дня)",
+ "No app name specified" : "Не указано имя приложения",
+ "App '%s' could not be installed!" : "Приложение «%s» не может быть установлено!",
+ "Sync clients" : "Клиенты синхронизации"
},"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);"
} \ No newline at end of file
diff --git a/lib/l10n/si_LK.js b/lib/l10n/si_LK.js
new file mode 100644
index 00000000000..e90fac8266c
--- /dev/null
+++ b/lib/l10n/si_LK.js
@@ -0,0 +1,16 @@
+OC.L10N.register(
+ "lib",
+ {
+ "today" : "අද",
+ "yesterday" : "ඊයේ",
+ "last month" : "පෙර මාසයේ",
+ "last year" : "පෙර අවුරුද්දේ",
+ "seconds ago" : "තත්පරයන්ට පෙර",
+ "__language_name__" : "සිංහල",
+ "Apps" : "යෙදුම්",
+ "Users" : "පරිශීලකයන්",
+ "Application is not enabled" : "යෙදුම සක්‍රිය කර නොමැත",
+ "Authentication error" : "සත්‍යාපන දෝෂයක්",
+ "Token expired. Please reload page." : "ටෝකනය කල් ඉකුත් වී ඇත. පිටුව නැවුම් කරන්න"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/si_LK.json b/lib/l10n/si_LK.json
new file mode 100644
index 00000000000..adb01c28391
--- /dev/null
+++ b/lib/l10n/si_LK.json
@@ -0,0 +1,14 @@
+{ "translations": {
+ "today" : "අද",
+ "yesterday" : "ඊයේ",
+ "last month" : "පෙර මාසයේ",
+ "last year" : "පෙර අවුරුද්දේ",
+ "seconds ago" : "තත්පරයන්ට පෙර",
+ "__language_name__" : "සිංහල",
+ "Apps" : "යෙදුම්",
+ "Users" : "පරිශීලකයන්",
+ "Application is not enabled" : "යෙදුම සක්‍රිය කර නොමැත",
+ "Authentication error" : "සත්‍යාපන දෝෂයක්",
+ "Token expired. Please reload page." : "ටෝකනය කල් ඉකුත් වී ඇත. පිටුව නැවුම් කරන්න"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/sk.js b/lib/l10n/sk.js
index ddd0c1de7f4..596a3e0dda9 100644
--- a/lib/l10n/sk.js
+++ b/lib/l10n/sk.js
@@ -27,26 +27,27 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Podporované sú nasledovné systémy: %s",
"Server version %s or higher is required." : "Je vyžadovaná verzia servera %s alebo vyššia.",
"Server version %s or lower is required." : "Je vyžadovaná verzia servera %s alebo nižšia.",
+ "Logged in user must be an admin" : "Prihlásený používateľ musí byť správca",
"Unknown filetype" : "Neznámy typ súboru",
"Invalid image" : "Chybný obrázok",
"Avatar image is not square" : "Obrázok avatara nie je štvorcový",
"today" : "dnes",
"tomorrow" : "zajtra",
"yesterday" : "včera",
- "_in %n day_::_in %n days_" : ["o %n deň","o %n dni","o %n dní"],
- "_%n day ago_::_%n days ago_" : ["včera","pred %n dňami","pred %n dňami"],
+ "_in %n day_::_in %n days_" : ["o %n deň","o %n dni","o %n dní","o %n dní"],
+ "_%n day ago_::_%n days ago_" : ["včera","pred %n dňami","pred %n dňami","pred %n dňami"],
"next month" : "budúci mesiac",
"last month" : "minulý mesiac",
- "_in %n month_::_in %n months_" : ["o %n mesiac ","o %n mesiace","o %n mesiacov"],
- "_%n month ago_::_%n months ago_" : ["pred %n mesiacom","pred %n mesiacmi","pred %n mesiacmi"],
+ "_in %n month_::_in %n months_" : ["o %n mesiac ","o %n mesiace","o %n mesiacov","o %n mesiacov"],
+ "_%n month ago_::_%n months ago_" : ["pred %n mesiacom","pred %n mesiacmi","pred %n mesiacmi","pred %n mesiacmi"],
"next year" : "budúci rok",
"last year" : "minulý rok",
- "_in %n year_::_in %n years_" : ["o %n rok","o %n roky","o %n rokov"],
- "_%n year ago_::_%n years ago_" : ["vlani","pred %n rokmi","pred %n rokmi"],
- "_in %n hour_::_in %n hours_" : ["o %n hodinu","o %n hodiny","o %n hodín"],
- "_%n hour ago_::_%n hours ago_" : ["pred %n hodinou","pred %n hodinami","pred %n hodinami"],
- "_in %n minute_::_in %n minutes_" : ["o %n minútu","o %n minúty","o %n minút"],
- "_%n minute ago_::_%n minutes ago_" : ["pred %n minútou","pred %n minútami","pred %n minútami"],
+ "_in %n year_::_in %n years_" : ["o %n rok","o %n roky","o %n rokov","o %n rokov"],
+ "_%n year ago_::_%n years ago_" : ["vlani","pred %n rokmi","pred %n rokmi","pred %n rokmi"],
+ "_in %n hour_::_in %n hours_" : ["o %n hodinu","o %n hodiny","o %n hodín","o %n hodín"],
+ "_%n hour ago_::_%n hours ago_" : ["pred %n hodinou","pred %n hodinami","pred %n hodinami","pred %n hodinami"],
+ "_in %n minute_::_in %n minutes_" : ["o %n minútu","o %n minúty","o %n minút","o %n minút"],
+ "_%n minute ago_::_%n minutes ago_" : ["pred %n minútou","pred %n minútami","pred %n minútami","pred %n minútami"],
"in a few seconds" : "o pár sekúnd",
"seconds ago" : "pred sekundami",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul s ID: %s neexistuje. Povoľte ho prosím vo vašom nastavení aplikácií alebo kontaktujte správcu.",
@@ -57,6 +58,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Prázdny názov súboru nie je povolený",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Aplikáciu \"%s\" nie je možné nainštalovať, lebo nebolo možné načítať súbor s informáciami o aplikácií.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Aplikácia \"%s\" nie je kompatibilná s verziou servera, preto nemôže byť nainštalovaná.",
+ "__language_name__" : "Slovenčina",
"This is an automatically sent email, please do not reply." : "Toto je automaticky odosielaný e-mail, prosím, neodpovedajte.",
"Help" : "Pomoc",
"Apps" : "Aplikácie",
@@ -64,18 +66,19 @@ OC.L10N.register(
"Log out" : "Odhlásiť sa",
"Users" : "Používatelia",
"Unknown user" : "Neznámy používateľ",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Vytvoriť",
+ "Change" : "Zmeniť",
+ "Delete" : "Zmazať",
+ "Share" : "Zdieľať",
+ "Overview" : "Prehľad",
"Basic settings" : "Základné nastavenia",
"Sharing" : "Sprístupnenie",
"Security" : "Zabezpečenie",
"Encryption" : "Šifrovanie",
"Additional settings" : "Ďalšie nastavenia",
- "Tips & tricks" : "Tipy a triky",
"Personal info" : "Osobné informácie",
- "Sync clients" : "Klienti synchronizácie",
+ "Mobile & desktop" : "Mobil a počítač",
"Unlimited" : "Neobmedzené",
- "__language_name__" : "Slovenčina",
"Verifying" : "Overovanie",
"Verifying …" : "Overovanie ...",
"Verify" : "Overiť",
@@ -227,6 +230,24 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Neplatná konfigurácia úložiska. %s",
"Storage connection error. %s" : "Chyba pripojenia k úložisku. %s",
"Storage is temporarily not available" : "Úložisko je dočasne nedostupné",
- "Storage connection timeout. %s" : "Vypršanie pripojenia k úložisku. %s"
+ "Storage connection timeout. %s" : "Vypršanie pripojenia k úložisku. %s",
+ "Personal" : "Osobné",
+ "Admin" : "Admi",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tipy a triky",
+ "DB Error: \"%s\"" : "Chyba databázy: \"%s\"",
+ "Offending command was: \"%s\"" : "Problémový príkaz bol: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "Problémový príkaz bol: \"%s\", meno: %s, heslo: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Nastavenie povolení pre %s zlyhalo, pretože povolenia prekračujú povolenia udelené %s",
+ "Setting permissions for %s failed, because the item was not found" : "Nastavenie povolení pre %s zlyhalo, pretože položka sa nenašla",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Nemožno vymazať čas exspirácie. Pri sprístupnení je čas exspirácie vyžadovaný.",
+ "Cannot increase permissions of %s" : "Nie je možné navýšiť oprávnenia pre %s",
+ "Files can't be shared with delete permissions" : "Súbory nie je možné sprístupňovať s oprávneniami na odstránenie",
+ "Files can't be shared with create permissions" : "Súbory nie je možné sprístupňovať s oprávneniami na vytváranie",
+ "Cannot set expiration date more than %s days in the future" : "Nie je možné nastaviť dátum konca platnosti viac ako %s dní v budúcnosti",
+ "No app name specified" : "Nešpecifikované meno aplikácie",
+ "App '%s' could not be installed!" : "Aplikáciu '%s' nebolo možné nainštalovať!",
+ "Sync clients" : "Klienti synchronizácie"
},
-"nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;");
+"nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);");
diff --git a/lib/l10n/sk.json b/lib/l10n/sk.json
index a9b9e1e6957..1ee63b2641d 100644
--- a/lib/l10n/sk.json
+++ b/lib/l10n/sk.json
@@ -25,26 +25,27 @@
"Following platforms are supported: %s" : "Podporované sú nasledovné systémy: %s",
"Server version %s or higher is required." : "Je vyžadovaná verzia servera %s alebo vyššia.",
"Server version %s or lower is required." : "Je vyžadovaná verzia servera %s alebo nižšia.",
+ "Logged in user must be an admin" : "Prihlásený používateľ musí byť správca",
"Unknown filetype" : "Neznámy typ súboru",
"Invalid image" : "Chybný obrázok",
"Avatar image is not square" : "Obrázok avatara nie je štvorcový",
"today" : "dnes",
"tomorrow" : "zajtra",
"yesterday" : "včera",
- "_in %n day_::_in %n days_" : ["o %n deň","o %n dni","o %n dní"],
- "_%n day ago_::_%n days ago_" : ["včera","pred %n dňami","pred %n dňami"],
+ "_in %n day_::_in %n days_" : ["o %n deň","o %n dni","o %n dní","o %n dní"],
+ "_%n day ago_::_%n days ago_" : ["včera","pred %n dňami","pred %n dňami","pred %n dňami"],
"next month" : "budúci mesiac",
"last month" : "minulý mesiac",
- "_in %n month_::_in %n months_" : ["o %n mesiac ","o %n mesiace","o %n mesiacov"],
- "_%n month ago_::_%n months ago_" : ["pred %n mesiacom","pred %n mesiacmi","pred %n mesiacmi"],
+ "_in %n month_::_in %n months_" : ["o %n mesiac ","o %n mesiace","o %n mesiacov","o %n mesiacov"],
+ "_%n month ago_::_%n months ago_" : ["pred %n mesiacom","pred %n mesiacmi","pred %n mesiacmi","pred %n mesiacmi"],
"next year" : "budúci rok",
"last year" : "minulý rok",
- "_in %n year_::_in %n years_" : ["o %n rok","o %n roky","o %n rokov"],
- "_%n year ago_::_%n years ago_" : ["vlani","pred %n rokmi","pred %n rokmi"],
- "_in %n hour_::_in %n hours_" : ["o %n hodinu","o %n hodiny","o %n hodín"],
- "_%n hour ago_::_%n hours ago_" : ["pred %n hodinou","pred %n hodinami","pred %n hodinami"],
- "_in %n minute_::_in %n minutes_" : ["o %n minútu","o %n minúty","o %n minút"],
- "_%n minute ago_::_%n minutes ago_" : ["pred %n minútou","pred %n minútami","pred %n minútami"],
+ "_in %n year_::_in %n years_" : ["o %n rok","o %n roky","o %n rokov","o %n rokov"],
+ "_%n year ago_::_%n years ago_" : ["vlani","pred %n rokmi","pred %n rokmi","pred %n rokmi"],
+ "_in %n hour_::_in %n hours_" : ["o %n hodinu","o %n hodiny","o %n hodín","o %n hodín"],
+ "_%n hour ago_::_%n hours ago_" : ["pred %n hodinou","pred %n hodinami","pred %n hodinami","pred %n hodinami"],
+ "_in %n minute_::_in %n minutes_" : ["o %n minútu","o %n minúty","o %n minút","o %n minút"],
+ "_%n minute ago_::_%n minutes ago_" : ["pred %n minútou","pred %n minútami","pred %n minútami","pred %n minútami"],
"in a few seconds" : "o pár sekúnd",
"seconds ago" : "pred sekundami",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul s ID: %s neexistuje. Povoľte ho prosím vo vašom nastavení aplikácií alebo kontaktujte správcu.",
@@ -55,6 +56,7 @@
"Empty filename is not allowed" : "Prázdny názov súboru nie je povolený",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Aplikáciu \"%s\" nie je možné nainštalovať, lebo nebolo možné načítať súbor s informáciami o aplikácií.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Aplikácia \"%s\" nie je kompatibilná s verziou servera, preto nemôže byť nainštalovaná.",
+ "__language_name__" : "Slovenčina",
"This is an automatically sent email, please do not reply." : "Toto je automaticky odosielaný e-mail, prosím, neodpovedajte.",
"Help" : "Pomoc",
"Apps" : "Aplikácie",
@@ -62,18 +64,19 @@
"Log out" : "Odhlásiť sa",
"Users" : "Používatelia",
"Unknown user" : "Neznámy používateľ",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Vytvoriť",
+ "Change" : "Zmeniť",
+ "Delete" : "Zmazať",
+ "Share" : "Zdieľať",
+ "Overview" : "Prehľad",
"Basic settings" : "Základné nastavenia",
"Sharing" : "Sprístupnenie",
"Security" : "Zabezpečenie",
"Encryption" : "Šifrovanie",
"Additional settings" : "Ďalšie nastavenia",
- "Tips & tricks" : "Tipy a triky",
"Personal info" : "Osobné informácie",
- "Sync clients" : "Klienti synchronizácie",
+ "Mobile & desktop" : "Mobil a počítač",
"Unlimited" : "Neobmedzené",
- "__language_name__" : "Slovenčina",
"Verifying" : "Overovanie",
"Verifying …" : "Overovanie ...",
"Verify" : "Overiť",
@@ -225,6 +228,24 @@
"Storage incomplete configuration. %s" : "Neplatná konfigurácia úložiska. %s",
"Storage connection error. %s" : "Chyba pripojenia k úložisku. %s",
"Storage is temporarily not available" : "Úložisko je dočasne nedostupné",
- "Storage connection timeout. %s" : "Vypršanie pripojenia k úložisku. %s"
-},"pluralForm" :"nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"
+ "Storage connection timeout. %s" : "Vypršanie pripojenia k úložisku. %s",
+ "Personal" : "Osobné",
+ "Admin" : "Admi",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tipy a triky",
+ "DB Error: \"%s\"" : "Chyba databázy: \"%s\"",
+ "Offending command was: \"%s\"" : "Problémový príkaz bol: \"%s\"",
+ "Offending command was: \"%s\", name: %s, password: %s" : "Problémový príkaz bol: \"%s\", meno: %s, heslo: %s",
+ "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "Nastavenie povolení pre %s zlyhalo, pretože povolenia prekračujú povolenia udelené %s",
+ "Setting permissions for %s failed, because the item was not found" : "Nastavenie povolení pre %s zlyhalo, pretože položka sa nenašla",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "Nemožno vymazať čas exspirácie. Pri sprístupnení je čas exspirácie vyžadovaný.",
+ "Cannot increase permissions of %s" : "Nie je možné navýšiť oprávnenia pre %s",
+ "Files can't be shared with delete permissions" : "Súbory nie je možné sprístupňovať s oprávneniami na odstránenie",
+ "Files can't be shared with create permissions" : "Súbory nie je možné sprístupňovať s oprávneniami na vytváranie",
+ "Cannot set expiration date more than %s days in the future" : "Nie je možné nastaviť dátum konca platnosti viac ako %s dní v budúcnosti",
+ "No app name specified" : "Nešpecifikované meno aplikácie",
+ "App '%s' could not be installed!" : "Aplikáciu '%s' nebolo možné nainštalovať!",
+ "Sync clients" : "Klienti synchronizácie"
+},"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);"
} \ No newline at end of file
diff --git a/lib/l10n/sl.js b/lib/l10n/sl.js
new file mode 100644
index 00000000000..3c90a1f7a3a
--- /dev/null
+++ b/lib/l10n/sl.js
@@ -0,0 +1,135 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Mapa 'config' nima določenih ustreznih dovoljenj za pisanje!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Napako je mogoče odpraviti z dodelitvijo dovoljenja spletnemu strežniku za pisanje v nastavitveno mapo.",
+ "See %s" : "Oglejte si %s",
+ "Sample configuration detected" : "Zaznana je neustrezna preizkusna nastavitev",
+ "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" : "Zaznano je, da je bila v sistem kopirana datoteka z enostavno nastavitvijo. To lahko vpliva na namestitev in zato možnost ni podprta. Pred spremembami datoteke config.php si natančno preberite dokumentacijo.",
+ "%1$s and %2$s" : "%1$s in %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s in %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s in %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s in %5$s",
+ "PHP %s or higher is required." : "Zahtevana je različica PHP %s ali višja.",
+ "PHP with a version lower than %s is required." : "Zahtevana je različica PHP manj kot %s.",
+ "%sbit or higher PHP required." : "Zahtevana je različica PHP %s ali višja.",
+ "Following databases are supported: %s" : "Podprte so navedene podatkovne zbirke: %s",
+ "The command line tool %s could not be found" : "Orodja ukazne vrstice %s ni mogoče najti",
+ "The library %s is not available." : "Knjižnica %s ni na voljo.",
+ "Library %s with a version higher than %s is required - available version %s." : "Zahtevana je knjižnica %s z različico, višjo od %s – na voljo je različica %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "Zahtevana je knjižnica %s z različico, manjšo od %s – na voljo je različica %s.",
+ "Following platforms are supported: %s" : "Podprta so okolja: %s",
+ "Server version %s or higher is required." : "Zahtevana je različica strežnika %s ali višja.",
+ "Server version %s or lower is required." : "Zahtevana je različica strežnika %s ali nižja.",
+ "Unknown filetype" : "Neznana vrsta datoteke",
+ "Invalid image" : "Neveljavna slika",
+ "today" : "danes",
+ "yesterday" : "včeraj",
+ "_%n day ago_::_%n days ago_" : ["pred %n dnevom","pred %n dnevoma","pred %n dnevi","pred %n dnevi"],
+ "last month" : "zadnji mesec",
+ "_%n month ago_::_%n months ago_" : ["pred %n mesecem","pred %n mesecema","pred %n meseci","pred %n meseci"],
+ "last year" : "lansko leto",
+ "_%n year ago_::_%n years ago_" : ["pred %n letom","pred %n letoma","pred %n leti","pred %n leti"],
+ "_%n hour ago_::_%n hours ago_" : ["pred %n uro","pred %n urama","pred %n urami","pred %n urami"],
+ "_%n minute ago_::_%n minutes ago_" : ["pred %n minuto","pred %n minutama","pred %n minutami","pred %n minutami"],
+ "seconds ago" : "pred nekaj sekundami",
+ "File name is a reserved word" : "Ime datoteke je zadržana beseda",
+ "File name contains at least one invalid character" : "Ime datoteke vsebuje vsaj en neveljaven znak.",
+ "File name is too long" : "Ime datoteke je predolgo",
+ "Dot files are not allowed" : "Skrite datoteke niso dovoljene",
+ "Empty filename is not allowed" : "Prazno polje imena datoteke ni dovoljeno.",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "Programa \\\"%s\\\" ni mogoče namestiti, ker ni mogoče brati datoteke appinfo.",
+ "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Programa »%s« ni mogoče namestiti, ker ni združljiv z nameščeno različico strežnika.",
+ "__language_name__" : "Slovenščina",
+ "Apps" : "Programi",
+ "Users" : "Uporabniki",
+ "Unknown user" : "Neznan uporabnik",
+ "Basic settings" : "Osnovne nastavitve",
+ "Security" : "Varnost",
+ "%s enter the database username and name." : "%s - vnos uporabniškega imena in imena podatkovne zbirke.",
+ "%s enter the database username." : "%s - vnos uporabniškega imena podatkovne zbirke.",
+ "%s enter the database name." : "%s - vnos imena podatkovne zbirke.",
+ "%s you may not use dots in the database name" : "%s - v imenu podatkovne zbirke ni dovoljeno uporabljati pik.",
+ "Oracle connection could not be established" : "Povezave s sistemom Oracle ni mogoče vzpostaviti.",
+ "Oracle username and/or password not valid" : "Uporabniško ime ali geslo Oracle ni veljavno",
+ "PostgreSQL username and/or password not valid" : "Uporabniško ime ali geslo PostgreSQL ni veljavno",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Sistem Mac OS X ni podprt, zato %s v tem okolju ne bo deloval zanesljivo. Program uporabljate na lastno odgovornost! ",
+ "For the best results, please consider using a GNU/Linux server instead." : "Za najbolj še rezultate je priporočljivo uporabljati strežnik GNU/Linux.",
+ "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." : "Videti je, da je dejavna seja %s zagnana v 32-bitnem okolju PHP in, da je v datoteki php.ini nastavljen open_basedir . Tako delovanje ni priporočljivo, saj se lahko pojavijo težave z datotekami, večjimi od 4GB.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Odstraniti je treba nastavitev open_basedir v datoteki php.ini ali pa preklopiti na 64-bitno okolje PHP.",
+ "Set an admin username." : "Nastavi uporabniško ime skrbnika.",
+ "Set an admin password." : "Nastavi geslo skrbnika.",
+ "Can't create or write into the data directory %s" : "Ni mogoče zapisati podatkov v podatkovno mapo %s",
+ "Invalid Federated Cloud ID" : "Neveljaven ID zveznega oblaka ownCloud",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "Omogočanje souporabe %s je spodletelo, ker ozadnji program ne dopušča souporabe vrste %i.",
+ "Sharing %s failed, because the file does not exist" : "Souporaba %s je spodletela, ker ta datoteka ne obstaja",
+ "You are not allowed to share %s" : "Omogočanje souporabe %s brez ustreznih dovoljenj ni mogoče.",
+ "Sharing %s failed, because you can not share with yourself" : "Nastavitev %s souporabe je spodletela, ker souporaba s samim seboj ni mogoča.",
+ "Sharing %s failed, because the user %s does not exist" : "Nastavljanje souporabe %s je spodletelo, ker uporabnik %s ne obstaja.",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Nastavljanje souporabe %s je spodletelo, ker uporabnik %s ni član nobene skupine, v kateri je tudi uporabnik %s.",
+ "Sharing %s failed, because this item is already shared with %s" : "Nastavljanje souporabe %s je spodletela, ker je ima uporabnik %s predmet že v souporabi.",
+ "Sharing %s failed, because this item is already shared with user %s" : "Nastavljanje souporabe %s je spodletelo, ker je predmet že v souporabi z uporabnikom %s.",
+ "Sharing %s failed, because the group %s does not exist" : "Nastavljanje souporabe %s je spodletelo, ker je skupina %s ne obstaja.",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Nastavljanje souporabe %s je spodletelo, ker uporabnik %s ni član skupine %s.",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Navesti je treba geslo za ustvarjanje javne povezave, saj so dovoljene le zaščitene.",
+ "Sharing %s failed, because sharing with links is not allowed" : "Nastavljanje souporabe %s je spodletelo, ker souporaba preko povezave ni dovoljena.",
+ "Not allowed to create a federated share with the same user" : "Ni dovoljeno ustvariti souporabe zveznega oblaka z istim uporabnikom",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Omogočanje souporabe %s je spodletelo, ker ni mogoče najti %s. Najverjetneje je strežnik nedosegljiv.",
+ "Share type %s is not valid for %s" : "Vrsta souporabe %s za %s ni veljavna.",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Ni mogoče določiti datuma preteka. Ni dovoljeno, da so mape ali datoteke, dodeljene v souporabo, v souporabi po %s.",
+ "Cannot set expiration date. Expiration date is in the past" : "Ni mogoče nastaviti datuma preteka. Ta datum je že preteklost.",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Souporaba ozadnjega programa %s mora vsebovati tudi vmesnik OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Ozadnjega programa %s za souporabo ni mogoče najti",
+ "Sharing backend for %s not found" : "Ozadnjega programa za souporabo za %s ni mogoče najti",
+ "Sharing failed, because the user %s is the original sharer" : "Nastavitev souporabe je spodletela, ker je uporabnik %s souporabo izvorno nastavil.",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Nastavljanje souporabe %s je spodletelo, ker zahteve presegajo dodeljena dovoljenja za %s.",
+ "Sharing %s failed, because resharing is not allowed" : "Nastavljanje souporabe %s je spodletelo, ker nadaljnje omogočanje souporabe ni dovoljeno.",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Nastavljanje souporabe %s je spodletelo, ker ozadnji program %s ne upravlja z viri.",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Nastavljanje souporabe %s je spodletelo, ker v predpomnilniku zahtevana datoteka ne obstaja.",
+ "Expiration date is in the past" : "Datum preteka je že mimo!",
+ "%s shared »%s« with you" : "%s je omogočil souporabo »%s«",
+ "%s via %s" : "%s prek %s",
+ "Could not find category \"%s\"" : "Kategorije \"%s\" ni mogoče najti.",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "V uporabniškem imenu je dovoljeno uporabiti le znake: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"",
+ "A valid username must be provided" : "Navedeno mora biti veljavno uporabniško ime",
+ "Username contains whitespace at the beginning or at the end" : "Uporabniško ime vsebuje presledni znak na začetku ali na koncu imena.",
+ "A valid password must be provided" : "Navedeno mora biti veljavno geslo",
+ "The username is already being used" : "Vpisano uporabniško ime je že v uporabi",
+ "User disabled" : "Uporabnik je onemogočen",
+ "Login canceled by app" : "Aplikacija je prijavo prekinila.",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "Programa \"%s\" ni mogoče namestiti zaradi nerešenih odvisnosti: %s",
+ "a safe home for all your data" : "varen dom za vse vaše podatke",
+ "File is currently busy, please try again later" : "Datoteka je trenutno v uporabi. Poskusite znova kasneje.",
+ "Can't read file" : "Datoteke ni mogoče prebrati.",
+ "Application is not enabled" : "Program ni omogočen",
+ "Authentication error" : "Napaka overjanja",
+ "Token expired. Please reload page." : "Žeton je potekel. Stran je treba ponovno naložiti.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Ni nameščenih programnikov podatkovnih zbirk (sqlite, mysql, ali postgresql).",
+ "Cannot write into \"config\" directory" : "Mapa 'config' nima nastavljenih ustreznih dovoljenj za pisanje!",
+ "Cannot write into \"apps\" directory" : "Mapa \"apps\" nima nastavljenih ustreznih dovoljenj za pisanje!",
+ "Setting locale to %s failed" : "Nastavljanje jezikovnih določil na %s je spodletelo.",
+ "Please install one of these locales on your system and restart your webserver." : "Namestiti je treba podporo za vsaj eno od navedenih jezikovnih določil v sistemu in nato ponovno zagnati spletni strežnik.",
+ "Please ask your server administrator to install the module." : "Obvestite skrbnika strežnika, da je treba namestiti manjkajoč modul.",
+ "PHP module %s not installed." : "Modul PHP %s ni nameščen.",
+ "PHP setting \"%s\" is not set to \"%s\"." : "Nastavitev PHP \"%s\" ni nastavljena na \"%s\".",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "Nastavitev tega parametra v <bold>php.ini</bold> bo vzpostavilo ponovno delovanje NextCloud",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload je nastavljeno na \"%s\" namesto pričakovane vrednosti \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Za reštev te težave nastavi <code>mbstring.func_overload</code> na <code>0</code> v tvojem php.ini",
+ "libxml2 2.7.0 is at least required. Currently %s is installed." : "libxml2 mora iti vsaj 2.7.0. Trenutno je nameščena %s.",
+ "To fix this issue update your libxml2 version and restart your web server." : "Za rešitev te težave je treba posodobiti knjižnico libxml2 in nato ponovno zagnati spletni strežnik.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : " Izgleda, da je PHP nastavljen, da odreže znake v 'inline doc' blokih. To bo povzročilo, da nekateri osnovni moduli ne bodo dosegljivi.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Napako je najverjetneje povzročil predpomnilnik ali pospeševalnik, kot sta Zend OPcache ali eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "Ali so bili moduli PHP nameščeni, pa so še vedno označeni kot manjkajoči?",
+ "Please ask your server administrator to restart the web server." : "Obvestite skrbnika strežnika, da je treba ponovno zagnati spletni strežnik.",
+ "PostgreSQL >= 9 required" : "Zahtevana je različica PostgreSQL >= 9.",
+ "Please upgrade your database version" : "Posodobite različico podatkovne zbirke.",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Spremenite dovoljenja mape na 0770 in s tem onemogočite branje vsebine drugim uporabnikom.",
+ "Check the value of \"datadirectory\" in your configuration" : "V konfiguraciji preverite nastavitev \"datadirectory\"",
+ "Could not obtain lock type %d on \"%s\"." : "Ni mogoče pridobiti zaklepa %d na \"%s\".",
+ "Storage unauthorized. %s" : "Dostop do shrambe ni overjen. %s",
+ "Storage incomplete configuration. %s" : "Nepopolna nastavitev shrambe. %s",
+ "Storage connection error. %s" : "Napaka povezave do shrambe. %s",
+ "Storage connection timeout. %s" : "Povezava do shrambe je časovno potekla. %s",
+ "Tips & tricks" : "Triki in nasveti"
+},
+"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);");
diff --git a/lib/l10n/sl.json b/lib/l10n/sl.json
new file mode 100644
index 00000000000..86ebbe50369
--- /dev/null
+++ b/lib/l10n/sl.json
@@ -0,0 +1,133 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Mapa 'config' nima določenih ustreznih dovoljenj za pisanje!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Napako je mogoče odpraviti z dodelitvijo dovoljenja spletnemu strežniku za pisanje v nastavitveno mapo.",
+ "See %s" : "Oglejte si %s",
+ "Sample configuration detected" : "Zaznana je neustrezna preizkusna nastavitev",
+ "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" : "Zaznano je, da je bila v sistem kopirana datoteka z enostavno nastavitvijo. To lahko vpliva na namestitev in zato možnost ni podprta. Pred spremembami datoteke config.php si natančno preberite dokumentacijo.",
+ "%1$s and %2$s" : "%1$s in %2$s",
+ "%1$s, %2$s and %3$s" : "%1$s, %2$s in %3$s",
+ "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s in %4$s",
+ "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s in %5$s",
+ "PHP %s or higher is required." : "Zahtevana je različica PHP %s ali višja.",
+ "PHP with a version lower than %s is required." : "Zahtevana je različica PHP manj kot %s.",
+ "%sbit or higher PHP required." : "Zahtevana je različica PHP %s ali višja.",
+ "Following databases are supported: %s" : "Podprte so navedene podatkovne zbirke: %s",
+ "The command line tool %s could not be found" : "Orodja ukazne vrstice %s ni mogoče najti",
+ "The library %s is not available." : "Knjižnica %s ni na voljo.",
+ "Library %s with a version higher than %s is required - available version %s." : "Zahtevana je knjižnica %s z različico, višjo od %s – na voljo je različica %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "Zahtevana je knjižnica %s z različico, manjšo od %s – na voljo je različica %s.",
+ "Following platforms are supported: %s" : "Podprta so okolja: %s",
+ "Server version %s or higher is required." : "Zahtevana je različica strežnika %s ali višja.",
+ "Server version %s or lower is required." : "Zahtevana je različica strežnika %s ali nižja.",
+ "Unknown filetype" : "Neznana vrsta datoteke",
+ "Invalid image" : "Neveljavna slika",
+ "today" : "danes",
+ "yesterday" : "včeraj",
+ "_%n day ago_::_%n days ago_" : ["pred %n dnevom","pred %n dnevoma","pred %n dnevi","pred %n dnevi"],
+ "last month" : "zadnji mesec",
+ "_%n month ago_::_%n months ago_" : ["pred %n mesecem","pred %n mesecema","pred %n meseci","pred %n meseci"],
+ "last year" : "lansko leto",
+ "_%n year ago_::_%n years ago_" : ["pred %n letom","pred %n letoma","pred %n leti","pred %n leti"],
+ "_%n hour ago_::_%n hours ago_" : ["pred %n uro","pred %n urama","pred %n urami","pred %n urami"],
+ "_%n minute ago_::_%n minutes ago_" : ["pred %n minuto","pred %n minutama","pred %n minutami","pred %n minutami"],
+ "seconds ago" : "pred nekaj sekundami",
+ "File name is a reserved word" : "Ime datoteke je zadržana beseda",
+ "File name contains at least one invalid character" : "Ime datoteke vsebuje vsaj en neveljaven znak.",
+ "File name is too long" : "Ime datoteke je predolgo",
+ "Dot files are not allowed" : "Skrite datoteke niso dovoljene",
+ "Empty filename is not allowed" : "Prazno polje imena datoteke ni dovoljeno.",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "Programa \\\"%s\\\" ni mogoče namestiti, ker ni mogoče brati datoteke appinfo.",
+ "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Programa »%s« ni mogoče namestiti, ker ni združljiv z nameščeno različico strežnika.",
+ "__language_name__" : "Slovenščina",
+ "Apps" : "Programi",
+ "Users" : "Uporabniki",
+ "Unknown user" : "Neznan uporabnik",
+ "Basic settings" : "Osnovne nastavitve",
+ "Security" : "Varnost",
+ "%s enter the database username and name." : "%s - vnos uporabniškega imena in imena podatkovne zbirke.",
+ "%s enter the database username." : "%s - vnos uporabniškega imena podatkovne zbirke.",
+ "%s enter the database name." : "%s - vnos imena podatkovne zbirke.",
+ "%s you may not use dots in the database name" : "%s - v imenu podatkovne zbirke ni dovoljeno uporabljati pik.",
+ "Oracle connection could not be established" : "Povezave s sistemom Oracle ni mogoče vzpostaviti.",
+ "Oracle username and/or password not valid" : "Uporabniško ime ali geslo Oracle ni veljavno",
+ "PostgreSQL username and/or password not valid" : "Uporabniško ime ali geslo PostgreSQL ni veljavno",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Sistem Mac OS X ni podprt, zato %s v tem okolju ne bo deloval zanesljivo. Program uporabljate na lastno odgovornost! ",
+ "For the best results, please consider using a GNU/Linux server instead." : "Za najbolj še rezultate je priporočljivo uporabljati strežnik GNU/Linux.",
+ "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." : "Videti je, da je dejavna seja %s zagnana v 32-bitnem okolju PHP in, da je v datoteki php.ini nastavljen open_basedir . Tako delovanje ni priporočljivo, saj se lahko pojavijo težave z datotekami, večjimi od 4GB.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Odstraniti je treba nastavitev open_basedir v datoteki php.ini ali pa preklopiti na 64-bitno okolje PHP.",
+ "Set an admin username." : "Nastavi uporabniško ime skrbnika.",
+ "Set an admin password." : "Nastavi geslo skrbnika.",
+ "Can't create or write into the data directory %s" : "Ni mogoče zapisati podatkov v podatkovno mapo %s",
+ "Invalid Federated Cloud ID" : "Neveljaven ID zveznega oblaka ownCloud",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "Omogočanje souporabe %s je spodletelo, ker ozadnji program ne dopušča souporabe vrste %i.",
+ "Sharing %s failed, because the file does not exist" : "Souporaba %s je spodletela, ker ta datoteka ne obstaja",
+ "You are not allowed to share %s" : "Omogočanje souporabe %s brez ustreznih dovoljenj ni mogoče.",
+ "Sharing %s failed, because you can not share with yourself" : "Nastavitev %s souporabe je spodletela, ker souporaba s samim seboj ni mogoča.",
+ "Sharing %s failed, because the user %s does not exist" : "Nastavljanje souporabe %s je spodletelo, ker uporabnik %s ne obstaja.",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Nastavljanje souporabe %s je spodletelo, ker uporabnik %s ni član nobene skupine, v kateri je tudi uporabnik %s.",
+ "Sharing %s failed, because this item is already shared with %s" : "Nastavljanje souporabe %s je spodletela, ker je ima uporabnik %s predmet že v souporabi.",
+ "Sharing %s failed, because this item is already shared with user %s" : "Nastavljanje souporabe %s je spodletelo, ker je predmet že v souporabi z uporabnikom %s.",
+ "Sharing %s failed, because the group %s does not exist" : "Nastavljanje souporabe %s je spodletelo, ker je skupina %s ne obstaja.",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Nastavljanje souporabe %s je spodletelo, ker uporabnik %s ni član skupine %s.",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Navesti je treba geslo za ustvarjanje javne povezave, saj so dovoljene le zaščitene.",
+ "Sharing %s failed, because sharing with links is not allowed" : "Nastavljanje souporabe %s je spodletelo, ker souporaba preko povezave ni dovoljena.",
+ "Not allowed to create a federated share with the same user" : "Ni dovoljeno ustvariti souporabe zveznega oblaka z istim uporabnikom",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Omogočanje souporabe %s je spodletelo, ker ni mogoče najti %s. Najverjetneje je strežnik nedosegljiv.",
+ "Share type %s is not valid for %s" : "Vrsta souporabe %s za %s ni veljavna.",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Ni mogoče določiti datuma preteka. Ni dovoljeno, da so mape ali datoteke, dodeljene v souporabo, v souporabi po %s.",
+ "Cannot set expiration date. Expiration date is in the past" : "Ni mogoče nastaviti datuma preteka. Ta datum je že preteklost.",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Souporaba ozadnjega programa %s mora vsebovati tudi vmesnik OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Ozadnjega programa %s za souporabo ni mogoče najti",
+ "Sharing backend for %s not found" : "Ozadnjega programa za souporabo za %s ni mogoče najti",
+ "Sharing failed, because the user %s is the original sharer" : "Nastavitev souporabe je spodletela, ker je uporabnik %s souporabo izvorno nastavil.",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Nastavljanje souporabe %s je spodletelo, ker zahteve presegajo dodeljena dovoljenja za %s.",
+ "Sharing %s failed, because resharing is not allowed" : "Nastavljanje souporabe %s je spodletelo, ker nadaljnje omogočanje souporabe ni dovoljeno.",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Nastavljanje souporabe %s je spodletelo, ker ozadnji program %s ne upravlja z viri.",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Nastavljanje souporabe %s je spodletelo, ker v predpomnilniku zahtevana datoteka ne obstaja.",
+ "Expiration date is in the past" : "Datum preteka je že mimo!",
+ "%s shared »%s« with you" : "%s je omogočil souporabo »%s«",
+ "%s via %s" : "%s prek %s",
+ "Could not find category \"%s\"" : "Kategorije \"%s\" ni mogoče najti.",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "V uporabniškem imenu je dovoljeno uporabiti le znake: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"",
+ "A valid username must be provided" : "Navedeno mora biti veljavno uporabniško ime",
+ "Username contains whitespace at the beginning or at the end" : "Uporabniško ime vsebuje presledni znak na začetku ali na koncu imena.",
+ "A valid password must be provided" : "Navedeno mora biti veljavno geslo",
+ "The username is already being used" : "Vpisano uporabniško ime je že v uporabi",
+ "User disabled" : "Uporabnik je onemogočen",
+ "Login canceled by app" : "Aplikacija je prijavo prekinila.",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "Programa \"%s\" ni mogoče namestiti zaradi nerešenih odvisnosti: %s",
+ "a safe home for all your data" : "varen dom za vse vaše podatke",
+ "File is currently busy, please try again later" : "Datoteka je trenutno v uporabi. Poskusite znova kasneje.",
+ "Can't read file" : "Datoteke ni mogoče prebrati.",
+ "Application is not enabled" : "Program ni omogočen",
+ "Authentication error" : "Napaka overjanja",
+ "Token expired. Please reload page." : "Žeton je potekel. Stran je treba ponovno naložiti.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Ni nameščenih programnikov podatkovnih zbirk (sqlite, mysql, ali postgresql).",
+ "Cannot write into \"config\" directory" : "Mapa 'config' nima nastavljenih ustreznih dovoljenj za pisanje!",
+ "Cannot write into \"apps\" directory" : "Mapa \"apps\" nima nastavljenih ustreznih dovoljenj za pisanje!",
+ "Setting locale to %s failed" : "Nastavljanje jezikovnih določil na %s je spodletelo.",
+ "Please install one of these locales on your system and restart your webserver." : "Namestiti je treba podporo za vsaj eno od navedenih jezikovnih določil v sistemu in nato ponovno zagnati spletni strežnik.",
+ "Please ask your server administrator to install the module." : "Obvestite skrbnika strežnika, da je treba namestiti manjkajoč modul.",
+ "PHP module %s not installed." : "Modul PHP %s ni nameščen.",
+ "PHP setting \"%s\" is not set to \"%s\"." : "Nastavitev PHP \"%s\" ni nastavljena na \"%s\".",
+ "Adjusting this setting in php.ini will make Nextcloud run again" : "Nastavitev tega parametra v <bold>php.ini</bold> bo vzpostavilo ponovno delovanje NextCloud",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload je nastavljeno na \"%s\" namesto pričakovane vrednosti \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Za reštev te težave nastavi <code>mbstring.func_overload</code> na <code>0</code> v tvojem php.ini",
+ "libxml2 2.7.0 is at least required. Currently %s is installed." : "libxml2 mora iti vsaj 2.7.0. Trenutno je nameščena %s.",
+ "To fix this issue update your libxml2 version and restart your web server." : "Za rešitev te težave je treba posodobiti knjižnico libxml2 in nato ponovno zagnati spletni strežnik.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : " Izgleda, da je PHP nastavljen, da odreže znake v 'inline doc' blokih. To bo povzročilo, da nekateri osnovni moduli ne bodo dosegljivi.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Napako je najverjetneje povzročil predpomnilnik ali pospeševalnik, kot sta Zend OPcache ali eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "Ali so bili moduli PHP nameščeni, pa so še vedno označeni kot manjkajoči?",
+ "Please ask your server administrator to restart the web server." : "Obvestite skrbnika strežnika, da je treba ponovno zagnati spletni strežnik.",
+ "PostgreSQL >= 9 required" : "Zahtevana je različica PostgreSQL >= 9.",
+ "Please upgrade your database version" : "Posodobite različico podatkovne zbirke.",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Spremenite dovoljenja mape na 0770 in s tem onemogočite branje vsebine drugim uporabnikom.",
+ "Check the value of \"datadirectory\" in your configuration" : "V konfiguraciji preverite nastavitev \"datadirectory\"",
+ "Could not obtain lock type %d on \"%s\"." : "Ni mogoče pridobiti zaklepa %d na \"%s\".",
+ "Storage unauthorized. %s" : "Dostop do shrambe ni overjen. %s",
+ "Storage incomplete configuration. %s" : "Nepopolna nastavitev shrambe. %s",
+ "Storage connection error. %s" : "Napaka povezave do shrambe. %s",
+ "Storage connection timeout. %s" : "Povezava do shrambe je časovno potekla. %s",
+ "Tips & tricks" : "Triki in nasveti"
+},"pluralForm" :"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"
+} \ No newline at end of file
diff --git a/lib/l10n/sq.js b/lib/l10n/sq.js
index 868ef665a91..ffb84891648 100644
--- a/lib/l10n/sq.js
+++ b/lib/l10n/sq.js
@@ -48,6 +48,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Nuk lejohen emra të zbrazët kartelash",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Aplikacioni \"%s\" s’mund të instalohet, ngaqë s’lexohet dot kartela appinfo.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Aplikacioni \"%s\" nuk mund të instalohet sepse nuk përputhet me këtë version të serverit.",
+ "__language_name__" : "Shqip",
"This is an automatically sent email, please do not reply." : "Ky është një email i dërguar automatikisht, ju lutem mos u përgjigjni.",
"Help" : "Ndihmë",
"Apps" : "Aplikacione",
@@ -55,18 +56,13 @@ OC.L10N.register(
"Log out" : "Shkyçu",
"Users" : "Përdorues",
"Unknown user" : "Përdorues i panjohur",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Konfigurime bazike",
"Sharing" : "Ndarja",
"Security" : "Siguria",
"Encryption" : "Enkriptimi",
"Additional settings" : "Konfigurime shtesë",
- "Tips & tricks" : "Këshilla dhe rrengje",
"Personal info" : "Informacion personal",
- "Sync clients" : "Klientë të sikronizuar",
"Unlimited" : "E palimituar",
- "__language_name__" : "_emri_i_gjuhës__",
"Verifying" : "Duke e verifikuar",
"Verifying …" : "Duke e verifikuar ...",
"Verify" : "Verifiko",
@@ -217,6 +213,10 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Formësim jo i plotë i depozitës. %s",
"Storage connection error. %s" : "Gabim lidhje te depozita. %s",
"Storage is temporarily not available" : "Hapsira ruajtëse nuk është në dispozicion përkohësisht",
- "Storage connection timeout. %s" : "Mbarim kohe lidhjeje për depozitën. %s"
+ "Storage connection timeout. %s" : "Mbarim kohe lidhjeje për depozitën. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Këshilla dhe rrengje",
+ "Sync clients" : "Klientë të sikronizuar"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/sq.json b/lib/l10n/sq.json
index a35cf7f6f90..edf0e868afb 100644
--- a/lib/l10n/sq.json
+++ b/lib/l10n/sq.json
@@ -46,6 +46,7 @@
"Empty filename is not allowed" : "Nuk lejohen emra të zbrazët kartelash",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Aplikacioni \"%s\" s’mund të instalohet, ngaqë s’lexohet dot kartela appinfo.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Aplikacioni \"%s\" nuk mund të instalohet sepse nuk përputhet me këtë version të serverit.",
+ "__language_name__" : "Shqip",
"This is an automatically sent email, please do not reply." : "Ky është një email i dërguar automatikisht, ju lutem mos u përgjigjni.",
"Help" : "Ndihmë",
"Apps" : "Aplikacione",
@@ -53,18 +54,13 @@
"Log out" : "Shkyçu",
"Users" : "Përdorues",
"Unknown user" : "Përdorues i panjohur",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Konfigurime bazike",
"Sharing" : "Ndarja",
"Security" : "Siguria",
"Encryption" : "Enkriptimi",
"Additional settings" : "Konfigurime shtesë",
- "Tips & tricks" : "Këshilla dhe rrengje",
"Personal info" : "Informacion personal",
- "Sync clients" : "Klientë të sikronizuar",
"Unlimited" : "E palimituar",
- "__language_name__" : "_emri_i_gjuhës__",
"Verifying" : "Duke e verifikuar",
"Verifying …" : "Duke e verifikuar ...",
"Verify" : "Verifiko",
@@ -215,6 +211,10 @@
"Storage incomplete configuration. %s" : "Formësim jo i plotë i depozitës. %s",
"Storage connection error. %s" : "Gabim lidhje te depozita. %s",
"Storage is temporarily not available" : "Hapsira ruajtëse nuk është në dispozicion përkohësisht",
- "Storage connection timeout. %s" : "Mbarim kohe lidhjeje për depozitën. %s"
+ "Storage connection timeout. %s" : "Mbarim kohe lidhjeje për depozitën. %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Këshilla dhe rrengje",
+ "Sync clients" : "Klientë të sikronizuar"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/sr.js b/lib/l10n/sr.js
index c45047be61f..647655f186f 100644
--- a/lib/l10n/sr.js
+++ b/lib/l10n/sr.js
@@ -4,7 +4,9 @@ OC.L10N.register(
"Cannot write into \"config\" directory!" : "Не могу да уписујем у „config“ директоријум!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Ово се обично може средити давањем права веб серверу да пише у директоријум са подешавањима",
"See %s" : "Погледајте %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Или, ако пре желите да задржите config.php да је само за читање, поставите опцију \"config_is_read_only\" на true у њему самом.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ово се обично може средити давањем права писања веб серверу за директоријум са подешавањима. Погледајте %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Или, ако пре желите да задржите config.php да је само за читање, поставите опцију \"config_is_read_only\" на true у њему самом. Погледајте %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Фајлови апликације „%$1s“ нису правилно замењени. Проверите да ли је верзија компатибилна са сервером.",
"Sample configuration detected" : "Откривен је пример подешавања",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Откривено је да је прекопиран пример подешавања. Ово може покварити инсталацију и није подржано. Прочитајте документацију пре вршења промена у фајлу config.php",
@@ -27,6 +29,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Подржане су следеће платформе: %s",
"Server version %s or higher is required." : "Потребна је верзија сервера %s или виша.",
"Server version %s or lower is required." : "Потребна је верзија сервера %s или нижа.",
+ "Logged in user must be an admin" : "Пријављени корисник мора бити администратор",
"Unknown filetype" : "Непознат тип фајла",
"Invalid image" : "Неисправна слика",
"Avatar image is not square" : "Слика аватара није квадратна",
@@ -57,6 +60,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Празан назив није дозвољен",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Апликација \"%s\" не може бити инсталирана јер appinfo фајл не може да се прочита.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Апликација \"%s\" не може бити инсталирана јер није компатибилна са овом верзијом сервера.",
+ "__language_name__" : "Српски",
"This is an automatically sent email, please do not reply." : "Ово је аутоматски генерисана порука, не одговарајте на њу.",
"Help" : "Помоћ",
"Apps" : "Апликације",
@@ -64,18 +68,20 @@ OC.L10N.register(
"Log out" : "Одјава",
"Users" : "Корисници",
"Unknown user" : "Непознат корисник",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Направи",
+ "Change" : "Измени",
+ "Delete" : "Обриши",
+ "Share" : "Подели",
+ "Overview" : "Преглед",
"Basic settings" : "Основне поставке",
"Sharing" : "Дељење",
"Security" : "Безбедност",
"Encryption" : "Шифровање",
+ "Groupware" : "Радни тимови",
"Additional settings" : "Додатне поставке",
- "Tips & tricks" : "Савети и трикови",
"Personal info" : "Лични подаци",
- "Sync clients" : "Клијенти у синхронизацији",
+ "Mobile & desktop" : "Мобилни и десктоп",
"Unlimited" : "Неограничено",
- "__language_name__" : "Српски",
"Verifying" : "Проверавам",
"Verifying …" : "Проверавам ...",
"Verify" : "Провери",
@@ -222,6 +228,11 @@ OC.L10N.register(
"Check the value of \"datadirectory\" in your configuration" : "Проверите податак за \"datadirectory\" у вашој конфигурацији",
"Your data directory is invalid" : "Директоријум са подацима није исправан",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Уверите се да фајл \".ocdata\" постоји у корену директоријума са подацима.",
+ "Action \"%s\" not supported or implemented." : "Радња \"%s\" није подржана или имплементирана.",
+ "Authentication failed, wrong token or provider ID given" : "Неуспела провера идентитета, добијен погрешан токен или ID провајдера",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Недостају параметри да би се довршио захтев. Недостајући параметри: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "Id \"%s\" већ користи провајдер клауд здруживања \"%s\"",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Провајдер клауд здруживања са ID-ом \"%s\" не постоји",
"Could not obtain lock type %d on \"%s\"." : "Не могу да остварим закључаност %d за „%s“.",
"Storage unauthorized. %s" : "Складиште није овлашћено. %s",
"Storage incomplete configuration. %s" : "Непотпуна конфигурација складишта. %s",
@@ -230,6 +241,9 @@ OC.L10N.register(
"Storage connection timeout. %s" : "Прекорачено време за повезивање на складиште. %s",
"Personal" : "Лично",
"Admin" : "Администратор",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Савети и трикови",
"DB Error: \"%s\"" : "Грешка базе података: \"%s\"",
"Offending command was: \"%s\"" : "Неисправна команда је: „%s“",
"Offending command was: \"%s\", name: %s, password: %s" : "Неисправна команда је: „%s“, назив: %s, лозинка: %s",
@@ -241,6 +255,7 @@ OC.L10N.register(
"Files can't be shared with create permissions" : "Фајлови не могу бити дељени са привилегијама за прављење",
"Cannot set expiration date more than %s days in the future" : "Датум истека не може да се постави више од %s дана у будућност",
"No app name specified" : "Није наведен назив апликације",
- "App '%s' could not be installed!" : "Апликација '%s' не може да се инсталира!"
+ "App '%s' could not be installed!" : "Апликација '%s' не може да се инсталира!",
+ "Sync clients" : "Клијенти у синхронизацији"
},
"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);");
diff --git a/lib/l10n/sr.json b/lib/l10n/sr.json
index b9452807f14..b32c258467c 100644
--- a/lib/l10n/sr.json
+++ b/lib/l10n/sr.json
@@ -2,7 +2,9 @@
"Cannot write into \"config\" directory!" : "Не могу да уписујем у „config“ директоријум!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Ово се обично може средити давањем права веб серверу да пише у директоријум са подешавањима",
"See %s" : "Погледајте %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Или, ако пре желите да задржите config.php да је само за читање, поставите опцију \"config_is_read_only\" на true у њему самом.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Ово се обично може средити давањем права писања веб серверу за директоријум са подешавањима. Погледајте %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Или, ако пре желите да задржите config.php да је само за читање, поставите опцију \"config_is_read_only\" на true у њему самом. Погледајте %s",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "Фајлови апликације „%$1s“ нису правилно замењени. Проверите да ли је верзија компатибилна са сервером.",
"Sample configuration detected" : "Откривен је пример подешавања",
"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Откривено је да је прекопиран пример подешавања. Ово може покварити инсталацију и није подржано. Прочитајте документацију пре вршења промена у фајлу config.php",
@@ -25,6 +27,7 @@
"Following platforms are supported: %s" : "Подржане су следеће платформе: %s",
"Server version %s or higher is required." : "Потребна је верзија сервера %s или виша.",
"Server version %s or lower is required." : "Потребна је верзија сервера %s или нижа.",
+ "Logged in user must be an admin" : "Пријављени корисник мора бити администратор",
"Unknown filetype" : "Непознат тип фајла",
"Invalid image" : "Неисправна слика",
"Avatar image is not square" : "Слика аватара није квадратна",
@@ -55,6 +58,7 @@
"Empty filename is not allowed" : "Празан назив није дозвољен",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Апликација \"%s\" не може бити инсталирана јер appinfo фајл не може да се прочита.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Апликација \"%s\" не може бити инсталирана јер није компатибилна са овом верзијом сервера.",
+ "__language_name__" : "Српски",
"This is an automatically sent email, please do not reply." : "Ово је аутоматски генерисана порука, не одговарајте на њу.",
"Help" : "Помоћ",
"Apps" : "Апликације",
@@ -62,18 +66,20 @@
"Log out" : "Одјава",
"Users" : "Корисници",
"Unknown user" : "Непознат корисник",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Направи",
+ "Change" : "Измени",
+ "Delete" : "Обриши",
+ "Share" : "Подели",
+ "Overview" : "Преглед",
"Basic settings" : "Основне поставке",
"Sharing" : "Дељење",
"Security" : "Безбедност",
"Encryption" : "Шифровање",
+ "Groupware" : "Радни тимови",
"Additional settings" : "Додатне поставке",
- "Tips & tricks" : "Савети и трикови",
"Personal info" : "Лични подаци",
- "Sync clients" : "Клијенти у синхронизацији",
+ "Mobile & desktop" : "Мобилни и десктоп",
"Unlimited" : "Неограничено",
- "__language_name__" : "Српски",
"Verifying" : "Проверавам",
"Verifying …" : "Проверавам ...",
"Verify" : "Провери",
@@ -220,6 +226,11 @@
"Check the value of \"datadirectory\" in your configuration" : "Проверите податак за \"datadirectory\" у вашој конфигурацији",
"Your data directory is invalid" : "Директоријум са подацима није исправан",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Уверите се да фајл \".ocdata\" постоји у корену директоријума са подацима.",
+ "Action \"%s\" not supported or implemented." : "Радња \"%s\" није подржана или имплементирана.",
+ "Authentication failed, wrong token or provider ID given" : "Неуспела провера идентитета, добијен погрешан токен или ID провајдера",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Недостају параметри да би се довршио захтев. Недостајући параметри: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "Id \"%s\" већ користи провајдер клауд здруживања \"%s\"",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "Провајдер клауд здруживања са ID-ом \"%s\" не постоји",
"Could not obtain lock type %d on \"%s\"." : "Не могу да остварим закључаност %d за „%s“.",
"Storage unauthorized. %s" : "Складиште није овлашћено. %s",
"Storage incomplete configuration. %s" : "Непотпуна конфигурација складишта. %s",
@@ -228,6 +239,9 @@
"Storage connection timeout. %s" : "Прекорачено време за повезивање на складиште. %s",
"Personal" : "Лично",
"Admin" : "Администратор",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Савети и трикови",
"DB Error: \"%s\"" : "Грешка базе података: \"%s\"",
"Offending command was: \"%s\"" : "Неисправна команда је: „%s“",
"Offending command was: \"%s\", name: %s, password: %s" : "Неисправна команда је: „%s“, назив: %s, лозинка: %s",
@@ -239,6 +253,7 @@
"Files can't be shared with create permissions" : "Фајлови не могу бити дељени са привилегијама за прављење",
"Cannot set expiration date more than %s days in the future" : "Датум истека не може да се постави више од %s дана у будућност",
"No app name specified" : "Није наведен назив апликације",
- "App '%s' could not be installed!" : "Апликација '%s' не може да се инсталира!"
+ "App '%s' could not be installed!" : "Апликација '%s' не може да се инсталира!",
+ "Sync clients" : "Клијенти у синхронизацији"
},"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"
} \ No newline at end of file
diff --git a/lib/l10n/sv.js b/lib/l10n/sv.js
index 8f62115859d..ff328b58aed 100644
--- a/lib/l10n/sv.js
+++ b/lib/l10n/sv.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Tomma filnamn är inte tillåtna",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Applikationen \"%s\" kan ej installeras eftersom informationen från appen ej kunde läsas.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Applikationen \"%s\" kan ej installeras eftersom den inte är kompatibel med denna serverversion.",
+ "__language_name__" : "Svenska",
"This is an automatically sent email, please do not reply." : "Detta är ett automatiskt skickat e-postmeddelande, svara inte på detta mejl.",
"Help" : "Hjälp",
"Apps" : "Applikationer",
@@ -64,18 +65,13 @@ OC.L10N.register(
"Log out" : "Logga ut",
"Users" : "Användare",
"Unknown user" : "Okänd användare",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Generella inställningar",
"Sharing" : "Delning",
"Security" : "Säkerhet",
"Encryption" : "Kryptering",
"Additional settings" : "Övriga inställningar",
- "Tips & tricks" : "Tips & tricks",
"Personal info" : "Personlig information",
- "Sync clients" : "Synkklienter",
"Unlimited" : "Obegränsad",
- "__language_name__" : "__language_name__",
"Verifying" : "Verifierar",
"Verifying …" : "Verifierar ...",
"Verify" : "Verifiera",
@@ -227,6 +223,10 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "Lagringsutrymme felaktigt inställt. %s",
"Storage connection error. %s" : "Lagringsutrymme lyckas inte ansluta. %s",
"Storage is temporarily not available" : "Lagringsutrymme är för tillfället inte tillgängligt",
- "Storage connection timeout. %s" : "Lagringsutrymme lyckas inte ansluta \"timeout\". %s"
+ "Storage connection timeout. %s" : "Lagringsutrymme lyckas inte ansluta \"timeout\". %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tips & tricks",
+ "Sync clients" : "Synkklienter"
},
"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/sv.json b/lib/l10n/sv.json
index 7e49c89319c..ea6ceff9a0a 100644
--- a/lib/l10n/sv.json
+++ b/lib/l10n/sv.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "Tomma filnamn är inte tillåtna",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "Applikationen \"%s\" kan ej installeras eftersom informationen från appen ej kunde läsas.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Applikationen \"%s\" kan ej installeras eftersom den inte är kompatibel med denna serverversion.",
+ "__language_name__" : "Svenska",
"This is an automatically sent email, please do not reply." : "Detta är ett automatiskt skickat e-postmeddelande, svara inte på detta mejl.",
"Help" : "Hjälp",
"Apps" : "Applikationer",
@@ -62,18 +63,13 @@
"Log out" : "Logga ut",
"Users" : "Användare",
"Unknown user" : "Okänd användare",
- "APCu" : "APCu",
- "Redis" : "Redis",
"Basic settings" : "Generella inställningar",
"Sharing" : "Delning",
"Security" : "Säkerhet",
"Encryption" : "Kryptering",
"Additional settings" : "Övriga inställningar",
- "Tips & tricks" : "Tips & tricks",
"Personal info" : "Personlig information",
- "Sync clients" : "Synkklienter",
"Unlimited" : "Obegränsad",
- "__language_name__" : "__language_name__",
"Verifying" : "Verifierar",
"Verifying …" : "Verifierar ...",
"Verify" : "Verifiera",
@@ -225,6 +221,10 @@
"Storage incomplete configuration. %s" : "Lagringsutrymme felaktigt inställt. %s",
"Storage connection error. %s" : "Lagringsutrymme lyckas inte ansluta. %s",
"Storage is temporarily not available" : "Lagringsutrymme är för tillfället inte tillgängligt",
- "Storage connection timeout. %s" : "Lagringsutrymme lyckas inte ansluta \"timeout\". %s"
+ "Storage connection timeout. %s" : "Lagringsutrymme lyckas inte ansluta \"timeout\". %s",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "Tips & tricks",
+ "Sync clients" : "Synkklienter"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/lib/l10n/ta_LK.js b/lib/l10n/ta_LK.js
new file mode 100644
index 00000000000..df9a6337a1f
--- /dev/null
+++ b/lib/l10n/ta_LK.js
@@ -0,0 +1,17 @@
+OC.L10N.register(
+ "lib",
+ {
+ "today" : "இன்று",
+ "yesterday" : "நேற்று",
+ "last month" : "கடந்த மாதம்",
+ "last year" : "கடந்த வருடம்",
+ "seconds ago" : "செக்கன்களுக்கு முன்",
+ "__language_name__" : "தமிழ்",
+ "Apps" : "செயலிகள்",
+ "Users" : "பயனாளர்",
+ "Could not find category \"%s\"" : "பிரிவு \"%s\" ஐ கண்டுப்பிடிக்க முடியவில்லை",
+ "Application is not enabled" : "செயலி இயலுமைப்படுத்தப்படவில்லை",
+ "Authentication error" : "அத்தாட்சிப்படுத்தலில் வழு",
+ "Token expired. Please reload page." : "அடையாளவில்லை காலாவதியாகிவிட்டது. தயவுசெய்து பக்கத்தை மீள் ஏற்றுக."
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/ta_LK.json b/lib/l10n/ta_LK.json
new file mode 100644
index 00000000000..b71fcc23a09
--- /dev/null
+++ b/lib/l10n/ta_LK.json
@@ -0,0 +1,15 @@
+{ "translations": {
+ "today" : "இன்று",
+ "yesterday" : "நேற்று",
+ "last month" : "கடந்த மாதம்",
+ "last year" : "கடந்த வருடம்",
+ "seconds ago" : "செக்கன்களுக்கு முன்",
+ "__language_name__" : "தமிழ்",
+ "Apps" : "செயலிகள்",
+ "Users" : "பயனாளர்",
+ "Could not find category \"%s\"" : "பிரிவு \"%s\" ஐ கண்டுப்பிடிக்க முடியவில்லை",
+ "Application is not enabled" : "செயலி இயலுமைப்படுத்தப்படவில்லை",
+ "Authentication error" : "அத்தாட்சிப்படுத்தலில் வழு",
+ "Token expired. Please reload page." : "அடையாளவில்லை காலாவதியாகிவிட்டது. தயவுசெய்து பக்கத்தை மீள் ஏற்றுக."
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/th.js b/lib/l10n/th.js
new file mode 100644
index 00000000000..18a7f7e825b
--- /dev/null
+++ b/lib/l10n/th.js
@@ -0,0 +1,119 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "ไม่สามารถเขียนลงในไดเรกทอรี \"การตั้งค่า\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "นี้จะสามารถแก้ไขได้โดยให้สิทธิ์การเขียนของเว็บเซิร์ฟเวอร์ไปยังการตั้งค่าไดเรกทอรี",
+ "See %s" : "เห็น %s",
+ "Sample configuration detected" : "ตรวจพบการกำหนดค่าตัวอย่าง",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "ตรวจพบว่าการกำหนดค่าตัวอย่างที่ถูกคัดลอก นี้สามารถทำลายการติดตั้งของคุณและไม่ได้รับการสนับสนุน โปรดอ่านเอกสารก่อนที่จะดำเนินการเปลี่ยนแปลงใน config.php",
+ "PHP %s or higher is required." : "จำเป็นต้องมี PHP รุ่น %s หรือที่สูงกว่า ",
+ "PHP with a version lower than %s is required." : "รุ่น PHP ของคุณต่ำกว่า %s",
+ "%sbit or higher PHP required." : "%sบิต หรือ PHP จะต้องเป็นรุ่นสูงกว่าที่กำหนด",
+ "Following databases are supported: %s" : "ฐานข้อมูลต่อไปนี้ได้รับการสนับสนุน: %s",
+ "The command line tool %s could not be found" : "ไม่พบเครื่องมือบรรทัดคำสั่ง %s ",
+ "The library %s is not available." : "ไลบรารี %s ไม่สามารถใช้ได้",
+ "Library %s with a version higher than %s is required - available version %s." : "จำเป็นต้องมีไลบรารีรุ่น %s หรือรุ่นที่สูงกว่า %s - รุ่นที่ใช้ได้คือ %s",
+ "Library %s with a version lower than %s is required - available version %s." : "จำเป็นต้องมีไลบรารีรุ่น %s หรือรุ่นที่ต่ำกว่า %s - รุ่นที่ใช้ได้คือ %s",
+ "Following platforms are supported: %s" : "แพลตฟอร์มต่อไปนี้ได้รับการสนับสนุน: %s",
+ "Unknown filetype" : "ไม่รู้จักชนิดของไฟล์",
+ "Invalid image" : "รูปภาพไม่ถูกต้อง",
+ "today" : "วันนี้",
+ "yesterday" : "เมื่อวานนี้",
+ "_%n day ago_::_%n days ago_" : ["%n วันที่ผ่านมา"],
+ "last month" : "เดือนที่แล้ว",
+ "_%n month ago_::_%n months ago_" : ["%n เดือนที่ผ่านมา"],
+ "last year" : "ปีที่แล้ว",
+ "_%n year ago_::_%n years ago_" : ["%n ปีที่ผ่านมา"],
+ "_%n hour ago_::_%n hours ago_" : ["%n ชั่วโมงที่ผ่านมา"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n นาทีที่ผ่านมา"],
+ "seconds ago" : "วินาที ก่อนหน้านี้",
+ "File name is a reserved word" : "ชื่อแฟ้มเป็นคำสงวน",
+ "File name contains at least one invalid character" : "ชื่อแฟ้มมีหนึ่งตัวอักษรที่ไม่ถูกต้อง",
+ "File name is too long" : "ชื่อแฟ้มยาวเกินไป",
+ "Dot files are not allowed" : "ชื่อไฟล์ห้ามมีจุด",
+ "Empty filename is not allowed" : "ชื่อไฟล์ห้ามว่างเปล่า",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "แอพฯ \"%s\" ไม่สามารถติดตั้งได้เพราะไฟล์ appInfo ไม่สามารถอ่านได้",
+ "__language_name__" : "ภาษาไทย - Thai languages",
+ "Apps" : "แอปฯ",
+ "Users" : "ผู้ใช้งาน",
+ "Unknown user" : "ไม่รู้จักผู้ใช้",
+ "%s enter the database username and name." : "%s ป้อนชื่อผู้ใช้ฐานข้อมูล และชื่อ",
+ "%s enter the database username." : "%s ใส่ชื่อผู้ใช้ฐานข้อมูล",
+ "%s enter the database name." : "%s ใส่ชื่อฐานข้อมูล",
+ "%s you may not use dots in the database name" : "%s บางที่คุณไม่ควรมีจุดในชื่อฐานข้อมูล",
+ "Oracle connection could not be established" : "ไม่สามารถสร้างการเชื่อมต่อกับ Oracle ",
+ "Oracle username and/or password not valid" : "Oracle ชื่อผู้ใช้ และ/หรือ รหัสผ่านไม่ถูกต้อง",
+ "PostgreSQL username and/or password not valid" : "PostgreSQL ชื่อผู้ใช้ และ/หรือ รหัสผ่านไม่ถูกต้อง",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "ระบบปฏิบัติการ Mac OS X ไม่ได้รับการสนับสนุนและ %s จะไม่ทำงานบนแพลตฟอร์มนี้ ใช้มันบนความเสี่ยงของคุณเอง!",
+ "For the best results, please consider using a GNU/Linux server instead." : "เพื่อให้ได้ผลลัพธ์ที่ดีที่สุดโปรดพิจารณาใช้เซิร์ฟเวอร์ GNU/Linux แทน",
+ "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." : "ดูเหมือนว่า %s ทำงานบน PHP 32 บิต และ open_basedir ได้ถูกกำหนดค่าใน php.ini ซึ่งจะมีปัญหาหากไฟล์มีขนาดกว่า 4 GB กิกะไบต์",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "กรุณาลบการตั้งค่า open_basedir ภายใน php.ini ของหรือเปลี่ยนไปใช้ PHP รุ่น 64 บิตแทน",
+ "Set an admin username." : "ตั้งค่าชื่อผู้ดูแลระบบ",
+ "Set an admin password." : "ตั้งค่ารหัสผ่านผู้ดูแลระบบ",
+ "Can't create or write into the data directory %s" : "ไม่สามารถสร้างหรือเขียนลงในข้อมูลไดเรกทอรี %s",
+ "Invalid Federated Cloud 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 ล้มเหลวเพราะไม่มีไฟล์นี้อยู่",
+ "You are not allowed to share %s" : "คุณยังไม่ได้รับอนุญาตให้แชร์ %s",
+ "Sharing %s failed, because you can not share with yourself" : "การแขร์ %s ล้มเหลวเพราะคุณไม่สามารถแชร์ให้กับตัวเอง",
+ "Sharing %s failed, because the user %s does not exist" : "การแชร์ %s ล้มเหลวเนื่องจากไม่ได้มีผู้ใช้ %s อยู่",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "การแชร์ %s ล้มเหลวเนื่องจากผู้ใช้ %s ไม่ได้เป็นสมาชิกของกลุ่มใดๆ %s เป็นสมาชิกของ",
+ "Sharing %s failed, because this item is already shared with %s" : "การแชร์ %s ล้มเหลวเพราะรายการนี้ถูกแชร์กับ %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "%s ที่กำลังแชร์ล้มเหลว เพราะรายการนี้ได้ถูกแชร์กับผู้ใช้ %s",
+ "Sharing %s failed, because the group %s does not exist" : "การแชร์ %s ล้มเหลวเพราะไม่มีกลุ่ม %s อยู่",
+ "Sharing %s failed, because %s is not a member of the group %s" : "การแชร์ %s ล้มเหลวเพราะ %s ไม่ได้เป็นสมาชิกของกลุ่ม %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "คุณจำเป็นต้องระบุรหัสผ่านเพื่อสร้างลิงค์สาธารณะ, ลิงค์ที่มีการป้องกันเท่านั้นที่ได้รับอนุญาต",
+ "Sharing %s failed, because sharing with links is not allowed" : "การแชร์ %s ล้มเหลวเพราะมีการแชร์ลิงค์ไม่ได้รับอนุญาต",
+ "Not allowed to create a federated share with the same user" : "ไม่อนุญาตให้สร้างแชร์สหพันธ์กับผู้ใช้เดียวกัน",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "การแชร์ %s ล้มเหลวไม่สามารถหา %s, บางทีอาจจะยังไม่สามารถเข้าถึงเซิร์ฟเวอร์ปัจจุบัน",
+ "Share type %s is not valid for %s" : "ประเภท %s ที่แชร์ไม่ถูกต้องสำหรับ %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "ไม่สามารถตั้งค่าวันหมดอายุ การแชร์ไม่สามารถหมดอายุน้อยกว่า %s หลังจากที่พวกเขาได้รับการแชร์",
+ "Cannot set expiration date. Expiration date is in the past" : "ไม่สามารถตั้งค่าวันหมดอายุ เพราะวันหมดอายุผ่านไปแล้ว",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "การแชร์แบ็กเอนด์ %s ต้องใช้อินเตอร์เฟซ OCP\\Share_Backend",
+ "Sharing backend %s not found" : "ไม่พบการแชร์แบ็กเอนด์ %s",
+ "Sharing backend for %s not found" : "ไม่พบการแชร์แบ็กเอนด์สำหรับ %s",
+ "Sharing failed, because the user %s is the original sharer" : "การแชร์ล้มเหลวเพราะผู้ใช้ %s เป็นต้นฉบับการแชร์นี้",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "การแชร์ %s ล้มเหลวเพราะใช้สิทธิ์เกินที่อนุญาตให้ %s",
+ "Sharing %s failed, because resharing is not allowed" : "การแชร์ %s ล้มเหลวเพราะการแชร์ต่อไม่ได้รับอนุญาต",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "การแชร์ %s ล้มเหลวเพราะการแชร์แบ็กเอนด์สำหรับ %s ไม่สามารถหาแหล่งที่มา",
+ "Sharing %s failed, because the file could not be found in the file cache" : "การแชร์ %s ล้มเหลวเพราะไม่พบไฟล์ในแคชไฟล์",
+ "Expiration date is in the past" : "วันหมดอายุอยู่ในอดีตที่ผ่านมา",
+ "%s shared »%s« with you" : "%s ถูกแชร์ »%s« กับคุณ",
+ "%s via %s" : "%s ผ่านทาง %s",
+ "Could not find category \"%s\"" : "ไม่พบหมวดหมู่ \"%s\"",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "ชื่อผู้ใช้จะใช้ได้แค่อักษรดังต่อไปนี้: \"a-z\", \"A-Z\", \"0-9\" และ \"_.@-'\"",
+ "A valid username must be provided" : "จะต้องระบุชื่อผู้ใช้ที่ถูกต้อง",
+ "A valid password must be provided" : "รหัสผ่านที่ถูกต้องจะต้องให้",
+ "The username is already being used" : "มีคนใช้ชื่อผู้ใช้นี้ไปแล้ว",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "แอพฯ \"%s\" ไม่สามารถติดตั้งเพราะไม่ได้ปฏิบัติตามการอ้างอิงต่อไปนี้: %s",
+ "File is currently busy, please try again later" : "ขณะนี้ไฟล์กำลังใช้งานอยู่ โปรดลองอีกครั้งในภายหลัง",
+ "Can't read file" : "ไม่สามารถอ่านไฟล์",
+ "Application is not enabled" : "แอพพลิเคชั่นดังกล่าวยังไม่ได้เปิดใช้งาน",
+ "Authentication error" : "เกิดข้อผิดพลาดในสิทธิ์การเข้าใช้งาน",
+ "Token expired. Please reload page." : "รหัสยืนยันความถูกต้องหมดอายุแล้ว กรุณาโหลดหน้าเว็บใหม่อีกครั้ง",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "ไม่มีไดรเวอร์ฐานข้อมูล (sqlite, mysql, or postgresql) ที่ถูกติดตั้ง",
+ "Cannot write into \"config\" directory" : "ไม่สามารถเขียนลงในไดเรกทอรี \"การตั้งค่า\"",
+ "Cannot write into \"apps\" directory" : "ไม่สามารถเขียนลงในไดเรกทอรี \"แอพฯ\"",
+ "Setting locale to %s failed" : "ตั้งค่าต้นทาง %s ล้มเหลว",
+ "Please install one of these locales on your system and restart your webserver." : "กรุณาติดตั้งหนึ่งในต้นทางเหล่านี้บนระบบของคุณและเริ่มต้นเว็บเซิร์ฟเวอร์ของคุณ",
+ "Please ask your server administrator to install the module." : "โปรดสอบถามผู้ดูแลระบบเซิร์ฟเวอร์ของคุณเพื่อติดตั้งโมดูล",
+ "PHP module %s not installed." : "โมดูล PHP %s ไม่ได้ถูกติดตั้ง",
+ "PHP setting \"%s\" is not set to \"%s\"." : "การตั้งค่า PHP \"%s\" ไม่ได้ตั้งค่าเป็น \"%s\"",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload ถูกตั้งเป็น \"%s\" แทนที่จะเป็น \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "หากต้องการแก้ไขปัญหานี้กรุณาแก้ <code>mbstring.func_overload</code> เป็น <code>0</code> ในไฟล์ php.ini ของคุณ",
+ "To fix this issue update your libxml2 version and restart your web server." : "เพื่อแก้ไขปัญหานี้ กรุณาอัพเดทรุ่นของ libxml2 และรีสตาร์ทเว็บเซิร์ฟเวอร์ของคุณ",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "เห็นได้ชัดว่า PHP มีการตั้งค่าเพื่อดึงบล็อกเอกสารแบบอินไลน์ ซึ่งจะทำให้แอพพลิเคชันไม่สามารถเข้าถึงได้",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "นี้อาจเกิดจาก cache/accelerator อย่างเช่น Zend OPcache หรือ eAccelerator",
+ "PHP modules have been installed, but they are still listed as missing?" : "โมดูล PHP ได้รับการติดตั้ง แต่พวกเขาไม่ได้ระบุไว้หรือมันอาจหายไป?",
+ "Please ask your server administrator to restart the web server." : "โปรดสอบถามผู้ดูแลระบบเซิร์ฟเวอร์ของคุณเพื่อเริ่มการทำงานของเว็บเซิร์ฟเวอร์",
+ "PostgreSQL >= 9 required" : "จำเป็นต้องใช้ PostgreSQL รุ่น >= 9",
+ "Please upgrade your database version" : "กรุณาอัพเดทฐานข้อมูลของคุณ",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "กรุณาเปลี่ยนสิทธิ์การเข้าถึงเป็น 0770 เพื่อให้ไดเรกทอรีไม่สามารถแก้ไขโดยผู้ใช้อื่น",
+ "Check the value of \"datadirectory\" in your configuration" : "ตรวจสอบค่าของ \"datadirectory\" ในการกำหนดค่าของคุณ",
+ "Could not obtain lock type %d on \"%s\"." : "ไม่สามารถรับล็อคชนิด %d บน \"%s\"",
+ "Storage unauthorized. %s" : "การจัดเก็บข้อมูลไม่ได้รับอนุญาต %s",
+ "Storage incomplete configuration. %s" : "การตั้งค่าการจัดเก็บข้อมูลไม่สำเร็จ %s",
+ "Storage connection error. %s" : "ข้อผิดพลาดการเชื่อมต่อพื้นที่จัดเก็บข้อมูล %s",
+ "Storage connection timeout. %s" : "หมดเวลาการเชื่อมต่อพื้นที่จัดเก็บข้อมูล %s"
+},
+"nplurals=1; plural=0;");
diff --git a/lib/l10n/th.json b/lib/l10n/th.json
new file mode 100644
index 00000000000..2decfc1bcda
--- /dev/null
+++ b/lib/l10n/th.json
@@ -0,0 +1,117 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "ไม่สามารถเขียนลงในไดเรกทอรี \"การตั้งค่า\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "นี้จะสามารถแก้ไขได้โดยให้สิทธิ์การเขียนของเว็บเซิร์ฟเวอร์ไปยังการตั้งค่าไดเรกทอรี",
+ "See %s" : "เห็น %s",
+ "Sample configuration detected" : "ตรวจพบการกำหนดค่าตัวอย่าง",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "ตรวจพบว่าการกำหนดค่าตัวอย่างที่ถูกคัดลอก นี้สามารถทำลายการติดตั้งของคุณและไม่ได้รับการสนับสนุน โปรดอ่านเอกสารก่อนที่จะดำเนินการเปลี่ยนแปลงใน config.php",
+ "PHP %s or higher is required." : "จำเป็นต้องมี PHP รุ่น %s หรือที่สูงกว่า ",
+ "PHP with a version lower than %s is required." : "รุ่น PHP ของคุณต่ำกว่า %s",
+ "%sbit or higher PHP required." : "%sบิต หรือ PHP จะต้องเป็นรุ่นสูงกว่าที่กำหนด",
+ "Following databases are supported: %s" : "ฐานข้อมูลต่อไปนี้ได้รับการสนับสนุน: %s",
+ "The command line tool %s could not be found" : "ไม่พบเครื่องมือบรรทัดคำสั่ง %s ",
+ "The library %s is not available." : "ไลบรารี %s ไม่สามารถใช้ได้",
+ "Library %s with a version higher than %s is required - available version %s." : "จำเป็นต้องมีไลบรารีรุ่น %s หรือรุ่นที่สูงกว่า %s - รุ่นที่ใช้ได้คือ %s",
+ "Library %s with a version lower than %s is required - available version %s." : "จำเป็นต้องมีไลบรารีรุ่น %s หรือรุ่นที่ต่ำกว่า %s - รุ่นที่ใช้ได้คือ %s",
+ "Following platforms are supported: %s" : "แพลตฟอร์มต่อไปนี้ได้รับการสนับสนุน: %s",
+ "Unknown filetype" : "ไม่รู้จักชนิดของไฟล์",
+ "Invalid image" : "รูปภาพไม่ถูกต้อง",
+ "today" : "วันนี้",
+ "yesterday" : "เมื่อวานนี้",
+ "_%n day ago_::_%n days ago_" : ["%n วันที่ผ่านมา"],
+ "last month" : "เดือนที่แล้ว",
+ "_%n month ago_::_%n months ago_" : ["%n เดือนที่ผ่านมา"],
+ "last year" : "ปีที่แล้ว",
+ "_%n year ago_::_%n years ago_" : ["%n ปีที่ผ่านมา"],
+ "_%n hour ago_::_%n hours ago_" : ["%n ชั่วโมงที่ผ่านมา"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n นาทีที่ผ่านมา"],
+ "seconds ago" : "วินาที ก่อนหน้านี้",
+ "File name is a reserved word" : "ชื่อแฟ้มเป็นคำสงวน",
+ "File name contains at least one invalid character" : "ชื่อแฟ้มมีหนึ่งตัวอักษรที่ไม่ถูกต้อง",
+ "File name is too long" : "ชื่อแฟ้มยาวเกินไป",
+ "Dot files are not allowed" : "ชื่อไฟล์ห้ามมีจุด",
+ "Empty filename is not allowed" : "ชื่อไฟล์ห้ามว่างเปล่า",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "แอพฯ \"%s\" ไม่สามารถติดตั้งได้เพราะไฟล์ appInfo ไม่สามารถอ่านได้",
+ "__language_name__" : "ภาษาไทย - Thai languages",
+ "Apps" : "แอปฯ",
+ "Users" : "ผู้ใช้งาน",
+ "Unknown user" : "ไม่รู้จักผู้ใช้",
+ "%s enter the database username and name." : "%s ป้อนชื่อผู้ใช้ฐานข้อมูล และชื่อ",
+ "%s enter the database username." : "%s ใส่ชื่อผู้ใช้ฐานข้อมูล",
+ "%s enter the database name." : "%s ใส่ชื่อฐานข้อมูล",
+ "%s you may not use dots in the database name" : "%s บางที่คุณไม่ควรมีจุดในชื่อฐานข้อมูล",
+ "Oracle connection could not be established" : "ไม่สามารถสร้างการเชื่อมต่อกับ Oracle ",
+ "Oracle username and/or password not valid" : "Oracle ชื่อผู้ใช้ และ/หรือ รหัสผ่านไม่ถูกต้อง",
+ "PostgreSQL username and/or password not valid" : "PostgreSQL ชื่อผู้ใช้ และ/หรือ รหัสผ่านไม่ถูกต้อง",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "ระบบปฏิบัติการ Mac OS X ไม่ได้รับการสนับสนุนและ %s จะไม่ทำงานบนแพลตฟอร์มนี้ ใช้มันบนความเสี่ยงของคุณเอง!",
+ "For the best results, please consider using a GNU/Linux server instead." : "เพื่อให้ได้ผลลัพธ์ที่ดีที่สุดโปรดพิจารณาใช้เซิร์ฟเวอร์ GNU/Linux แทน",
+ "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." : "ดูเหมือนว่า %s ทำงานบน PHP 32 บิต และ open_basedir ได้ถูกกำหนดค่าใน php.ini ซึ่งจะมีปัญหาหากไฟล์มีขนาดกว่า 4 GB กิกะไบต์",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "กรุณาลบการตั้งค่า open_basedir ภายใน php.ini ของหรือเปลี่ยนไปใช้ PHP รุ่น 64 บิตแทน",
+ "Set an admin username." : "ตั้งค่าชื่อผู้ดูแลระบบ",
+ "Set an admin password." : "ตั้งค่ารหัสผ่านผู้ดูแลระบบ",
+ "Can't create or write into the data directory %s" : "ไม่สามารถสร้างหรือเขียนลงในข้อมูลไดเรกทอรี %s",
+ "Invalid Federated Cloud 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 ล้มเหลวเพราะไม่มีไฟล์นี้อยู่",
+ "You are not allowed to share %s" : "คุณยังไม่ได้รับอนุญาตให้แชร์ %s",
+ "Sharing %s failed, because you can not share with yourself" : "การแขร์ %s ล้มเหลวเพราะคุณไม่สามารถแชร์ให้กับตัวเอง",
+ "Sharing %s failed, because the user %s does not exist" : "การแชร์ %s ล้มเหลวเนื่องจากไม่ได้มีผู้ใช้ %s อยู่",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "การแชร์ %s ล้มเหลวเนื่องจากผู้ใช้ %s ไม่ได้เป็นสมาชิกของกลุ่มใดๆ %s เป็นสมาชิกของ",
+ "Sharing %s failed, because this item is already shared with %s" : "การแชร์ %s ล้มเหลวเพราะรายการนี้ถูกแชร์กับ %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "%s ที่กำลังแชร์ล้มเหลว เพราะรายการนี้ได้ถูกแชร์กับผู้ใช้ %s",
+ "Sharing %s failed, because the group %s does not exist" : "การแชร์ %s ล้มเหลวเพราะไม่มีกลุ่ม %s อยู่",
+ "Sharing %s failed, because %s is not a member of the group %s" : "การแชร์ %s ล้มเหลวเพราะ %s ไม่ได้เป็นสมาชิกของกลุ่ม %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "คุณจำเป็นต้องระบุรหัสผ่านเพื่อสร้างลิงค์สาธารณะ, ลิงค์ที่มีการป้องกันเท่านั้นที่ได้รับอนุญาต",
+ "Sharing %s failed, because sharing with links is not allowed" : "การแชร์ %s ล้มเหลวเพราะมีการแชร์ลิงค์ไม่ได้รับอนุญาต",
+ "Not allowed to create a federated share with the same user" : "ไม่อนุญาตให้สร้างแชร์สหพันธ์กับผู้ใช้เดียวกัน",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "การแชร์ %s ล้มเหลวไม่สามารถหา %s, บางทีอาจจะยังไม่สามารถเข้าถึงเซิร์ฟเวอร์ปัจจุบัน",
+ "Share type %s is not valid for %s" : "ประเภท %s ที่แชร์ไม่ถูกต้องสำหรับ %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "ไม่สามารถตั้งค่าวันหมดอายุ การแชร์ไม่สามารถหมดอายุน้อยกว่า %s หลังจากที่พวกเขาได้รับการแชร์",
+ "Cannot set expiration date. Expiration date is in the past" : "ไม่สามารถตั้งค่าวันหมดอายุ เพราะวันหมดอายุผ่านไปแล้ว",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "การแชร์แบ็กเอนด์ %s ต้องใช้อินเตอร์เฟซ OCP\\Share_Backend",
+ "Sharing backend %s not found" : "ไม่พบการแชร์แบ็กเอนด์ %s",
+ "Sharing backend for %s not found" : "ไม่พบการแชร์แบ็กเอนด์สำหรับ %s",
+ "Sharing failed, because the user %s is the original sharer" : "การแชร์ล้มเหลวเพราะผู้ใช้ %s เป็นต้นฉบับการแชร์นี้",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "การแชร์ %s ล้มเหลวเพราะใช้สิทธิ์เกินที่อนุญาตให้ %s",
+ "Sharing %s failed, because resharing is not allowed" : "การแชร์ %s ล้มเหลวเพราะการแชร์ต่อไม่ได้รับอนุญาต",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "การแชร์ %s ล้มเหลวเพราะการแชร์แบ็กเอนด์สำหรับ %s ไม่สามารถหาแหล่งที่มา",
+ "Sharing %s failed, because the file could not be found in the file cache" : "การแชร์ %s ล้มเหลวเพราะไม่พบไฟล์ในแคชไฟล์",
+ "Expiration date is in the past" : "วันหมดอายุอยู่ในอดีตที่ผ่านมา",
+ "%s shared »%s« with you" : "%s ถูกแชร์ »%s« กับคุณ",
+ "%s via %s" : "%s ผ่านทาง %s",
+ "Could not find category \"%s\"" : "ไม่พบหมวดหมู่ \"%s\"",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "ชื่อผู้ใช้จะใช้ได้แค่อักษรดังต่อไปนี้: \"a-z\", \"A-Z\", \"0-9\" และ \"_.@-'\"",
+ "A valid username must be provided" : "จะต้องระบุชื่อผู้ใช้ที่ถูกต้อง",
+ "A valid password must be provided" : "รหัสผ่านที่ถูกต้องจะต้องให้",
+ "The username is already being used" : "มีคนใช้ชื่อผู้ใช้นี้ไปแล้ว",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "แอพฯ \"%s\" ไม่สามารถติดตั้งเพราะไม่ได้ปฏิบัติตามการอ้างอิงต่อไปนี้: %s",
+ "File is currently busy, please try again later" : "ขณะนี้ไฟล์กำลังใช้งานอยู่ โปรดลองอีกครั้งในภายหลัง",
+ "Can't read file" : "ไม่สามารถอ่านไฟล์",
+ "Application is not enabled" : "แอพพลิเคชั่นดังกล่าวยังไม่ได้เปิดใช้งาน",
+ "Authentication error" : "เกิดข้อผิดพลาดในสิทธิ์การเข้าใช้งาน",
+ "Token expired. Please reload page." : "รหัสยืนยันความถูกต้องหมดอายุแล้ว กรุณาโหลดหน้าเว็บใหม่อีกครั้ง",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "ไม่มีไดรเวอร์ฐานข้อมูล (sqlite, mysql, or postgresql) ที่ถูกติดตั้ง",
+ "Cannot write into \"config\" directory" : "ไม่สามารถเขียนลงในไดเรกทอรี \"การตั้งค่า\"",
+ "Cannot write into \"apps\" directory" : "ไม่สามารถเขียนลงในไดเรกทอรี \"แอพฯ\"",
+ "Setting locale to %s failed" : "ตั้งค่าต้นทาง %s ล้มเหลว",
+ "Please install one of these locales on your system and restart your webserver." : "กรุณาติดตั้งหนึ่งในต้นทางเหล่านี้บนระบบของคุณและเริ่มต้นเว็บเซิร์ฟเวอร์ของคุณ",
+ "Please ask your server administrator to install the module." : "โปรดสอบถามผู้ดูแลระบบเซิร์ฟเวอร์ของคุณเพื่อติดตั้งโมดูล",
+ "PHP module %s not installed." : "โมดูล PHP %s ไม่ได้ถูกติดตั้ง",
+ "PHP setting \"%s\" is not set to \"%s\"." : "การตั้งค่า PHP \"%s\" ไม่ได้ตั้งค่าเป็น \"%s\"",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload ถูกตั้งเป็น \"%s\" แทนที่จะเป็น \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "หากต้องการแก้ไขปัญหานี้กรุณาแก้ <code>mbstring.func_overload</code> เป็น <code>0</code> ในไฟล์ php.ini ของคุณ",
+ "To fix this issue update your libxml2 version and restart your web server." : "เพื่อแก้ไขปัญหานี้ กรุณาอัพเดทรุ่นของ libxml2 และรีสตาร์ทเว็บเซิร์ฟเวอร์ของคุณ",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "เห็นได้ชัดว่า PHP มีการตั้งค่าเพื่อดึงบล็อกเอกสารแบบอินไลน์ ซึ่งจะทำให้แอพพลิเคชันไม่สามารถเข้าถึงได้",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "นี้อาจเกิดจาก cache/accelerator อย่างเช่น Zend OPcache หรือ eAccelerator",
+ "PHP modules have been installed, but they are still listed as missing?" : "โมดูล PHP ได้รับการติดตั้ง แต่พวกเขาไม่ได้ระบุไว้หรือมันอาจหายไป?",
+ "Please ask your server administrator to restart the web server." : "โปรดสอบถามผู้ดูแลระบบเซิร์ฟเวอร์ของคุณเพื่อเริ่มการทำงานของเว็บเซิร์ฟเวอร์",
+ "PostgreSQL >= 9 required" : "จำเป็นต้องใช้ PostgreSQL รุ่น >= 9",
+ "Please upgrade your database version" : "กรุณาอัพเดทฐานข้อมูลของคุณ",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "กรุณาเปลี่ยนสิทธิ์การเข้าถึงเป็น 0770 เพื่อให้ไดเรกทอรีไม่สามารถแก้ไขโดยผู้ใช้อื่น",
+ "Check the value of \"datadirectory\" in your configuration" : "ตรวจสอบค่าของ \"datadirectory\" ในการกำหนดค่าของคุณ",
+ "Could not obtain lock type %d on \"%s\"." : "ไม่สามารถรับล็อคชนิด %d บน \"%s\"",
+ "Storage unauthorized. %s" : "การจัดเก็บข้อมูลไม่ได้รับอนุญาต %s",
+ "Storage incomplete configuration. %s" : "การตั้งค่าการจัดเก็บข้อมูลไม่สำเร็จ %s",
+ "Storage connection error. %s" : "ข้อผิดพลาดการเชื่อมต่อพื้นที่จัดเก็บข้อมูล %s",
+ "Storage connection timeout. %s" : "หมดเวลาการเชื่อมต่อพื้นที่จัดเก็บข้อมูล %s"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/lib/l10n/tr.js b/lib/l10n/tr.js
index 446e16f8023..000fc32efc7 100644
--- a/lib/l10n/tr.js
+++ b/lib/l10n/tr.js
@@ -4,7 +4,9 @@ OC.L10N.register(
"Cannot write into \"config\" directory!" : "\"config\" klasörüne yazılamadı!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Bu sorun genellikle, web sunucusuna config klasörüne yazma izni verilerek çözülebilir",
"See %s" : "Şuraya bakın: %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Ya da config.php dosyasının salt okunur olarak kalmasını istiyorsanız içindeki \"config_is_read_only\" seçeneğini true olarak ayarlayın.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Bu sorun genellikle, web sunucusuna config klasörüne yazma izni verilerek çözülebilir. %s bölümüne bakın",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Ya da config.php dosyasının salt okunur olarak kalmasını istiyorsanız içindeki \"config_is_read_only\" seçeneğini true olarak ayarlayın. %s bölümüne bakabilirsiniz",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "%1$s uygulamasının dosyaları doğru şekilde değiştirilmedi. Sunucu ile uyumlu dosyaların yüklü olduğundan emin olun.",
"Sample configuration detected" : "Örnek yapılandırma algılandı",
"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" : "Örnek yapılandırmanın kopyalanmış olabileceği tespit edildi. Bu durum kurulumunuzu bozabilir ve desteklenmez. Lütfen config.php dosyasında değişiklik yapmadan önce belgeleri okuyun",
@@ -14,7 +16,7 @@ OC.L10N.register(
"%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s ve %5$s",
"Education Edition" : "Eğitim Sürümü",
"Enterprise bundle" : "Kurumsal paket",
- "Groupware bundle" : "Grup paketi",
+ "Groupware bundle" : "Grup çalışması paketi",
"Social sharing bundle" : "Sosyal ağ paketi",
"PHP %s or higher is required." : "PHP %s ya da daha sonraki bir sürümü gerekli.",
"PHP with a version lower than %s is required." : "PHP %s ya da daha önceki bir sürümü gerekli.",
@@ -27,6 +29,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "Şu platformlar destekleniyor: %s",
"Server version %s or higher is required." : "Sunucu %s ya da daha sonraki bir sürüm olmalıdır.",
"Server version %s or lower is required." : "Sunucu %s ya da daha önceki bir sürüm olmalıdır.",
+ "Logged in user must be an admin" : "Oturum açmış kullanıcı bir yönetici olmalıdır",
"Unknown filetype" : "Dosya türü bilinmiyor",
"Invalid image" : "Görsel geçersiz",
"Avatar image is not square" : "Avatar görseli kare değil",
@@ -57,6 +60,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "Boş dosya adına izin verilmiyor",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "appinfo dosyası okunamadığından \"%s\" uygulaması kurulamaz.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "\"%s\" uygulaması sunucu sürümüyle uyumlu olmadığından kurulamaz.",
+ "__language_name__" : "Türkçe",
"This is an automatically sent email, please do not reply." : "Bu ileti otomatik olarak gönderildiğinden lütfen yanıtlamayın.",
"Help" : "Yardım",
"Apps" : "Uygulamalar",
@@ -64,18 +68,20 @@ OC.L10N.register(
"Log out" : "Oturumu Kapat",
"Users" : "Kullanıcılar",
"Unknown user" : "Kullanıcı bilinmiyor",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Ekle",
+ "Change" : "Düzenle",
+ "Delete" : "Sil",
+ "Share" : "Paylaş",
+ "Overview" : "Özet",
"Basic settings" : "Temel Ayarlar",
"Sharing" : "Paylaşım",
"Security" : "Güvenlik",
"Encryption" : "Şifreleme",
+ "Groupware" : "Grup çalışması",
"Additional settings" : "Ek ayarlar",
- "Tips & tricks" : "İpucu ve kolaylıklar",
"Personal info" : "Kişisel Bilgiler",
- "Sync clients" : "Eşitleme istemcileri",
+ "Mobile & desktop" : "Mobil ve masaüstü",
"Unlimited" : "Sınırsız",
- "__language_name__" : "Türkçe",
"Verifying" : "Doğrulanıyor",
"Verifying …" : "Doğrulanıyor...",
"Verify" : "Doğrula",
@@ -95,7 +101,7 @@ OC.L10N.register(
"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ı",
"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 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ı",
"You are not allowed to share %s" : "%s ögesini paylaşma izniniz yok",
"Sharing %s failed, because you can not share with yourself" : "%s paylaşılamadı. Ögeyi kendiniz ile paylaşamazsınız",
@@ -105,8 +111,8 @@ OC.L10N.register(
"Sharing %s failed, because this item is already shared with user %s" : "%s paylaşılamadı. Bu öge zaten %s kullanıcısı ile paylaşılmış",
"Sharing %s failed, because the group %s does not exist" : "%s paylaşılamadı. %s grubu bulunamadı",
"Sharing %s failed, because %s is not a member of the group %s" : "%s paylaşılamadı. %s kullanıcısı %s grubunun üyesi değil",
- "You need to provide a password to create a public link, only protected links are allowed" : "Herkese açık bir bağlantı oluşturmak için bir parola belirtmelisiniz. Yalnız korunmuş bağlantılara izin verilir",
- "Sharing %s failed, because sharing with links is not allowed" : "%s paylaşılamadı. Bağlantı üzerinden paylaşım izni verilmiyor",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Herkese açık bir bağlantı oluşturmak için bir parola belirtmelisiniz. Yalnız korunmuş bağlantılara izin verilir",
+ "Sharing %s failed, because sharing with links is not allowed" : "%s paylaşılamadı. Bağlantı üzerinden paylaşım izni verilmiyor",
"Not allowed to create a federated share with the same user" : "Aynı kullanıcı ile bir birleşmiş paylaşım oluşturulamaz",
"Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "%s paylaşılamadı. %s bulunamadı. Sunucuya şu anda erişilemiyor olabilir.",
"Share type %s is not valid for %s" : "%s paylaşım türü %s için geçerli değil",
@@ -222,6 +228,11 @@ OC.L10N.register(
"Check the value of \"datadirectory\" in your configuration" : "Yapılandırmanızdaki \"datadirectory\" seçeneğini denetleyin",
"Your data directory is invalid" : "Veri klasörünüz geçersiz",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Veri klasörü kökünde \".ocdata\" adında bir dosya bulunduğundan emin olun.",
+ "Action \"%s\" not supported or implemented." : "\"%s\" işlemi desteklenmiyor ya da henüz kullanılamıyor.",
+ "Authentication failed, wrong token or provider ID given" : "Kimlik doğrulanamadı. Belirtilen kod ya da hizmet sağlayıcı kodu hatalı",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "İsteğin tamamlanması için gerekli parametreler eksik: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "\"%s\" kodu zaten \"%s\" birleşmiş hizmet sağlayıcısı tarafından kullanılıyor",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "\"%s\" kodlu Birleşmiş Bulut Hizmeti Sağlayıcısı bulunamadı.",
"Could not obtain lock type %d on \"%s\"." : "\"%s\" için %d kilit türü alınamadı.",
"Storage unauthorized. %s" : "Depolamaya erişim izni yok. %s",
"Storage incomplete configuration. %s" : "Depolama yapılandırması tamamlanmamış. %s",
@@ -230,6 +241,9 @@ OC.L10N.register(
"Storage connection timeout. %s" : "Depolama bağlantısı zaman aşımı. %s",
"Personal" : "Kişisel",
"Admin" : "Yönetici",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "İpucu ve kolaylıklar",
"DB Error: \"%s\"" : "Veritabanı Sorunu: \"%s\"",
"Offending command was: \"%s\"" : "Saldırgan komut: \"%s\"",
"Offending command was: \"%s\", name: %s, password: %s" : "Saldırgan komut: \"%s\", kullanıcı adı: %s, parola: %s",
@@ -241,6 +255,7 @@ OC.L10N.register(
"Files can't be shared with create permissions" : "Dosyalar oluşturma izniyle paylaşılamaz",
"Cannot set expiration date more than %s days in the future" : "Paylaşımların son kullanım süreleri, gelecekte %s günden fazla olamaz",
"No app name specified" : "Uygulama adı belirtilmemiş",
- "App '%s' could not be installed!" : "'%s' uygulaması kurulamadı!"
+ "App '%s' could not be installed!" : "'%s' uygulaması kurulamadı!",
+ "Sync clients" : "Eşitleme istemcileri"
},
"nplurals=2; plural=(n > 1);");
diff --git a/lib/l10n/tr.json b/lib/l10n/tr.json
index 08385b3d2e7..a1683ccce5c 100644
--- a/lib/l10n/tr.json
+++ b/lib/l10n/tr.json
@@ -2,7 +2,9 @@
"Cannot write into \"config\" directory!" : "\"config\" klasörüne yazılamadı!",
"This can usually be fixed by giving the webserver write access to the config directory" : "Bu sorun genellikle, web sunucusuna config klasörüne yazma izni verilerek çözülebilir",
"See %s" : "Şuraya bakın: %s",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Ya da config.php dosyasının salt okunur olarak kalmasını istiyorsanız içindeki \"config_is_read_only\" seçeneğini true olarak ayarlayın.",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Bu sorun genellikle, web sunucusuna config klasörüne yazma izni verilerek çözülebilir. %s bölümüne bakın",
+ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Ya da config.php dosyasının salt okunur olarak kalmasını istiyorsanız içindeki \"config_is_read_only\" seçeneğini true olarak ayarlayın. %s bölümüne bakabilirsiniz",
"The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "%1$s uygulamasının dosyaları doğru şekilde değiştirilmedi. Sunucu ile uyumlu dosyaların yüklü olduğundan emin olun.",
"Sample configuration detected" : "Örnek yapılandırma algılandı",
"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" : "Örnek yapılandırmanın kopyalanmış olabileceği tespit edildi. Bu durum kurulumunuzu bozabilir ve desteklenmez. Lütfen config.php dosyasında değişiklik yapmadan önce belgeleri okuyun",
@@ -12,7 +14,7 @@
"%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s ve %5$s",
"Education Edition" : "Eğitim Sürümü",
"Enterprise bundle" : "Kurumsal paket",
- "Groupware bundle" : "Grup paketi",
+ "Groupware bundle" : "Grup çalışması paketi",
"Social sharing bundle" : "Sosyal ağ paketi",
"PHP %s or higher is required." : "PHP %s ya da daha sonraki bir sürümü gerekli.",
"PHP with a version lower than %s is required." : "PHP %s ya da daha önceki bir sürümü gerekli.",
@@ -25,6 +27,7 @@
"Following platforms are supported: %s" : "Şu platformlar destekleniyor: %s",
"Server version %s or higher is required." : "Sunucu %s ya da daha sonraki bir sürüm olmalıdır.",
"Server version %s or lower is required." : "Sunucu %s ya da daha önceki bir sürüm olmalıdır.",
+ "Logged in user must be an admin" : "Oturum açmış kullanıcı bir yönetici olmalıdır",
"Unknown filetype" : "Dosya türü bilinmiyor",
"Invalid image" : "Görsel geçersiz",
"Avatar image is not square" : "Avatar görseli kare değil",
@@ -55,6 +58,7 @@
"Empty filename is not allowed" : "Boş dosya adına izin verilmiyor",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "appinfo dosyası okunamadığından \"%s\" uygulaması kurulamaz.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "\"%s\" uygulaması sunucu sürümüyle uyumlu olmadığından kurulamaz.",
+ "__language_name__" : "Türkçe",
"This is an automatically sent email, please do not reply." : "Bu ileti otomatik olarak gönderildiğinden lütfen yanıtlamayın.",
"Help" : "Yardım",
"Apps" : "Uygulamalar",
@@ -62,18 +66,20 @@
"Log out" : "Oturumu Kapat",
"Users" : "Kullanıcılar",
"Unknown user" : "Kullanıcı bilinmiyor",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "Ekle",
+ "Change" : "Düzenle",
+ "Delete" : "Sil",
+ "Share" : "Paylaş",
+ "Overview" : "Özet",
"Basic settings" : "Temel Ayarlar",
"Sharing" : "Paylaşım",
"Security" : "Güvenlik",
"Encryption" : "Şifreleme",
+ "Groupware" : "Grup çalışması",
"Additional settings" : "Ek ayarlar",
- "Tips & tricks" : "İpucu ve kolaylıklar",
"Personal info" : "Kişisel Bilgiler",
- "Sync clients" : "Eşitleme istemcileri",
+ "Mobile & desktop" : "Mobil ve masaüstü",
"Unlimited" : "Sınırsız",
- "__language_name__" : "Türkçe",
"Verifying" : "Doğrulanıyor",
"Verifying …" : "Doğrulanıyor...",
"Verify" : "Doğrula",
@@ -93,7 +99,7 @@
"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ı",
"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 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ı",
"You are not allowed to share %s" : "%s ögesini paylaşma izniniz yok",
"Sharing %s failed, because you can not share with yourself" : "%s paylaşılamadı. Ögeyi kendiniz ile paylaşamazsınız",
@@ -103,8 +109,8 @@
"Sharing %s failed, because this item is already shared with user %s" : "%s paylaşılamadı. Bu öge zaten %s kullanıcısı ile paylaşılmış",
"Sharing %s failed, because the group %s does not exist" : "%s paylaşılamadı. %s grubu bulunamadı",
"Sharing %s failed, because %s is not a member of the group %s" : "%s paylaşılamadı. %s kullanıcısı %s grubunun üyesi değil",
- "You need to provide a password to create a public link, only protected links are allowed" : "Herkese açık bir bağlantı oluşturmak için bir parola belirtmelisiniz. Yalnız korunmuş bağlantılara izin verilir",
- "Sharing %s failed, because sharing with links is not allowed" : "%s paylaşılamadı. Bağlantı üzerinden paylaşım izni verilmiyor",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Herkese açık bir bağlantı oluşturmak için bir parola belirtmelisiniz. Yalnız korunmuş bağlantılara izin verilir",
+ "Sharing %s failed, because sharing with links is not allowed" : "%s paylaşılamadı. Bağlantı üzerinden paylaşım izni verilmiyor",
"Not allowed to create a federated share with the same user" : "Aynı kullanıcı ile bir birleşmiş paylaşım oluşturulamaz",
"Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "%s paylaşılamadı. %s bulunamadı. Sunucuya şu anda erişilemiyor olabilir.",
"Share type %s is not valid for %s" : "%s paylaşım türü %s için geçerli değil",
@@ -220,6 +226,11 @@
"Check the value of \"datadirectory\" in your configuration" : "Yapılandırmanızdaki \"datadirectory\" seçeneğini denetleyin",
"Your data directory is invalid" : "Veri klasörünüz geçersiz",
"Ensure there is a file called \".ocdata\" in the root of the data directory." : "Veri klasörü kökünde \".ocdata\" adında bir dosya bulunduğundan emin olun.",
+ "Action \"%s\" not supported or implemented." : "\"%s\" işlemi desteklenmiyor ya da henüz kullanılamıyor.",
+ "Authentication failed, wrong token or provider ID given" : "Kimlik doğrulanamadı. Belirtilen kod ya da hizmet sağlayıcı kodu hatalı",
+ "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "İsteğin tamamlanması için gerekli parametreler eksik: \"%s\"",
+ "Id \"%s\" already used by cloud federation provider \"%s\"" : "\"%s\" kodu zaten \"%s\" birleşmiş hizmet sağlayıcısı tarafından kullanılıyor",
+ "Cloud Federation Provider with ID: \"%s\" does not exist." : "\"%s\" kodlu Birleşmiş Bulut Hizmeti Sağlayıcısı bulunamadı.",
"Could not obtain lock type %d on \"%s\"." : "\"%s\" için %d kilit türü alınamadı.",
"Storage unauthorized. %s" : "Depolamaya erişim izni yok. %s",
"Storage incomplete configuration. %s" : "Depolama yapılandırması tamamlanmamış. %s",
@@ -228,6 +239,9 @@
"Storage connection timeout. %s" : "Depolama bağlantısı zaman aşımı. %s",
"Personal" : "Kişisel",
"Admin" : "Yönetici",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "İpucu ve kolaylıklar",
"DB Error: \"%s\"" : "Veritabanı Sorunu: \"%s\"",
"Offending command was: \"%s\"" : "Saldırgan komut: \"%s\"",
"Offending command was: \"%s\", name: %s, password: %s" : "Saldırgan komut: \"%s\", kullanıcı adı: %s, parola: %s",
@@ -239,6 +253,7 @@
"Files can't be shared with create permissions" : "Dosyalar oluşturma izniyle paylaşılamaz",
"Cannot set expiration date more than %s days in the future" : "Paylaşımların son kullanım süreleri, gelecekte %s günden fazla olamaz",
"No app name specified" : "Uygulama adı belirtilmemiş",
- "App '%s' could not be installed!" : "'%s' uygulaması kurulamadı!"
+ "App '%s' could not be installed!" : "'%s' uygulaması kurulamadı!",
+ "Sync clients" : "Eşitleme istemcileri"
},"pluralForm" :"nplurals=2; plural=(n > 1);"
} \ No newline at end of file
diff --git a/lib/l10n/ug.js b/lib/l10n/ug.js
new file mode 100644
index 00000000000..dceb30593e9
--- /dev/null
+++ b/lib/l10n/ug.js
@@ -0,0 +1,13 @@
+OC.L10N.register(
+ "lib",
+ {
+ "today" : "بۈگۈن",
+ "yesterday" : "تۈنۈگۈن",
+ "__language_name__" : "ئۇيغۇرچە",
+ "Apps" : "ئەپلەر",
+ "Users" : "ئىشلەتكۈچىلەر",
+ "A valid username must be provided" : "چوقۇم ئىناۋەتلىك ئىشلەتكۈچى ئىسمىدىن بىرنى تەمىنلەش كېرەك",
+ "A valid password must be provided" : "چوقۇم ئىناۋەتلىك ئىم تەمىنلەش كېرەك",
+ "Authentication error" : "سالاھىيەت دەلىللەش خاتالىقى"
+},
+"nplurals=1; plural=0;");
diff --git a/lib/l10n/ug.json b/lib/l10n/ug.json
new file mode 100644
index 00000000000..8af77f82c5d
--- /dev/null
+++ b/lib/l10n/ug.json
@@ -0,0 +1,11 @@
+{ "translations": {
+ "today" : "بۈگۈن",
+ "yesterday" : "تۈنۈگۈن",
+ "__language_name__" : "ئۇيغۇرچە",
+ "Apps" : "ئەپلەر",
+ "Users" : "ئىشلەتكۈچىلەر",
+ "A valid username must be provided" : "چوقۇم ئىناۋەتلىك ئىشلەتكۈچى ئىسمىدىن بىرنى تەمىنلەش كېرەك",
+ "A valid password must be provided" : "چوقۇم ئىناۋەتلىك ئىم تەمىنلەش كېرەك",
+ "Authentication error" : "سالاھىيەت دەلىللەش خاتالىقى"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/lib/l10n/uk.js b/lib/l10n/uk.js
new file mode 100644
index 00000000000..bbd0ce7b6bc
--- /dev/null
+++ b/lib/l10n/uk.js
@@ -0,0 +1,118 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Не можу писати у каталог \"config\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Зазвичай це можна виправити, надавши веб-серверу права на запис в теці конфігурації",
+ "See %s" : "Переглянути %s",
+ "Sample configuration detected" : "Виявлено приклад конфігурації",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Було виявлено, що приклад конфігурації було скопійовано. Це може нашкодити вашій системі та не підтримується. Будь ласка, зверніться до документації перед внесенням змін в файл config.php",
+ "PHP %s or higher is required." : "Необхідно PHP %s або вище",
+ "PHP with a version lower than %s is required." : "Потрібна версія PHP нижче %s ",
+ "Following databases are supported: %s" : "Підтримуються наступні сервери баз даних: %s",
+ "The command line tool %s could not be found" : "Утиліту командного рядка %s не знайдено",
+ "The library %s is not available." : "Бібліотека %s недоступна.",
+ "Library %s with a version higher than %s is required - available version %s." : "Потрібна бібліотека %s версії не більше %s, встановлена версія %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "Потрібна бібліотека %s версії менш ніж %s, встановлена версія %s.",
+ "Following platforms are supported: %s" : "Підтримуються наступні платформи: %s",
+ "Unknown filetype" : "Невідомий тип файлу",
+ "Invalid image" : "Невірне зображення",
+ "today" : "сьогодні",
+ "yesterday" : "вчора",
+ "_%n day ago_::_%n days ago_" : ["%n день тому","%n днів тому","%n днів тому","%n днів тому"],
+ "last month" : "минулого місяця",
+ "last year" : "минулого року",
+ "_%n year ago_::_%n years ago_" : ["%n рік тому","%n років тому","%n років тому","%n років тому"],
+ "seconds ago" : "секунди тому",
+ "File name is a reserved word" : "Ім’я файлу є зарезервованим словом",
+ "File name contains at least one invalid character" : "Ім’я файлу містить принаймні один некоректний символ",
+ "File name is too long" : "Ім’я файлу занадто довге",
+ "Dot files are not allowed" : "Файли які починаються з крапки не допустимі",
+ "Empty filename is not allowed" : "Порожні імена файлів не допускаються",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "Додаток \"%s\" не може бути встановлений через те, що файл appinfo не може бути прочитано.",
+ "__language_name__" : "Українська",
+ "Apps" : "Додатки",
+ "Users" : "Користувачі",
+ "Unknown user" : "Невідомий користувач",
+ "%s enter the database username and name." : "%s введіть назву бази даних та ім'я користувача.",
+ "%s enter the database username." : "%s введіть ім'я користувача бази даних.",
+ "%s enter the database name." : "%s введіть назву бази даних.",
+ "%s you may not use dots in the database name" : "%s не можна використовувати крапки в назві бази даних",
+ "Oracle connection could not be established" : "Не можемо з'єднатися з Oracle ",
+ "Oracle username and/or password not valid" : "Oracle ім'я користувача та/або пароль не дійсні",
+ "PostgreSQL username and/or password not valid" : "PostgreSQL ім'я користувача та/або пароль не дійсні",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X не підтримується і %s не буде коректно працювати на цій платформі. Випробовуєте на свій риск!",
+ "For the best results, please consider using a GNU/Linux server instead." : "Для кращих результатів розгляньте можливість використання GNU/Linux серверу",
+ "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." : "Здається що екземпляр цього %s працює в 32-бітному PHP середовищі і open_basedir повинен бути налаштований в php.ini. Це призведе до проблем з файлами більше 4 ГБ і це дуже не рекомендується.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Будь ласка, видаліть параметр open_basedir у вашому php.ini або перейдіть на 64-бітний PHP.",
+ "Set an admin username." : "Встановіть ім'я адміністратора.",
+ "Set an admin password." : "Встановіть пароль адміністратора.",
+ "Can't create or write into the data directory %s" : "Неможливо створити або записати каталог даних %s",
+ "Invalid Federated Cloud 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, оскільки файл не існує",
+ "You are not allowed to share %s" : "Вам заборонено поширювати %s",
+ "Sharing %s failed, because you can not share with yourself" : "Не вдалося поділитися %s, оскільки ви не можете ділитись самі з собою",
+ "Sharing %s failed, because the user %s does not exist" : "Не вдалося поділитися з %s, оскільки користувач %s не існує",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Не вдалося поділитися %s, оскільки користувач %s не є членом будь-якої групи в яку входить %s",
+ "Sharing %s failed, because this item is already shared with %s" : "Не вдалося поділитися %s, оскільки файл вже в загальному доступі з %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "Не вдалося поділитися %s, оскільки %s вже має до нього доступ",
+ "Sharing %s failed, because the group %s does not exist" : "Не вдалося поділитися %s, оскільки група %s не існує",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Не вдалося поділитися %s, оскільки %s не є членом групи %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Вам необхідно задати пароль для створення публічного посилання. Дозволені лише захищені посилання",
+ "Sharing %s failed, because sharing with links is not allowed" : "Не вдалося поділитися %s, оскільки публічний доступ через посилання заборонений",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Не вдалося поділитися %s, не вдалося знайти %s, можливо, сервер не доступний.",
+ "Share type %s is not valid for %s" : "Тип загального доступу %s неприпустимий для %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Неможливо встановити дату закінчення. Загальні ресурси не можуть застаріти пізніше %s з моменту їх публікації.",
+ "Cannot set expiration date. Expiration date is in the past" : "Неможливо встановити дату закінчення. Дата закінчення в минулому.",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Backend загального доступу %s повинен реалізовувати інтерфейс OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Backend загального доступу %s не знайдено",
+ "Sharing backend for %s not found" : "Бекенд загального доступу для %s не знайдено",
+ "Sharing failed, because the user %s is the original sharer" : "Не вдалося поділитися, оскільки %s є тим хто поділився з самого початку",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Не вдалося поділитися %s, права перевищують надані права доступу %s",
+ "Sharing %s failed, because resharing is not allowed" : "Не вдалося поділитися %s, перевідкриття доступу заборонено",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Не вдалося поділитися %s, backend загального доступу не знайшов шлях до %s",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Не вдалося поділитися %s, елемент не знайдено у файловому кеші.",
+ "Expiration date is in the past" : "Дата закінчення в минулому",
+ "%s shared »%s« with you" : "%s поділився »%s« з вами",
+ "%s via %s" : "%s за допомогою %s",
+ "Could not find category \"%s\"" : "Не вдалося знайти категорію \"%s\"",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Тільки такі символи допускаються в імені користувача: \"a-z\", \"A-Z\", \"0-9\", і \"_.@-'\"",
+ "A valid username must be provided" : "Потрібно задати вірне ім'я користувача",
+ "Username contains whitespace at the beginning or at the end" : "Ім'я користувача містить символ пробілу в початку або в кінці",
+ "A valid password must be provided" : "Потрібно задати вірний пароль",
+ "The username is already being used" : "Ім'я користувача вже використовується",
+ "User disabled" : "Користувач виключений",
+ "Login canceled by app" : "Вхід скасовано додатком",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "Додаток \"%s\" не може бути встановлений, так як наступні залежності не виконано: %s",
+ "File is currently busy, please try again later" : "Файл на разі зайнятий, будь ласка, спробуйте пізніше",
+ "Can't read file" : "Не можливо прочитати файл",
+ "Application is not enabled" : "Додаток не увімкнений",
+ "Authentication error" : "Помилка автентифікації",
+ "Token expired. Please reload page." : "Строк дії токена скінчився. Будь ласка, перезавантажте сторінку.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Не встановлено драйвер бази даних (sqlite, mysql, or postgresql).",
+ "Cannot write into \"config\" directory" : "Не можу писати у теку \"config\"",
+ "Cannot write into \"apps\" directory" : "Не можу писати у теку \"apps\"",
+ "Setting locale to %s failed" : "Установка локалі %s не вдалася",
+ "Please install one of these locales on your system and restart your webserver." : "Встановіть один із цих мовних пакетів в вашу систему і перезапустіть веб-сервер.",
+ "Please ask your server administrator to install the module." : "Будь ласка, зверніться до адміністратора, щоб встановити модуль.",
+ "PHP module %s not installed." : "%s модуль PHP не встановлено.",
+ "PHP setting \"%s\" is not set to \"%s\"." : "Параметр PHP \"%s\" не встановлено в \"%s\".",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload налаштовано як \"%s\" замість очікуваного значення \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Для виправлення змініть <code>mbstring.func_overload</code> на <code>0</code> у вашому php.ini",
+ "libxml2 2.7.0 is at least required. Currently %s is installed." : "Необхідно libxml2 версії принаймні 2.7.0. На разі встановлена %s.",
+ "To fix this issue update your libxml2 version and restart your web server." : "Що виправити це оновіть версію libxml2 та перезапустіть веб-сервер.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "Схоже, що PHP налаштовано на вичищення блоків вбудованої документації. Це зробить кілька основних додатків недоступними.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Це, ймовірно, обумовлено використанням кеша/прискорювача такого як Zend OPcache або eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "Модулі PHP були встановлені, але вони все ще перераховані як відсутні?",
+ "Please ask your server administrator to restart the web server." : "Будь ласка, зверніться до адміністратора, щоб перезавантажити сервер.",
+ "PostgreSQL >= 9 required" : "Потрібно PostgreSQL> = 9",
+ "Please upgrade your database version" : "Оновіть версію бази даних",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Змініть права доступу на 0770, щоб інші користувачі не могли отримати список файлів цього каталогу.",
+ "Check the value of \"datadirectory\" in your configuration" : "Перевірте значення \"datadirectory\" у своїй конфігурації",
+ "Could not obtain lock type %d on \"%s\"." : "Не вдалося отримати блокування типу %d для \"%s\"",
+ "Storage unauthorized. %s" : "Сховище не авторизовано. %s",
+ "Storage incomplete configuration. %s" : "Неповна конфігурація сховища. %s",
+ "Storage connection error. %s" : "Помилка з'єднання зі сховищем. %s",
+ "Storage connection timeout. %s" : "Час під'єднання до сховища вичерпався. %s"
+},
+"nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);");
diff --git a/lib/l10n/uk.json b/lib/l10n/uk.json
new file mode 100644
index 00000000000..4f6b08fbd9e
--- /dev/null
+++ b/lib/l10n/uk.json
@@ -0,0 +1,116 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Не можу писати у каталог \"config\"!",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "Зазвичай це можна виправити, надавши веб-серверу права на запис в теці конфігурації",
+ "See %s" : "Переглянути %s",
+ "Sample configuration detected" : "Виявлено приклад конфігурації",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Було виявлено, що приклад конфігурації було скопійовано. Це може нашкодити вашій системі та не підтримується. Будь ласка, зверніться до документації перед внесенням змін в файл config.php",
+ "PHP %s or higher is required." : "Необхідно PHP %s або вище",
+ "PHP with a version lower than %s is required." : "Потрібна версія PHP нижче %s ",
+ "Following databases are supported: %s" : "Підтримуються наступні сервери баз даних: %s",
+ "The command line tool %s could not be found" : "Утиліту командного рядка %s не знайдено",
+ "The library %s is not available." : "Бібліотека %s недоступна.",
+ "Library %s with a version higher than %s is required - available version %s." : "Потрібна бібліотека %s версії не більше %s, встановлена версія %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "Потрібна бібліотека %s версії менш ніж %s, встановлена версія %s.",
+ "Following platforms are supported: %s" : "Підтримуються наступні платформи: %s",
+ "Unknown filetype" : "Невідомий тип файлу",
+ "Invalid image" : "Невірне зображення",
+ "today" : "сьогодні",
+ "yesterday" : "вчора",
+ "_%n day ago_::_%n days ago_" : ["%n день тому","%n днів тому","%n днів тому","%n днів тому"],
+ "last month" : "минулого місяця",
+ "last year" : "минулого року",
+ "_%n year ago_::_%n years ago_" : ["%n рік тому","%n років тому","%n років тому","%n років тому"],
+ "seconds ago" : "секунди тому",
+ "File name is a reserved word" : "Ім’я файлу є зарезервованим словом",
+ "File name contains at least one invalid character" : "Ім’я файлу містить принаймні один некоректний символ",
+ "File name is too long" : "Ім’я файлу занадто довге",
+ "Dot files are not allowed" : "Файли які починаються з крапки не допустимі",
+ "Empty filename is not allowed" : "Порожні імена файлів не допускаються",
+ "App \"%s\" cannot be installed because appinfo file cannot be read." : "Додаток \"%s\" не може бути встановлений через те, що файл appinfo не може бути прочитано.",
+ "__language_name__" : "Українська",
+ "Apps" : "Додатки",
+ "Users" : "Користувачі",
+ "Unknown user" : "Невідомий користувач",
+ "%s enter the database username and name." : "%s введіть назву бази даних та ім'я користувача.",
+ "%s enter the database username." : "%s введіть ім'я користувача бази даних.",
+ "%s enter the database name." : "%s введіть назву бази даних.",
+ "%s you may not use dots in the database name" : "%s не можна використовувати крапки в назві бази даних",
+ "Oracle connection could not be established" : "Не можемо з'єднатися з Oracle ",
+ "Oracle username and/or password not valid" : "Oracle ім'я користувача та/або пароль не дійсні",
+ "PostgreSQL username and/or password not valid" : "PostgreSQL ім'я користувача та/або пароль не дійсні",
+ "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X не підтримується і %s не буде коректно працювати на цій платформі. Випробовуєте на свій риск!",
+ "For the best results, please consider using a GNU/Linux server instead." : "Для кращих результатів розгляньте можливість використання GNU/Linux серверу",
+ "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." : "Здається що екземпляр цього %s працює в 32-бітному PHP середовищі і open_basedir повинен бути налаштований в php.ini. Це призведе до проблем з файлами більше 4 ГБ і це дуже не рекомендується.",
+ "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Будь ласка, видаліть параметр open_basedir у вашому php.ini або перейдіть на 64-бітний PHP.",
+ "Set an admin username." : "Встановіть ім'я адміністратора.",
+ "Set an admin password." : "Встановіть пароль адміністратора.",
+ "Can't create or write into the data directory %s" : "Неможливо створити або записати каталог даних %s",
+ "Invalid Federated Cloud 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, оскільки файл не існує",
+ "You are not allowed to share %s" : "Вам заборонено поширювати %s",
+ "Sharing %s failed, because you can not share with yourself" : "Не вдалося поділитися %s, оскільки ви не можете ділитись самі з собою",
+ "Sharing %s failed, because the user %s does not exist" : "Не вдалося поділитися з %s, оскільки користувач %s не існує",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "Не вдалося поділитися %s, оскільки користувач %s не є членом будь-якої групи в яку входить %s",
+ "Sharing %s failed, because this item is already shared with %s" : "Не вдалося поділитися %s, оскільки файл вже в загальному доступі з %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "Не вдалося поділитися %s, оскільки %s вже має до нього доступ",
+ "Sharing %s failed, because the group %s does not exist" : "Не вдалося поділитися %s, оскільки група %s не існує",
+ "Sharing %s failed, because %s is not a member of the group %s" : "Не вдалося поділитися %s, оскільки %s не є членом групи %s",
+ "You need to provide a password to create a public link, only protected links are allowed" : "Вам необхідно задати пароль для створення публічного посилання. Дозволені лише захищені посилання",
+ "Sharing %s failed, because sharing with links is not allowed" : "Не вдалося поділитися %s, оскільки публічний доступ через посилання заборонений",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "Не вдалося поділитися %s, не вдалося знайти %s, можливо, сервер не доступний.",
+ "Share type %s is not valid for %s" : "Тип загального доступу %s неприпустимий для %s",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "Неможливо встановити дату закінчення. Загальні ресурси не можуть застаріти пізніше %s з моменту їх публікації.",
+ "Cannot set expiration date. Expiration date is in the past" : "Неможливо встановити дату закінчення. Дата закінчення в минулому.",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Backend загального доступу %s повинен реалізовувати інтерфейс OCP\\Share_Backend",
+ "Sharing backend %s not found" : "Backend загального доступу %s не знайдено",
+ "Sharing backend for %s not found" : "Бекенд загального доступу для %s не знайдено",
+ "Sharing failed, because the user %s is the original sharer" : "Не вдалося поділитися, оскільки %s є тим хто поділився з самого початку",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "Не вдалося поділитися %s, права перевищують надані права доступу %s",
+ "Sharing %s failed, because resharing is not allowed" : "Не вдалося поділитися %s, перевідкриття доступу заборонено",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "Не вдалося поділитися %s, backend загального доступу не знайшов шлях до %s",
+ "Sharing %s failed, because the file could not be found in the file cache" : "Не вдалося поділитися %s, елемент не знайдено у файловому кеші.",
+ "Expiration date is in the past" : "Дата закінчення в минулому",
+ "%s shared »%s« with you" : "%s поділився »%s« з вами",
+ "%s via %s" : "%s за допомогою %s",
+ "Could not find category \"%s\"" : "Не вдалося знайти категорію \"%s\"",
+ "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Тільки такі символи допускаються в імені користувача: \"a-z\", \"A-Z\", \"0-9\", і \"_.@-'\"",
+ "A valid username must be provided" : "Потрібно задати вірне ім'я користувача",
+ "Username contains whitespace at the beginning or at the end" : "Ім'я користувача містить символ пробілу в початку або в кінці",
+ "A valid password must be provided" : "Потрібно задати вірний пароль",
+ "The username is already being used" : "Ім'я користувача вже використовується",
+ "User disabled" : "Користувач виключений",
+ "Login canceled by app" : "Вхід скасовано додатком",
+ "App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "Додаток \"%s\" не може бути встановлений, так як наступні залежності не виконано: %s",
+ "File is currently busy, please try again later" : "Файл на разі зайнятий, будь ласка, спробуйте пізніше",
+ "Can't read file" : "Не можливо прочитати файл",
+ "Application is not enabled" : "Додаток не увімкнений",
+ "Authentication error" : "Помилка автентифікації",
+ "Token expired. Please reload page." : "Строк дії токена скінчився. Будь ласка, перезавантажте сторінку.",
+ "No database drivers (sqlite, mysql, or postgresql) installed." : "Не встановлено драйвер бази даних (sqlite, mysql, or postgresql).",
+ "Cannot write into \"config\" directory" : "Не можу писати у теку \"config\"",
+ "Cannot write into \"apps\" directory" : "Не можу писати у теку \"apps\"",
+ "Setting locale to %s failed" : "Установка локалі %s не вдалася",
+ "Please install one of these locales on your system and restart your webserver." : "Встановіть один із цих мовних пакетів в вашу систему і перезапустіть веб-сервер.",
+ "Please ask your server administrator to install the module." : "Будь ласка, зверніться до адміністратора, щоб встановити модуль.",
+ "PHP module %s not installed." : "%s модуль PHP не встановлено.",
+ "PHP setting \"%s\" is not set to \"%s\"." : "Параметр PHP \"%s\" не встановлено в \"%s\".",
+ "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "mbstring.func_overload налаштовано як \"%s\" замість очікуваного значення \"0\"",
+ "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Для виправлення змініть <code>mbstring.func_overload</code> на <code>0</code> у вашому php.ini",
+ "libxml2 2.7.0 is at least required. Currently %s is installed." : "Необхідно libxml2 версії принаймні 2.7.0. На разі встановлена %s.",
+ "To fix this issue update your libxml2 version and restart your web server." : "Що виправити це оновіть версію libxml2 та перезапустіть веб-сервер.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "Схоже, що PHP налаштовано на вичищення блоків вбудованої документації. Це зробить кілька основних додатків недоступними.",
+ "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Це, ймовірно, обумовлено використанням кеша/прискорювача такого як Zend OPcache або eAccelerator.",
+ "PHP modules have been installed, but they are still listed as missing?" : "Модулі PHP були встановлені, але вони все ще перераховані як відсутні?",
+ "Please ask your server administrator to restart the web server." : "Будь ласка, зверніться до адміністратора, щоб перезавантажити сервер.",
+ "PostgreSQL >= 9 required" : "Потрібно PostgreSQL> = 9",
+ "Please upgrade your database version" : "Оновіть версію бази даних",
+ "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Змініть права доступу на 0770, щоб інші користувачі не могли отримати список файлів цього каталогу.",
+ "Check the value of \"datadirectory\" in your configuration" : "Перевірте значення \"datadirectory\" у своїй конфігурації",
+ "Could not obtain lock type %d on \"%s\"." : "Не вдалося отримати блокування типу %d для \"%s\"",
+ "Storage unauthorized. %s" : "Сховище не авторизовано. %s",
+ "Storage incomplete configuration. %s" : "Неповна конфігурація сховища. %s",
+ "Storage connection error. %s" : "Помилка з'єднання зі сховищем. %s",
+ "Storage connection timeout. %s" : "Час під'єднання до сховища вичерпався. %s"
+},"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);"
+} \ No newline at end of file
diff --git a/lib/l10n/ur_PK.js b/lib/l10n/ur_PK.js
new file mode 100644
index 00000000000..eba333c571b
--- /dev/null
+++ b/lib/l10n/ur_PK.js
@@ -0,0 +1,15 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Unknown filetype" : "غیر معرروف قسم کی فائل",
+ "Invalid image" : "غلط تصویر",
+ "today" : "آج",
+ "yesterday" : "کل",
+ "last month" : "پچھلے مہنیے",
+ "last year" : "پچھلے سال",
+ "seconds ago" : "سیکنڈز پہلے",
+ "__language_name__" : "اردو",
+ "Apps" : "ایپز",
+ "Users" : "یوزرز"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/lib/l10n/ur_PK.json b/lib/l10n/ur_PK.json
new file mode 100644
index 00000000000..6a350b48006
--- /dev/null
+++ b/lib/l10n/ur_PK.json
@@ -0,0 +1,13 @@
+{ "translations": {
+ "Unknown filetype" : "غیر معرروف قسم کی فائل",
+ "Invalid image" : "غلط تصویر",
+ "today" : "آج",
+ "yesterday" : "کل",
+ "last month" : "پچھلے مہنیے",
+ "last year" : "پچھلے سال",
+ "seconds ago" : "سیکنڈز پہلے",
+ "__language_name__" : "اردو",
+ "Apps" : "ایپز",
+ "Users" : "یوزرز"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/lib/l10n/uz.js b/lib/l10n/uz.js
new file mode 100644
index 00000000000..988715b389e
--- /dev/null
+++ b/lib/l10n/uz.js
@@ -0,0 +1,7 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "\"Config\" katalogiga yozish mumkin emas!",
+ "January" : "Yanvar"
+},
+"nplurals=1; plural=0;");
diff --git a/lib/l10n/uz.json b/lib/l10n/uz.json
new file mode 100644
index 00000000000..b0a64514c3e
--- /dev/null
+++ b/lib/l10n/uz.json
@@ -0,0 +1,5 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "\"Config\" katalogiga yozish mumkin emas!",
+ "January" : "Yanvar"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/lib/l10n/vi.js b/lib/l10n/vi.js
new file mode 100644
index 00000000000..f42825aad46
--- /dev/null
+++ b/lib/l10n/vi.js
@@ -0,0 +1,25 @@
+OC.L10N.register(
+ "lib",
+ {
+ "Cannot write into \"config\" directory!" : "Không thể ghi vào thư mục \"config\"!",
+ "See %s" : "Xem %s",
+ "Unknown filetype" : "Không biết kiểu tập tin",
+ "Invalid image" : "Hình ảnh không hợp lệ",
+ "today" : "hôm nay",
+ "yesterday" : "hôm qua",
+ "last month" : "tháng trước",
+ "_%n month ago_::_%n months ago_" : ["%n tháng trước"],
+ "last year" : "năm trước",
+ "_%n hour ago_::_%n hours ago_" : ["%n giờ trước"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n phút trước"],
+ "seconds ago" : "vài giây trước",
+ "__language_name__" : "Tiếng Việt",
+ "Apps" : "Ứng dụng",
+ "Users" : "Người dùng",
+ "%s shared »%s« with you" : "%s đã chia sẻ »%s« với bạn",
+ "Could not find category \"%s\"" : "không thể tìm thấy mục \"%s\"",
+ "Application is not enabled" : "Ứng dụng không được BẬT",
+ "Authentication error" : "Lỗi xác thực",
+ "Token expired. Please reload page." : "Mã Token đã hết hạn. Hãy tải lại trang."
+},
+"nplurals=1; plural=0;");
diff --git a/lib/l10n/vi.json b/lib/l10n/vi.json
new file mode 100644
index 00000000000..6fe39695b02
--- /dev/null
+++ b/lib/l10n/vi.json
@@ -0,0 +1,23 @@
+{ "translations": {
+ "Cannot write into \"config\" directory!" : "Không thể ghi vào thư mục \"config\"!",
+ "See %s" : "Xem %s",
+ "Unknown filetype" : "Không biết kiểu tập tin",
+ "Invalid image" : "Hình ảnh không hợp lệ",
+ "today" : "hôm nay",
+ "yesterday" : "hôm qua",
+ "last month" : "tháng trước",
+ "_%n month ago_::_%n months ago_" : ["%n tháng trước"],
+ "last year" : "năm trước",
+ "_%n hour ago_::_%n hours ago_" : ["%n giờ trước"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n phút trước"],
+ "seconds ago" : "vài giây trước",
+ "__language_name__" : "Tiếng Việt",
+ "Apps" : "Ứng dụng",
+ "Users" : "Người dùng",
+ "%s shared »%s« with you" : "%s đã chia sẻ »%s« với bạn",
+ "Could not find category \"%s\"" : "không thể tìm thấy mục \"%s\"",
+ "Application is not enabled" : "Ứng dụng không được BẬT",
+ "Authentication error" : "Lỗi xác thực",
+ "Token expired. Please reload page." : "Mã Token đã hết hạn. Hãy tải lại trang."
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/lib/l10n/zh_CN.js b/lib/l10n/zh_CN.js
index 8fe3bb7c00d..1c5563cb264 100644
--- a/lib/l10n/zh_CN.js
+++ b/lib/l10n/zh_CN.js
@@ -57,6 +57,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "不允许使用空名称。",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "无法安装应用\"%s\",因为无法读取appinfo文件.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "应用程式 \"%s\" 无法安装,因为它与这个版本的服务器不兼容.",
+ "__language_name__" : "简体中文",
"This is an automatically sent email, please do not reply." : "这是一个自动生成的电子邮件,请不要回复。",
"Help" : "帮助",
"Apps" : "应用",
@@ -64,18 +65,17 @@ OC.L10N.register(
"Log out" : "注销",
"Users" : "用户",
"Unknown user" : "未知用户",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "创建",
+ "Change" : "修改",
+ "Delete" : "删除",
+ "Share" : "共享",
"Basic settings" : "基本设置",
"Sharing" : "分享",
"Security" : "安全",
"Encryption" : "加密",
"Additional settings" : "其他设置",
- "Tips & tricks" : "小提示",
"Personal info" : "个人信息",
- "Sync clients" : "同步客户",
"Unlimited" : "无限制",
- "__language_name__" : "简体中文",
"Verifying" : "验证",
"Verifying …" : "验证...",
"Verify" : "验证",
@@ -227,6 +227,13 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "存储未完成配置. %s",
"Storage connection error. %s" : "存储连接错误. %s",
"Storage is temporarily not available" : "存储暂时不可用",
- "Storage connection timeout. %s" : "存储连接超时. %s"
+ "Storage connection timeout. %s" : "存储连接超时. %s",
+ "Personal" : "个人",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "小提示",
+ "DB Error: \"%s\"" : "数据库错误:\"%s\"",
+ "No app name specified" : "没有指定的 App 名称",
+ "Sync clients" : "同步客户"
},
"nplurals=1; plural=0;");
diff --git a/lib/l10n/zh_CN.json b/lib/l10n/zh_CN.json
index 375d946c0cb..27aa81f926f 100644
--- a/lib/l10n/zh_CN.json
+++ b/lib/l10n/zh_CN.json
@@ -55,6 +55,7 @@
"Empty filename is not allowed" : "不允许使用空名称。",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "无法安装应用\"%s\",因为无法读取appinfo文件.",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "应用程式 \"%s\" 无法安装,因为它与这个版本的服务器不兼容.",
+ "__language_name__" : "简体中文",
"This is an automatically sent email, please do not reply." : "这是一个自动生成的电子邮件,请不要回复。",
"Help" : "帮助",
"Apps" : "应用",
@@ -62,18 +63,17 @@
"Log out" : "注销",
"Users" : "用户",
"Unknown user" : "未知用户",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "创建",
+ "Change" : "修改",
+ "Delete" : "删除",
+ "Share" : "共享",
"Basic settings" : "基本设置",
"Sharing" : "分享",
"Security" : "安全",
"Encryption" : "加密",
"Additional settings" : "其他设置",
- "Tips & tricks" : "小提示",
"Personal info" : "个人信息",
- "Sync clients" : "同步客户",
"Unlimited" : "无限制",
- "__language_name__" : "简体中文",
"Verifying" : "验证",
"Verifying …" : "验证...",
"Verify" : "验证",
@@ -225,6 +225,13 @@
"Storage incomplete configuration. %s" : "存储未完成配置. %s",
"Storage connection error. %s" : "存储连接错误. %s",
"Storage is temporarily not available" : "存储暂时不可用",
- "Storage connection timeout. %s" : "存储连接超时. %s"
+ "Storage connection timeout. %s" : "存储连接超时. %s",
+ "Personal" : "个人",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "小提示",
+ "DB Error: \"%s\"" : "数据库错误:\"%s\"",
+ "No app name specified" : "没有指定的 App 名称",
+ "Sync clients" : "同步客户"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/lib/l10n/zh_HK.js b/lib/l10n/zh_HK.js
new file mode 100644
index 00000000000..3efe314c7dc
--- /dev/null
+++ b/lib/l10n/zh_HK.js
@@ -0,0 +1,16 @@
+OC.L10N.register(
+ "lib",
+ {
+ "today" : "今日",
+ "yesterday" : "昨日",
+ "last month" : "前一月",
+ "_%n month ago_::_%n months ago_" : ["%n 月前"],
+ "last year" : "上年",
+ "_%n hour ago_::_%n hours ago_" : ["%n 小時前"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n 分鐘前"],
+ "seconds ago" : "秒前",
+ "__language_name__" : "繁體中文(香港)",
+ "Apps" : "軟件",
+ "Users" : "用戶"
+},
+"nplurals=1; plural=0;");
diff --git a/lib/l10n/zh_HK.json b/lib/l10n/zh_HK.json
new file mode 100644
index 00000000000..30482f15116
--- /dev/null
+++ b/lib/l10n/zh_HK.json
@@ -0,0 +1,14 @@
+{ "translations": {
+ "today" : "今日",
+ "yesterday" : "昨日",
+ "last month" : "前一月",
+ "_%n month ago_::_%n months ago_" : ["%n 月前"],
+ "last year" : "上年",
+ "_%n hour ago_::_%n hours ago_" : ["%n 小時前"],
+ "_%n minute ago_::_%n minutes ago_" : ["%n 分鐘前"],
+ "seconds ago" : "秒前",
+ "__language_name__" : "繁體中文(香港)",
+ "Apps" : "軟件",
+ "Users" : "用戶"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/lib/l10n/zh_TW.js b/lib/l10n/zh_TW.js
index f37dca588ca..280d1c5c180 100644
--- a/lib/l10n/zh_TW.js
+++ b/lib/l10n/zh_TW.js
@@ -5,8 +5,8 @@ OC.L10N.register(
"This can usually be fixed by giving the webserver write access to the config directory" : "允許網頁伺服器寫入 \"config\" 目錄通常可以解決這個問題",
"See %s" : "見 %s",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "允許網頁伺服器寫入 \"config\" 目錄通常可以解決這個問題,詳見 %s",
- "Sample configuration detected" : "偵測到範本設定",
- "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "看來您直接複製了範本設定來使用,這可能會毀掉你的安裝,請閱讀說明文件後對 config.php 進行適當的修改",
+ "Sample configuration detected" : "您目前正在使用範例設定",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "您似乎直接複製了範例設定來使用,這樣的安裝很可能會無法運作,請閱讀說明文件後對 config.php 進行適當的修改",
"%1$s and %2$s" : "%1$s 和 %2$s",
"%1$s, %2$s and %3$s" : "%1$s, %2$s 和 %3$s",
"PHP %s or higher is required." : "需要 PHP %s 或更高版本",
@@ -20,6 +20,7 @@ OC.L10N.register(
"Following platforms are supported: %s" : "支援下列平台: %s",
"Server version %s or higher is required." : "需要伺服器版本 %s 或更高",
"Server version %s or lower is required." : "需要伺服器版本 %s 或更低",
+ "Logged in user must be an admin" : "登入的使用者必須有管理員權限",
"Unknown filetype" : "未知的檔案類型",
"Invalid image" : "無效的圖片",
"Avatar image is not square" : "頭像不是正方形",
@@ -34,9 +35,13 @@ OC.L10N.register(
"_%n month ago_::_%n months ago_" : ["%n 個月前"],
"next year" : "明年",
"last year" : "去年",
- "_%n year ago_::_%n years ago_" : ["%n 幾年前"],
+ "_in %n year_::_in %n years_" : ["%n 年後"],
+ "_%n year ago_::_%n years ago_" : ["%n 年前"],
+ "_in %n hour_::_in %n hours_" : ["%n 小時後"],
"_%n hour ago_::_%n hours ago_" : ["%n 小時前"],
+ "_in %n minute_::_in %n minutes_" : ["%n 分鐘後"],
"_%n minute ago_::_%n minutes ago_" : ["%n 分鐘前"],
+ "in a few seconds" : "幾秒後",
"seconds ago" : "幾秒前",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "名為 %s 的模組不存在,請在應用程式設定中啟用,或是聯絡系統管理員",
"File name is a reserved word" : "檔案名稱是保留字",
@@ -46,6 +51,7 @@ OC.L10N.register(
"Empty filename is not allowed" : "不允許空白的檔名",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "應用程式 \"%s\" 無法安裝,因為無法讀取 appinfo 檔案。",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "應用程式 \"%s\" 無法安裝,因為該應用程式不相容於目前版本的伺服器。",
+ "__language_name__" : "正體中文(臺灣)",
"This is an automatically sent email, please do not reply." : "此為自動寄送的電子郵件,請不要回覆。",
"Help" : "說明",
"Apps" : "應用程式",
@@ -53,18 +59,17 @@ OC.L10N.register(
"Log out" : "登出",
"Users" : "使用者",
"Unknown user" : "未知的使用者",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "建立",
+ "Change" : "更改",
+ "Delete" : "刪除",
+ "Share" : "分享",
"Basic settings" : "基本設定",
"Sharing" : "分享",
"Security" : "安全性",
"Encryption" : "加密",
"Additional settings" : "其他設定",
- "Tips & tricks" : "使用祕訣",
"Personal info" : "個人資訊",
- "Sync clients" : "同步客戶端",
"Unlimited" : "無限",
- "__language_name__" : "__language_name__",
"Verifying" : "驗證中",
"Verifying …" : "驗證中…",
"Verify" : "驗證",
@@ -216,6 +221,17 @@ OC.L10N.register(
"Storage incomplete configuration. %s" : "儲存空間配置尚未完成。%s",
"Storage connection error. %s" : "儲存空間連線錯誤。%s",
"Storage is temporarily not available" : "儲存空間暫時無法使用",
- "Storage connection timeout. %s" : "儲存空間連線逾時。%s"
+ "Storage connection timeout. %s" : "儲存空間連線逾時。%s",
+ "Personal" : "個人",
+ "Admin" : "管理",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "使用祕訣",
+ "DB Error: \"%s\"" : "資料庫錯誤: %s",
+ "Offending command was: \"%s\"" : "有問題的指令: %s",
+ "Offending command was: \"%s\", name: %s, password: %s" : "有問題的指令: %s,名字: %s,密碼: %s",
+ "No app name specified" : "沒有指定應用程式名稱",
+ "App '%s' could not be installed!" : "應用程式 \"%s\" 無法被安裝",
+ "Sync clients" : "同步客戶端"
},
"nplurals=1; plural=0;");
diff --git a/lib/l10n/zh_TW.json b/lib/l10n/zh_TW.json
index e43cf6fd214..906623415f8 100644
--- a/lib/l10n/zh_TW.json
+++ b/lib/l10n/zh_TW.json
@@ -3,8 +3,8 @@
"This can usually be fixed by giving the webserver write access to the config directory" : "允許網頁伺服器寫入 \"config\" 目錄通常可以解決這個問題",
"See %s" : "見 %s",
"This can usually be fixed by giving the webserver write access to the config directory. See %s" : "允許網頁伺服器寫入 \"config\" 目錄通常可以解決這個問題,詳見 %s",
- "Sample configuration detected" : "偵測到範本設定",
- "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "看來您直接複製了範本設定來使用,這可能會毀掉你的安裝,請閱讀說明文件後對 config.php 進行適當的修改",
+ "Sample configuration detected" : "您目前正在使用範例設定",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "您似乎直接複製了範例設定來使用,這樣的安裝很可能會無法運作,請閱讀說明文件後對 config.php 進行適當的修改",
"%1$s and %2$s" : "%1$s 和 %2$s",
"%1$s, %2$s and %3$s" : "%1$s, %2$s 和 %3$s",
"PHP %s or higher is required." : "需要 PHP %s 或更高版本",
@@ -18,6 +18,7 @@
"Following platforms are supported: %s" : "支援下列平台: %s",
"Server version %s or higher is required." : "需要伺服器版本 %s 或更高",
"Server version %s or lower is required." : "需要伺服器版本 %s 或更低",
+ "Logged in user must be an admin" : "登入的使用者必須有管理員權限",
"Unknown filetype" : "未知的檔案類型",
"Invalid image" : "無效的圖片",
"Avatar image is not square" : "頭像不是正方形",
@@ -32,9 +33,13 @@
"_%n month ago_::_%n months ago_" : ["%n 個月前"],
"next year" : "明年",
"last year" : "去年",
- "_%n year ago_::_%n years ago_" : ["%n 幾年前"],
+ "_in %n year_::_in %n years_" : ["%n 年後"],
+ "_%n year ago_::_%n years ago_" : ["%n 年前"],
+ "_in %n hour_::_in %n hours_" : ["%n 小時後"],
"_%n hour ago_::_%n hours ago_" : ["%n 小時前"],
+ "_in %n minute_::_in %n minutes_" : ["%n 分鐘後"],
"_%n minute ago_::_%n minutes ago_" : ["%n 分鐘前"],
+ "in a few seconds" : "幾秒後",
"seconds ago" : "幾秒前",
"Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "名為 %s 的模組不存在,請在應用程式設定中啟用,或是聯絡系統管理員",
"File name is a reserved word" : "檔案名稱是保留字",
@@ -44,6 +49,7 @@
"Empty filename is not allowed" : "不允許空白的檔名",
"App \"%s\" cannot be installed because appinfo file cannot be read." : "應用程式 \"%s\" 無法安裝,因為無法讀取 appinfo 檔案。",
"App \"%s\" cannot be installed because it is not compatible with this version of the server." : "應用程式 \"%s\" 無法安裝,因為該應用程式不相容於目前版本的伺服器。",
+ "__language_name__" : "正體中文(臺灣)",
"This is an automatically sent email, please do not reply." : "此為自動寄送的電子郵件,請不要回覆。",
"Help" : "說明",
"Apps" : "應用程式",
@@ -51,18 +57,17 @@
"Log out" : "登出",
"Users" : "使用者",
"Unknown user" : "未知的使用者",
- "APCu" : "APCu",
- "Redis" : "Redis",
+ "Create" : "建立",
+ "Change" : "更改",
+ "Delete" : "刪除",
+ "Share" : "分享",
"Basic settings" : "基本設定",
"Sharing" : "分享",
"Security" : "安全性",
"Encryption" : "加密",
"Additional settings" : "其他設定",
- "Tips & tricks" : "使用祕訣",
"Personal info" : "個人資訊",
- "Sync clients" : "同步客戶端",
"Unlimited" : "無限",
- "__language_name__" : "__language_name__",
"Verifying" : "驗證中",
"Verifying …" : "驗證中…",
"Verify" : "驗證",
@@ -214,6 +219,17 @@
"Storage incomplete configuration. %s" : "儲存空間配置尚未完成。%s",
"Storage connection error. %s" : "儲存空間連線錯誤。%s",
"Storage is temporarily not available" : "儲存空間暫時無法使用",
- "Storage connection timeout. %s" : "儲存空間連線逾時。%s"
+ "Storage connection timeout. %s" : "儲存空間連線逾時。%s",
+ "Personal" : "個人",
+ "Admin" : "管理",
+ "APCu" : "APCu",
+ "Redis" : "Redis",
+ "Tips & tricks" : "使用祕訣",
+ "DB Error: \"%s\"" : "資料庫錯誤: %s",
+ "Offending command was: \"%s\"" : "有問題的指令: %s",
+ "Offending command was: \"%s\", name: %s, password: %s" : "有問題的指令: %s,名字: %s,密碼: %s",
+ "No app name specified" : "沒有指定應用程式名稱",
+ "App '%s' could not be installed!" : "應用程式 \"%s\" 無法被安裝",
+ "Sync clients" : "同步客戶端"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/lib/private/AllConfig.php b/lib/private/AllConfig.php
index 745bab367d3..58706e290fb 100644
--- a/lib/private/AllConfig.php
+++ b/lib/private/AllConfig.php
@@ -233,7 +233,7 @@ class AllConfig implements \OCP\IConfig {
->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($key)));
$qb->execute();
- $this->userCache[$userId][$appName][$key] = $value;
+ $this->userCache[$userId][$appName][$key] = (string)$value;
return;
}
}
@@ -258,7 +258,7 @@ class AllConfig implements \OCP\IConfig {
if (!isset($this->userCache[$userId][$appName])) {
$this->userCache[$userId][$appName] = array();
}
- $this->userCache[$userId][$appName][$key] = $value;
+ $this->userCache[$userId][$appName][$key] = (string)$value;
}
}
diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php
index 0e921ba1b7f..94addb2b785 100644
--- a/lib/private/App/AppManager.php
+++ b/lib/private/App/AppManager.php
@@ -204,7 +204,9 @@ class AppManager implements IAppManager {
}
/**
- * Check if an app is installed in the instance
+ * Check if an app is enabled in the instance
+ *
+ * Notice: This actually checks if the app is enabled and not only if it is installed.
*
* @param string $appId
* @return bool
@@ -287,6 +289,13 @@ class AppManager implements IAppManager {
}
unset($this->installedAppsCache[$appId]);
$this->appConfig->setValue($appId, 'enabled', 'no');
+
+ // run uninstall steps
+ $appData = $this->getAppInfo($appId);
+ if (!is_null($appData)) {
+ \OC_App::executeRepairSteps($appId, $appData['repair-steps']['uninstall']);
+ }
+
$this->dispatcher->dispatch(ManagerEvent::EVENT_APP_DISABLE, new ManagerEvent(
ManagerEvent::EVENT_APP_DISABLE, $appId
));
@@ -314,6 +323,7 @@ class AppManager implements IAppManager {
public function clearAppsCache() {
$settingsMemCache = $this->memCacheFactory->createDistributed('settings');
$settingsMemCache->clear('listApps');
+ $this->appInfos = [];
}
/**
@@ -349,7 +359,7 @@ class AppManager implements IAppManager {
*
* @param bool $path
* @param null $lang
- * @return array app info
+ * @return array|null app info
*/
public function getAppInfo(string $appId, bool $path = false, $lang = null) {
if ($path) {
@@ -380,10 +390,10 @@ class AppManager implements IAppManager {
return $data;
}
- public function getAppVersion(string $appId, bool $useCache = true) {
+ public function getAppVersion(string $appId, bool $useCache = true): string {
if(!$useCache || !isset($this->appVersions[$appId])) {
$appInfo = \OC::$server->getAppManager()->getAppInfo($appId);
- $this->appVersions[$appId] = ($appInfo !== null) ? $appInfo['version'] : '0';
+ $this->appVersions[$appId] = ($appInfo !== null && isset($appInfo['version'])) ? $appInfo['version'] : '0';
}
return $this->appVersions[$appId];
}
@@ -397,12 +407,14 @@ class AppManager implements IAppManager {
*
* @internal
*/
- public function getIncompatibleApps($version) {
+ public function getIncompatibleApps(string $version): array {
$apps = $this->getInstalledApps();
$incompatibleApps = array();
foreach ($apps as $appId) {
$info = $this->getAppInfo($appId);
- if (!\OC_App::isAppCompatible($version, $info)) {
+ if ($info === null) {
+ $incompatibleApps[] = ['id' => $appId];
+ } else if (!\OC_App::isAppCompatible($version, $info)) {
$incompatibleApps[] = $info;
}
}
@@ -411,6 +423,7 @@ class AppManager implements IAppManager {
/**
* @inheritdoc
+ * In case you change this method, also change \OC\App\CodeChecker\InfoChecker::isShipped()
*/
public function isShipped($appId) {
$this->loadShippedJson();
@@ -422,6 +435,10 @@ class AppManager implements IAppManager {
return in_array($appId, $alwaysEnabled, true);
}
+ /**
+ * In case you change this method, also change \OC\App\CodeChecker\InfoChecker::loadShippedJson()
+ * @throws \Exception
+ */
private function loadShippedJson() {
if ($this->shippedApps === null) {
$shippedJson = \OC::$SERVERROOT . '/core/shipped.json';
diff --git a/lib/private/App/AppStore/Fetcher/AppFetcher.php b/lib/private/App/AppStore/Fetcher/AppFetcher.php
index 63121c079bd..cf5839e4994 100644
--- a/lib/private/App/AppStore/Fetcher/AppFetcher.php
+++ b/lib/private/App/AppStore/Fetcher/AppFetcher.php
@@ -27,24 +27,32 @@
namespace OC\App\AppStore\Fetcher;
use OC\App\AppStore\Version\VersionParser;
+use OC\App\CompareVersion;
use OC\Files\AppData\Factory;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Http\Client\IClientService;
use OCP\IConfig;
use OCP\ILogger;
+use OCP\Util;
class AppFetcher extends Fetcher {
+
+ /** @var CompareVersion */
+ private $compareVersion;
+
/**
* @param Factory $appDataFactory
* @param IClientService $clientService
* @param ITimeFactory $timeFactory
* @param IConfig $config
+ * @param CompareVersion $compareVersion
* @param ILogger $logger
*/
public function __construct(Factory $appDataFactory,
IClientService $clientService,
ITimeFactory $timeFactory,
IConfig $config,
+ CompareVersion $compareVersion,
ILogger $logger) {
parent::__construct(
$appDataFactory,
@@ -56,6 +64,7 @@ class AppFetcher extends Fetcher {
$this->fileName = 'apps.json';
$this->setEndpoint();
+ $this->compareVersion = $compareVersion;
}
/**
@@ -70,8 +79,6 @@ class AppFetcher extends Fetcher {
/** @var mixed[] $response */
$response = parent::fetch($ETag, $content);
- $ncVersion = $this->getVersion();
- $ncMajorVersion = explode('.', $ncVersion)[0];
foreach($response['data'] as $dataKey => $app) {
$releases = [];
@@ -81,15 +88,20 @@ class AppFetcher extends Fetcher {
if($release['isNightly'] === false
&& strpos($release['version'], '-') === false) {
// Exclude all versions not compatible with the current version
- $versionParser = new VersionParser();
- $version = $versionParser->getVersion($release['rawPlatformVersionSpec']);
- if (
- // Major version is bigger or equals to the minimum version of the app
- version_compare($ncMajorVersion, $version->getMinimumVersion(), '>=')
- // Major version is smaller or equals to the maximum version of the app
- && version_compare($ncMajorVersion, $version->getMaximumVersion(), '<=')
- ) {
- $releases[] = $release;
+ try {
+ $versionParser = new VersionParser();
+ $version = $versionParser->getVersion($release['rawPlatformVersionSpec']);
+ $ncVersion = $this->getVersion();
+ $min = $version->getMinimumVersion();
+ $max = $version->getMaximumVersion();
+ $minFulfilled = $this->compareVersion->isCompatible($ncVersion, $min, '>=');
+ $maxFulfilled = $max !== '' &&
+ $this->compareVersion->isCompatible($ncVersion, $max, '<=');
+ if ($minFulfilled && $maxFulfilled) {
+ $releases[] = $release;
+ }
+ } catch (\InvalidArgumentException $e) {
+ $this->logger->logException($e, ['app' => 'appstoreFetcher', 'level' => ILogger::WARN]);
}
}
}
@@ -133,9 +145,11 @@ class AppFetcher extends Fetcher {
/**
* @param string $version
+ * @param string $fileName
*/
- public function setVersion($version) {
+ public function setVersion(string $version, string $fileName = 'apps.json') {
parent::setVersion($version);
+ $this->fileName = $fileName;
$this->setEndpoint();
}
}
diff --git a/lib/private/App/AppStore/Fetcher/Fetcher.php b/lib/private/App/AppStore/Fetcher/Fetcher.php
index 8bf9ca15349..973c4e55e9f 100644
--- a/lib/private/App/AppStore/Fetcher/Fetcher.php
+++ b/lib/private/App/AppStore/Fetcher/Fetcher.php
@@ -171,9 +171,10 @@ abstract class Fetcher {
$file->putContent(json_encode($responseJson));
return json_decode($file->getContent(), true)['data'];
} catch (ConnectException $e) {
- $this->logger->logException($e, ['app' => 'appstoreFetcher', 'level' => Util::INFO, 'message' => 'Could not connect to appstore']);
+ $this->logger->logException($e, ['app' => 'appstoreFetcher', 'level' => ILogger::INFO, 'message' => 'Could not connect to appstore']);
return [];
} catch (\Exception $e) {
+ $this->logger->logException($e, ['app' => 'appstoreFetcher', 'level' => ILogger::INFO]);
return [];
}
}
@@ -193,7 +194,7 @@ abstract class Fetcher {
* Set the current Nextcloud version
* @param string $version
*/
- public function setVersion($version) {
+ public function setVersion(string $version) {
$this->version = $version;
}
}
diff --git a/lib/private/App/CodeChecker/DeprecationCheck.php b/lib/private/App/CodeChecker/DeprecationCheck.php
index c337e71f27e..518ab1ec380 100644
--- a/lib/private/App/CodeChecker/DeprecationCheck.php
+++ b/lib/private/App/CodeChecker/DeprecationCheck.php
@@ -40,13 +40,13 @@ class DeprecationCheck extends AbstractCheck {
'OCP\Contacts' => '8.1.0',
'OCP\DB' => '8.1.0',
- 'OCP\IHelper' => '8.1.0',
'OCP\JSON' => '8.1.0',
'OCP\Response' => '8.1.0',
'OCP\AppFramework\IApi' => '8.0.0',
'OCP\User' => '13.0.0',
'OCP\BackgroundJob' => '14.0.0',
'OCP\App' => '14.0.0',
+ 'OCP\Files' => '14.0.0',
];
}
@@ -146,6 +146,8 @@ class DeprecationCheck extends AbstractCheck {
'OCP\IServerContainer::getDb' => '8.1.0',
'OCP\IServerContainer::getHTTPHelper' => '8.1.0',
+ 'OCP\Response::disableCaching' => '14.0.0',
+
'OCP\User::getUser' => '8.0.0',
'OCP\User::getUsers' => '8.1.0',
'OCP\User::getDisplayName' => '8.1.0',
@@ -173,6 +175,13 @@ class DeprecationCheck extends AbstractCheck {
'OCP\Util::mb_substr_replace' => '8.2.0',
'OCP\Util::sendMail' => '8.1.0',
'OCP\Util::writeLog' => '13.0.0',
+
+ 'OCP\Files::rmdirr' => '14.0.0',
+ 'OCP\Files::getMimeType' => '14.0.0',
+ 'OCP\Files::searchByMime' => '14.0.0',
+ 'OCP\Files::streamCopy' => '14.0.0',
+ 'OCP\Files::buildNotExistingFileName' => '14.0.0',
+ 'OCP\Files::getStorage' => '14.0.0',
];
}
}
diff --git a/lib/private/App/CodeChecker/InfoChecker.php b/lib/private/App/CodeChecker/InfoChecker.php
index e8791bd7037..f5de6d376d8 100644
--- a/lib/private/App/CodeChecker/InfoChecker.php
+++ b/lib/private/App/CodeChecker/InfoChecker.php
@@ -23,121 +23,88 @@
namespace OC\App\CodeChecker;
-use OC\App\InfoParser;
use OC\Hooks\BasicEmitter;
+use OCP\App\AppPathNotFoundException;
+use OCP\App\IAppManager;
class InfoChecker extends BasicEmitter {
- /** @var InfoParser */
- private $infoParser;
+ /** @var string[] */
+ private $shippedApps;
- private $mandatoryFields = [
- 'author',
- 'description',
- 'dependencies',
- 'id',
- 'licence',
- 'name',
- 'version',
- ];
- private $optionalFields = [
- 'bugs',
- 'category',
- 'default_enable',
- 'documentation',
- 'namespace',
- 'ocsid',
- 'public',
- 'remote',
- 'repository',
- 'types',
- 'website',
- ];
- private $deprecatedFields = [
- 'info',
- 'require',
- 'requiremax',
- 'requiremin',
- 'shipped',
- 'standalone',
- ];
-
- public function __construct(InfoParser $infoParser) {
- $this->infoParser = $infoParser;
- }
+ /** @var string[] */
+ private $alwaysEnabled;
/**
* @param string $appId
* @return array
+ * @throws \RuntimeException
*/
- public function analyse($appId) {
+ public function analyse($appId): array {
$appPath = \OC_App::getAppPath($appId);
if ($appPath === false) {
throw new \RuntimeException("No app with given id <$appId> known.");
}
- $errors = [];
-
- $info = $this->infoParser->parse($appPath . '/appinfo/info.xml');
-
- if (!isset($info['dependencies']['nextcloud']['@attributes']['min-version'])) {
- $errors[] = [
- 'type' => 'missingRequirement',
- 'field' => 'min',
- ];
- $this->emit('InfoChecker', 'missingRequirement', ['min']);
- }
-
- if (!isset($info['dependencies']['nextcloud']['@attributes']['max-version'])) {
- $errors[] = [
- 'type' => 'missingRequirement',
- 'field' => 'max',
- ];
- $this->emit('InfoChecker', 'missingRequirement', ['max']);
- }
-
- foreach ($info as $key => $value) {
- if(is_array($value)) {
- $value = json_encode($value);
- }
- if (in_array($key, $this->mandatoryFields)) {
- $this->emit('InfoChecker', 'mandatoryFieldFound', [$key, $value]);
- continue;
- }
+ $xml = new \DOMDocument();
+ $xml->load($appPath . '/appinfo/info.xml');
- if (in_array($key, $this->optionalFields)) {
- $this->emit('InfoChecker', 'optionalFieldFound', [$key, $value]);
- continue;
+ $schema = \OC::$SERVERROOT . '/resources/app-info.xsd';
+ try {
+ if ($this->isShipped($appId)) {
+ // Shipped apps are allowed to have the public and default_enabled tags
+ $schema = \OC::$SERVERROOT . '/resources/app-info-shipped.xsd';
}
-
- if (in_array($key, $this->deprecatedFields)) {
- // skip empty arrays - empty arrays for remote and public are always added
- if($value === '[]' && in_array($key, ['public', 'remote', 'info'])) {
- continue;
- }
- $this->emit('InfoChecker', 'deprecatedFieldFound', [$key, $value]);
- continue;
- }
-
- $this->emit('InfoChecker', 'unusedFieldFound', [$key, $value]);
+ } catch (\Exception $e) {
+ // Assume it is not shipped
}
- foreach ($this->mandatoryFields as $key) {
- if(!isset($info[$key])) {
- $this->emit('InfoChecker', 'mandatoryFieldMissing', [$key]);
+ $errors = [];
+ if (!$xml->schemaValidate($schema)) {
+ foreach (libxml_get_errors() as $error) {
$errors[] = [
- 'type' => 'mandatoryFieldMissing',
- 'field' => $key,
+ 'type' => 'parseError',
+ 'field' => $error->message,
];
+ $this->emit('InfoChecker', 'parseError', [$error->message]);
}
}
- $versionFile = $appPath . '/appinfo/version';
- if (is_file($versionFile)) {
- $version = trim(file_get_contents($versionFile));
- $this->emit('InfoChecker', 'migrateVersion', [$version]);
- }
-
return $errors;
}
+
+ /**
+ * This is a copy of \OC\App\AppManager::isShipped(), keep both in sync.
+ * This method is copied, so the code checker works even when Nextcloud is
+ * not installed yet. The AppManager requires a database connection, which
+ * fails in that case.
+ *
+ * @param string $appId
+ * @return bool
+ * @throws \Exception
+ */
+ protected function isShipped(string $appId): bool {
+ $this->loadShippedJson();
+ return \in_array($appId, $this->shippedApps, true);
+ }
+
+ /**
+ * This is a copy of \OC\App\AppManager::loadShippedJson(), keep both in sync
+ * This method is copied, so the code checker works even when Nextcloud is
+ * not installed yet. The AppManager requires a database connection, which
+ * fails in that case.
+ *
+ * @throws \Exception
+ */
+ protected function loadShippedJson() {
+ if ($this->shippedApps === null) {
+ $shippedJson = \OC::$SERVERROOT . '/core/shipped.json';
+ if (!file_exists($shippedJson)) {
+ throw new \Exception("File not found: $shippedJson");
+ }
+ $content = json_decode(file_get_contents($shippedJson), true);
+ $this->shippedApps = $content['shippedApps'];
+ $this->alwaysEnabled = $content['alwaysEnabled'];
+ }
+ }
}
diff --git a/lib/private/App/CompareVersion.php b/lib/private/App/CompareVersion.php
new file mode 100644
index 00000000000..ee25a8b9460
--- /dev/null
+++ b/lib/private/App/CompareVersion.php
@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @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\App;
+
+use InvalidArgumentException;
+
+class CompareVersion {
+
+ const REGEX_MAJOR = '/^\d+$/';
+ const REGEX_MAJOR_MINOR = '/^\d+.\d+$/';
+ const REGEX_MAJOR_MINOR_PATCH = '/^\d+.\d+.\d+$/';
+ const REGEX_SERVER = '/^\d+.\d+.\d+(.\d+)?$/';
+
+ /**
+ * Checks if the given server version fulfills the given (app) version requirements.
+ *
+ * Version requirements can be 'major.minor.patch', 'major.minor' or just 'major',
+ * so '13.0.1', '13.0' and '13' are valid.
+ *
+ * @param string $actual version as major.minor.patch notation
+ * @param string $required version where major is requried and minor and patch are optional
+ * @param string $comparator passed to `version_compare`
+ * @return bool whether the requirement is fulfilled
+ * @throws InvalidArgumentException if versions specified in an invalid format
+ */
+ public function isCompatible(string $actual, string $required,
+ string $comparator = '>='): bool {
+
+ if (!preg_match(self::REGEX_SERVER, $actual)) {
+ throw new InvalidArgumentException('server version is invalid');
+ }
+
+ if (preg_match(self::REGEX_MAJOR, $required) === 1) {
+ return $this->compareMajor($actual, $required, $comparator);
+ } else if (preg_match(self::REGEX_MAJOR_MINOR, $required) === 1) {
+ return $this->compareMajorMinor($actual, $required, $comparator);
+ } else if (preg_match(self::REGEX_MAJOR_MINOR_PATCH, $required) === 1) {
+ return $this->compareMajorMinorPatch($actual, $required, $comparator);
+ } else {
+ throw new InvalidArgumentException('required version is invalid');
+ }
+ }
+
+ private function compareMajor(string $actual, string $required,
+ string $comparator) {
+ $actualMajor = explode('.', $actual)[0];
+ $requiredMajor = explode('.', $required)[0];
+
+ return version_compare($actualMajor, $requiredMajor, $comparator);
+ }
+
+ private function compareMajorMinor(string $actual, string $required,
+ string $comparator) {
+ $actualMajor = explode('.', $actual)[0];
+ $actualMinor = explode('.', $actual)[1];
+ $requiredMajor = explode('.', $required)[0];
+ $requiredMinor = explode('.', $required)[1];
+
+ return version_compare("$actualMajor.$actualMinor",
+ "$requiredMajor.$requiredMinor", $comparator);
+ }
+
+ private function compareMajorMinorPatch($actual, $required, $comparator) {
+ $actualMajor = explode('.', $actual)[0];
+ $actualMinor = explode('.', $actual)[1];
+ $actualPatch = explode('.', $actual)[2];
+ $requiredMajor = explode('.', $required)[0];
+ $requiredMinor = explode('.', $required)[1];
+ $requiredPatch = explode('.', $required)[2];
+
+ return version_compare("$actualMajor.$actualMinor.$actualPatch",
+ "$requiredMajor.$requiredMinor.$requiredPatch", $comparator);
+ }
+
+}
diff --git a/lib/private/App/DependencyAnalyzer.php b/lib/private/App/DependencyAnalyzer.php
index 4193ee5083f..e8da5a0b63a 100644
--- a/lib/private/App/DependencyAnalyzer.php
+++ b/lib/private/App/DependencyAnalyzer.php
@@ -140,19 +140,19 @@ class DependencyAnalyzer {
if (isset($dependencies['php']['@attributes']['min-version'])) {
$minVersion = $dependencies['php']['@attributes']['min-version'];
if ($this->compareSmaller($this->platform->getPhpVersion(), $minVersion)) {
- $missing[] = (string)$this->l->t('PHP %s or higher is required.', $minVersion);
+ $missing[] = (string)$this->l->t('PHP %s or higher is required.', [$minVersion]);
}
}
if (isset($dependencies['php']['@attributes']['max-version'])) {
$maxVersion = $dependencies['php']['@attributes']['max-version'];
if ($this->compareBigger($this->platform->getPhpVersion(), $maxVersion)) {
- $missing[] = (string)$this->l->t('PHP with a version lower than %s is required.', $maxVersion);
+ $missing[] = (string)$this->l->t('PHP with a version lower than %s is required.', [$maxVersion]);
}
}
if (isset($dependencies['php']['@attributes']['min-int-size'])) {
$intSize = $dependencies['php']['@attributes']['min-int-size'];
if ($intSize > $this->platform->getIntSize()*8) {
- $missing[] = (string)$this->l->t('%sbit or higher PHP required.', $intSize);
+ $missing[] = (string)$this->l->t('%sbit or higher PHP required.', [$intSize]);
}
}
return $missing;
@@ -209,7 +209,7 @@ class DependencyAnalyzer {
}
$commandName = $this->getValue($command);
if (!$this->platform->isCommandKnown($commandName)) {
- $missing[] = (string)$this->l->t('The command line tool %s could not be found', $commandName);
+ $missing[] = (string)$this->l->t('The command line tool %s could not be found', [$commandName]);
}
}
return $missing;
@@ -236,7 +236,7 @@ class DependencyAnalyzer {
$libName = $this->getValue($lib);
$libVersion = $this->platform->getLibraryVersion($libName);
if (is_null($libVersion)) {
- $missing[] = (string)$this->l->t('The library %s is not available.', $libName);
+ $missing[] = (string)$this->l->t('The library %s is not available.', [$libName]);
continue;
}
diff --git a/lib/private/App/Platform.php b/lib/private/App/Platform.php
index fe4d7ff48f7..efe01d291d7 100644
--- a/lib/private/App/Platform.php
+++ b/lib/private/App/Platform.php
@@ -61,7 +61,7 @@ class Platform {
*/
public function getOcVersion() {
$v = \OCP\Util::getVersion();
- return join('.', $v);
+ return implode('.', $v);
}
/**
diff --git a/lib/private/AppConfig.php b/lib/private/AppConfig.php
index 59a340cb491..6d24ca5fa8e 100644
--- a/lib/private/AppConfig.php
+++ b/lib/private/AppConfig.php
@@ -288,9 +288,11 @@ class AppConfig implements IAppConfig {
public function getFilteredValues($app) {
$values = $this->getValues($app, false);
- foreach ($this->sensitiveValues[$app] as $sensitiveKey) {
- if (isset($values[$sensitiveKey])) {
- $values[$sensitiveKey] = IConfig::SENSITIVE_VALUE;
+ if (isset($this->sensitiveValues[$app])) {
+ foreach ($this->sensitiveValues[$app] as $sensitiveKey) {
+ if (isset($values[$sensitiveKey])) {
+ $values[$sensitiveKey] = IConfig::SENSITIVE_VALUE;
+ }
}
}
diff --git a/lib/private/AppFramework/App.php b/lib/private/AppFramework/App.php
index 6e8c3736fdb..25708245e26 100644
--- a/lib/private/AppFramework/App.php
+++ b/lib/private/AppFramework/App.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -55,7 +56,7 @@ class App {
* the transformed app id, defaults to OCA\
* @return string the starting namespace for the app
*/
- public static function buildAppNamespace($appId, $topNamespace='OCA\\') {
+ public static function buildAppNamespace(string $appId, string $topNamespace='OCA\\'): string {
// Hit the cache!
if (isset(self::$nameSpaceCache[$appId])) {
return $topNamespace . self::$nameSpaceCache[$appId];
@@ -81,7 +82,7 @@ class App {
* @param DIContainer $container an instance of a pimple container.
* @param array $urlParams list of URL parameters (optional)
*/
- public static function main($controllerName, $methodName, DIContainer $container, array $urlParams = null) {
+ public static function main(string $controllerName, string $methodName, DIContainer $container, array $urlParams = null) {
if (!is_null($urlParams)) {
$container[IRequest::class]->setUrlParameters($urlParams);
} else if (isset($container['urlParams']) && !is_null($container['urlParams'])) {
@@ -171,7 +172,7 @@ class App {
* @param array $urlParams an array with variables extracted from the routes
* @param DIContainer $container an instance of a pimple container.
*/
- public static function part($controllerName, $methodName, array $urlParams,
+ public static function part(string $controllerName, string $methodName, array $urlParams,
DIContainer $container){
$container['urlParams'] = $urlParams;
diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php
index 5fe925c2998..8803ef8c47d 100644
--- a/lib/private/AppFramework/DependencyInjection/DIContainer.php
+++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php
@@ -46,6 +46,7 @@ use OC\AppFramework\Middleware\Security\RateLimitingMiddleware;
use OC\AppFramework\Middleware\Security\SecurityMiddleware;
use OC\AppFramework\Middleware\SessionMiddleware;
use OC\AppFramework\Utility\SimpleContainer;
+use OC\Collaboration\Collaborators\SearchResult;
use OC\Core\Middleware\TwoFactorMiddleware;
use OC\RichObjectStrings\Validator;
use OC\ServerContainer;
@@ -53,15 +54,17 @@ use OCP\AppFramework\Http\IOutput;
use OCP\AppFramework\IAppContainer;
use OCP\AppFramework\QueryException;
use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\Files\Folder;
use OCP\Files\IAppData;
use OCP\GlobalScale\IConfig;
use OCP\IL10N;
+use OCP\ILogger;
use OCP\IRequest;
use OCP\IServerContainer;
+use OCP\ISession;
use OCP\IUserSession;
use OCP\RichObjectStrings\IValidator;
-use OCP\Util;
use OCP\Encryption\IManager;
use OCA\WorkflowEngine\Manager;
@@ -143,6 +146,8 @@ class DIContainer extends SimpleContainer implements IAppContainer {
return $c;
});
+ $this->registerAlias(ISearchResult::class, SearchResult::class);
+
// commonly used attributes
$this->registerService('UserId', function ($c) {
return $c->query(IUserSession::class)->getSession()->get('user_id');
@@ -152,10 +157,6 @@ class DIContainer extends SimpleContainer implements IAppContainer {
return $c->query('ServerContainer')->getWebRoot();
});
- $this->registerService('fromMailAddress', function() {
- return Util::getDefaultEmailAddress('no-reply');
- });
-
$this->registerService('OC_Defaults', function ($c) {
return $c->getServer()->getThemingDefaults();
});
@@ -223,7 +224,8 @@ class DIContainer extends SimpleContainer implements IAppContainer {
$server->getContentSecurityPolicyManager(),
$server->getCsrfTokenManager(),
$server->getContentSecurityPolicyNonceManager(),
- $server->getAppManager()
+ $server->getAppManager(),
+ $server->getL10N('lib')
);
});
@@ -303,7 +305,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
});
$middleWares = &$this->middleWares;
- $this->registerService('MiddlewareDispatcher', function($c) use (&$middleWares) {
+ $this->registerService('MiddlewareDispatcher', function(SimpleContainer $c) use (&$middleWares) {
$dispatcher = new MiddlewareDispatcher();
$dispatcher->registerMiddleware($c[OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware::class]);
$dispatcher->registerMiddleware($c['CORSMiddleware']);
@@ -313,6 +315,11 @@ class DIContainer extends SimpleContainer implements IAppContainer {
$dispatcher->registerMiddleware($c['TwoFactorMiddleware']);
$dispatcher->registerMiddleware($c['BruteForceMiddleware']);
$dispatcher->registerMiddleware($c['RateLimitingMiddleware']);
+ $dispatcher->registerMiddleware(new OC\AppFramework\Middleware\PublicShare\PublicShareMiddleware(
+ $c['Request'],
+ $c->query(ISession::class),
+ $c->query(\OCP\IConfig::class)
+ ));
foreach($middleWares as $middleWare) {
$dispatcher->registerMiddleware($c[$middleWare]);
@@ -378,19 +385,19 @@ class DIContainer extends SimpleContainer implements IAppContainer {
public function log($message, $level) {
switch($level){
case 'debug':
- $level = \OCP\Util::DEBUG;
+ $level = ILogger::DEBUG;
break;
case 'info':
- $level = \OCP\Util::INFO;
+ $level = ILogger::INFO;
break;
case 'warn':
- $level = \OCP\Util::WARN;
+ $level = ILogger::WARN;
break;
case 'fatal':
- $level = \OCP\Util::FATAL;
+ $level = ILogger::FATAL;
break;
default:
- $level = \OCP\Util::ERROR;
+ $level = ILogger::ERROR;
break;
}
\OCP\Util::writeLog($this->getAppName(), $message, $level);
diff --git a/lib/private/AppFramework/Http/Dispatcher.php b/lib/private/AppFramework/Http/Dispatcher.php
index ecf8462ebb6..7b9ad015de6 100644
--- a/lib/private/AppFramework/Http/Dispatcher.php
+++ b/lib/private/AppFramework/Http/Dispatcher.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -44,9 +45,16 @@ use OCP\IRequest;
*/
class Dispatcher {
+ /** @var MiddlewareDispatcher */
private $middlewareDispatcher;
+
+ /** @var Http */
private $protocol;
+
+ /** @var ControllerMethodReflector */
private $reflector;
+
+ /** @var IRequest */
private $request;
/**
@@ -78,8 +86,8 @@ class Dispatcher {
* the response output
* @throws \Exception
*/
- public function dispatch(Controller $controller, $methodName) {
- $out = array(null, array(), null);
+ public function dispatch(Controller $controller, string $methodName): array {
+ $out = [null, [], null];
try {
// prefill reflector with everything thats needed for the
@@ -97,9 +105,6 @@ class Dispatcher {
} catch(\Exception $exception){
$response = $this->middlewareDispatcher->afterException(
$controller, $methodName, $exception);
- if (is_null($response)) {
- throw $exception;
- }
}
$response = $this->middlewareDispatcher->afterController(
@@ -126,11 +131,11 @@ class Dispatcher {
* @param string $methodName the method on the controller that should be executed
* @return Response
*/
- private function executeController($controller, $methodName) {
- $arguments = array();
+ private function executeController(Controller $controller, string $methodName): Response {
+ $arguments = [];
// valid types that will be casted
- $types = array('int', 'integer', 'bool', 'boolean', 'float');
+ $types = ['int', 'integer', 'bool', 'boolean', 'float'];
foreach($this->reflector->getParameters() as $param => $default) {
@@ -151,14 +156,14 @@ class Dispatcher {
) {
$value = false;
- } elseif($value !== null && in_array($type, $types)) {
+ } elseif($value !== null && \in_array($type, $types, true)) {
settype($value, $type);
}
$arguments[] = $value;
}
- $response = call_user_func_array(array($controller, $methodName), $arguments);
+ $response = \call_user_func_array([$controller, $methodName], $arguments);
// format response
if($response instanceof DataResponse || !($response instanceof Response)) {
diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php
index 975c4255d5a..86ba884141f 100644
--- a/lib/private/AppFramework/Http/Request.php
+++ b/lib/private/AppFramework/Http/Request.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -87,8 +88,8 @@ class Request implements \ArrayAccess, \Countable, IRequest {
protected $inputStream;
protected $content;
- protected $items = array();
- protected $allowedKeys = array(
+ protected $items = [];
+ protected $allowedKeys = [
'get',
'post',
'files',
@@ -99,7 +100,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
'parameters',
'method',
'requesttoken',
- );
+ ];
/** @var ISecureRandom */
protected $secureRandom;
/** @var IConfig */
@@ -131,13 +132,13 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @param string $stream
* @see http://www.php.net/manual/en/reserved.variables.php
*/
- public function __construct(array $vars=array(),
+ public function __construct(array $vars= [],
ISecureRandom $secureRandom = null,
IConfig $config,
CsrfTokenManager $csrfTokenManager = null,
- $stream = 'php://input') {
+ string $stream = 'php://input') {
$this->inputStream = $stream;
- $this->items['params'] = array();
+ $this->items['params'] = [];
$this->secureRandom = $secureRandom;
$this->config = $config;
$this->csrfTokenManager = $csrfTokenManager;
@@ -149,7 +150,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
foreach($this->allowedKeys as $name) {
$this->items[$name] = isset($vars[$name])
? $vars[$name]
- : array();
+ : [];
}
$this->items['parameters'] = array_merge(
@@ -175,8 +176,8 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* Countable method
* @return int
*/
- public function count() {
- return count(array_keys($this->items['parameters']));
+ public function count(): int {
+ return \count($this->items['parameters']);
}
/**
@@ -199,13 +200,15 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @param string $offset The key to lookup
* @return boolean
*/
- public function offsetExists($offset) {
+ public function offsetExists($offset): bool {
return isset($this->items['parameters'][$offset]);
}
/**
- * @see offsetExists
- */
+ * @see offsetExists
+ * @param string $offset
+ * @return mixed
+ */
public function offsetGet($offset) {
return isset($this->items['parameters'][$offset])
? $this->items['parameters'][$offset]
@@ -213,15 +216,18 @@ class Request implements \ArrayAccess, \Countable, IRequest {
}
/**
- * @see offsetExists
- */
+ * @see offsetExists
+ * @param string $offset
+ * @param mixed $value
+ */
public function offsetSet($offset, $value) {
throw new \RuntimeException('You cannot change the contents of the request object');
}
/**
- * @see offsetExists
- */
+ * @see offsetExists
+ * @param string $offset
+ */
public function offsetUnset($offset) {
throw new \RuntimeException('You cannot change the contents of the request object');
}
@@ -284,7 +290,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @return bool
*/
public function __isset($name) {
- if (in_array($name, $this->allowedKeys, true)) {
+ if (\in_array($name, $this->allowedKeys, true)) {
return true;
}
return isset($this->items['parameters'][$name]);
@@ -305,9 +311,9 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @param string $name
* @return string
*/
- public function getHeader($name) {
+ public function getHeader(string $name): string {
- $name = strtoupper(str_replace(array('-'),array('_'),$name));
+ $name = strtoupper(str_replace('-', '_',$name));
if (isset($this->server['HTTP_' . $name])) {
return $this->server['HTTP_' . $name];
}
@@ -340,7 +346,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @param mixed $default If the key is not found, this value will be returned
* @return mixed the content of the array
*/
- public function getParam($key, $default = null) {
+ public function getParam(string $key, $default = null) {
return isset($this->parameters[$key])
? $this->parameters[$key]
: $default;
@@ -351,7 +357,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* (as GET or POST) or throuh the URL by the route
* @return array the array with all parameters
*/
- public function getParams() {
+ public function getParams(): array {
return $this->parameters;
}
@@ -359,7 +365,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* Returns the method of the request
* @return string the method of the request (POST, GET, etc)
*/
- public function getMethod() {
+ public function getMethod(): string {
return $this->method;
}
@@ -368,7 +374,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @param string $key the key that will be taken from the $_FILES array
* @return array the file in the $_FILES element
*/
- public function getUploadedFile($key) {
+ public function getUploadedFile(string $key) {
return isset($this->files[$key]) ? $this->files[$key] : null;
}
@@ -377,7 +383,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @param string $key the key that will be taken from the $_ENV array
* @return array the value in the $_ENV element
*/
- public function getEnv($key) {
+ public function getEnv(string $key) {
return isset($this->env[$key]) ? $this->env[$key] : null;
}
@@ -386,7 +392,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @param string $key the key that will be taken from the $_COOKIE array
* @return string the value in the $_COOKIE element
*/
- public function getCookie($key) {
+ public function getCookie(string $key) {
return isset($this->cookies[$key]) ? $this->cookies[$key] : null;
}
@@ -435,7 +441,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
// 'application/json' must be decoded manually.
if (strpos($this->getHeader('Content-Type'), 'application/json') !== false) {
$params = json_decode(file_get_contents($this->inputStream), true);
- if($params !== null && count($params) > 0) {
+ if($params !== null && \count($params) > 0) {
$this->items['params'] = $params;
if($this->method === 'POST') {
$this->items['post'] = $params;
@@ -449,12 +455,12 @@ class Request implements \ArrayAccess, \Countable, IRequest {
&& strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) {
parse_str(file_get_contents($this->inputStream), $params);
- if(is_array($params)) {
+ if(\is_array($params)) {
$this->items['params'] = $params;
}
}
- if (is_array($params)) {
+ if (\is_array($params)) {
$this->items['parameters'] = array_merge($this->items['parameters'], $params);
}
$this->contentDecoded = true;
@@ -465,7 +471,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* Checks if the CSRF check was correct
* @return bool true if CSRF check passed
*/
- public function passesCSRFCheck() {
+ public function passesCSRFCheck(): bool {
if($this->csrfTokenManager === null) {
return false;
}
@@ -494,7 +500,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
*
* @return bool
*/
- private function cookieCheckRequired() {
+ private function cookieCheckRequired(): bool {
if ($this->getHeader('OCS-APIREQUEST')) {
return false;
}
@@ -510,7 +516,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
*
* @return array
*/
- public function getCookieParams() {
+ public function getCookieParams(): array {
return session_get_cookie_params();
}
@@ -520,7 +526,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @param string $name
* @return string
*/
- protected function getProtectedCookieName($name) {
+ protected function getProtectedCookieName(string $name): string {
$cookieParams = $this->getCookieParams();
$prefix = '';
if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
@@ -537,7 +543,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @return bool
* @since 9.1.0
*/
- public function passesStrictCookieCheck() {
+ public function passesStrictCookieCheck(): bool {
if(!$this->cookieCheckRequired()) {
return true;
}
@@ -557,7 +563,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @return bool
* @since 9.1.0
*/
- public function passesLaxCookieCheck() {
+ public function passesLaxCookieCheck(): bool {
if(!$this->cookieCheckRequired()) {
return true;
}
@@ -575,7 +581,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* If `mod_unique_id` is installed this value will be taken.
* @return string
*/
- public function getId() {
+ public function getId(): string {
if(isset($this->server['UNIQUE_ID'])) {
return $this->server['UNIQUE_ID'];
}
@@ -595,11 +601,11 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* Do always use this instead of $_SERVER['REMOTE_ADDR']
* @return string IP address
*/
- public function getRemoteAddress() {
+ public function getRemoteAddress(): string {
$remoteAddress = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '';
$trustedProxies = $this->config->getSystemValue('trusted_proxies', []);
- if(is_array($trustedProxies) && in_array($remoteAddress, $trustedProxies)) {
+ if(\is_array($trustedProxies) && \in_array($remoteAddress, $trustedProxies)) {
$forwardedForHeaders = $this->config->getSystemValue('forwarded_for_headers', [
'HTTP_X_FORWARDED_FOR'
// only have one default, so we cannot ship an insecure product out of the box
@@ -625,7 +631,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @param string $type
* @return bool
*/
- private function isOverwriteCondition($type = '') {
+ private function isOverwriteCondition(string $type = ''): bool {
$regex = '/' . $this->config->getSystemValue('overwritecondaddr', '') . '/';
$remoteAddr = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '';
return $regex === '//' || preg_match($regex, $remoteAddr) === 1
@@ -637,7 +643,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* and load balancers
* @return string Server protocol (http or https)
*/
- public function getServerProtocol() {
+ public function getServerProtocol(): string {
if($this->config->getSystemValue('overwriteprotocol') !== ''
&& $this->isOverwriteCondition('protocol')) {
return $this->config->getSystemValue('overwriteprotocol');
@@ -671,8 +677,12 @@ class Request implements \ArrayAccess, \Countable, IRequest {
*
* @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0.
*/
- public function getHttpProtocol() {
- $claimedProtocol = strtoupper($this->server['SERVER_PROTOCOL']);
+ public function getHttpProtocol(): string {
+ $claimedProtocol = $this->server['SERVER_PROTOCOL'];
+
+ if (\is_string($claimedProtocol)) {
+ $claimedProtocol = strtoupper($claimedProtocol);
+ }
$validProtocols = [
'HTTP/1.0',
@@ -680,7 +690,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
'HTTP/2',
];
- if(in_array($claimedProtocol, $validProtocols, true)) {
+ if(\in_array($claimedProtocol, $validProtocols, true)) {
return $claimedProtocol;
}
@@ -692,10 +702,10 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* reverse proxies
* @return string
*/
- public function getRequestUri() {
+ public function getRequestUri(): string {
$uri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : '';
if($this->config->getSystemValue('overwritewebroot') !== '' && $this->isOverwriteCondition()) {
- $uri = $this->getScriptName() . substr($uri, strlen($this->server['SCRIPT_NAME']));
+ $uri = $this->getScriptName() . substr($uri, \strlen($this->server['SCRIPT_NAME']));
}
return $uri;
}
@@ -705,7 +715,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @throws \Exception
* @return string Path info
*/
- public function getRawPathInfo() {
+ public function getRawPathInfo(): string {
$requestUri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : '';
// remove too many leading slashes - can be caused by reverse proxy configuration
if (strpos($requestUri, '/') === 0) {
@@ -727,16 +737,20 @@ class Request implements \ArrayAccess, \Countable, IRequest {
list($path, $name) = \Sabre\Uri\split($scriptName);
if (!empty($path)) {
if($path === $pathInfo || strpos($pathInfo, $path.'/') === 0) {
- $pathInfo = substr($pathInfo, strlen($path));
+ $pathInfo = substr($pathInfo, \strlen($path));
} else {
throw new \Exception("The requested uri($requestUri) cannot be processed by the script '$scriptName')");
}
}
+ if ($name === null) {
+ $name = '';
+ }
+
if (strpos($pathInfo, '/'.$name) === 0) {
- $pathInfo = substr($pathInfo, strlen($name) + 1);
+ $pathInfo = substr($pathInfo, \strlen($name) + 1);
}
- if (strpos($pathInfo, $name) === 0) {
- $pathInfo = substr($pathInfo, strlen($name));
+ if ($name !== '' && strpos($pathInfo, $name) === 0) {
+ $pathInfo = substr($pathInfo, \strlen($name));
}
if($pathInfo === false || $pathInfo === '/'){
return '';
@@ -770,13 +784,13 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* reverse proxies
* @return string the script name
*/
- public function getScriptName() {
+ public function getScriptName(): string {
$name = $this->server['SCRIPT_NAME'];
$overwriteWebRoot = $this->config->getSystemValue('overwritewebroot');
if ($overwriteWebRoot !== '' && $this->isOverwriteCondition()) {
// FIXME: This code is untestable due to __DIR__, also that hardcoded path is really dangerous
- $serverRoot = str_replace('\\', '/', substr(__DIR__, 0, -strlen('lib/private/appframework/http/')));
- $suburi = str_replace('\\', '/', substr(realpath($this->server['SCRIPT_FILENAME']), strlen($serverRoot)));
+ $serverRoot = str_replace('\\', '/', substr(__DIR__, 0, -\strlen('lib/private/appframework/http/')));
+ $suburi = str_replace('\\', '/', substr(realpath($this->server['SCRIPT_FILENAME']), \strlen($serverRoot)));
$name = '/' . ltrim($overwriteWebRoot . $suburi, '/');
}
return $name;
@@ -787,7 +801,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* @param array $agent array of agent names
* @return bool true if at least one of the given agent matches, false otherwise
*/
- public function isUserAgent(array $agent) {
+ public function isUserAgent(array $agent): bool {
if (!isset($this->server['HTTP_USER_AGENT'])) {
return false;
}
@@ -804,7 +818,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* whether it is a trusted domain
* @return string Server host
*/
- public function getInsecureServerHost() {
+ public function getInsecureServerHost(): string {
$host = 'localhost';
if (isset($this->server['HTTP_X_FORWARDED_HOST'])) {
if (strpos($this->server['HTTP_X_FORWARDED_HOST'], ',') !== false) {
@@ -829,7 +843,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* trusted domain if the host isn't in the trusted list
* @return string Server host
*/
- public function getServerHost() {
+ public function getServerHost(): string {
// overwritehost is always trusted
$host = $this->getOverwriteHost();
if ($host !== null) {
diff --git a/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php b/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php
index 60d2ae8b5c9..e1262b6c712 100644
--- a/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php
+++ b/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -30,7 +31,7 @@ namespace OC\AppFramework\Middleware;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Response;
-use OCP\AppFramework\MiddleWare;
+use OCP\AppFramework\Middleware;
/**
* This class is used to store and run all the middleware in correct order
@@ -53,7 +54,7 @@ class MiddlewareDispatcher {
* Constructor
*/
public function __construct(){
- $this->middlewares = array();
+ $this->middlewares = [];
$this->middlewareCounter = 0;
}
@@ -71,7 +72,7 @@ class MiddlewareDispatcher {
* returns an array with all middleware elements
* @return array the middlewares
*/
- public function getMiddlewares(){
+ public function getMiddlewares(): array {
return $this->middlewares;
}
@@ -84,10 +85,10 @@ class MiddlewareDispatcher {
* @param string $methodName the name of the method that will be called on
* the controller
*/
- public function beforeController(Controller $controller, $methodName){
+ public function beforeController(Controller $controller, string $methodName){
// we need to count so that we know which middlewares we have to ask in
// case there is an exception
- $middlewareCount = count($this->middlewares);
+ $middlewareCount = \count($this->middlewares);
for($i = 0; $i < $middlewareCount; $i++){
$this->middlewareCounter++;
$middleware = $this->middlewares[$i];
@@ -111,7 +112,7 @@ class MiddlewareDispatcher {
* exception
* @throws \Exception the passed in exception if it can't handle it
*/
- public function afterException(Controller $controller, $methodName, \Exception $exception){
+ public function afterException(Controller $controller, string $methodName, \Exception $exception): Response {
for($i=$this->middlewareCounter-1; $i>=0; $i--){
$middleware = $this->middlewares[$i];
try {
@@ -134,8 +135,8 @@ class MiddlewareDispatcher {
* @param Response $response the generated response from the controller
* @return Response a Response object
*/
- public function afterController(Controller $controller, $methodName, Response $response){
- for($i=count($this->middlewares)-1; $i>=0; $i--){
+ public function afterController(Controller $controller, string $methodName, Response $response): Response {
+ for($i= \count($this->middlewares)-1; $i>=0; $i--){
$middleware = $this->middlewares[$i];
$response = $middleware->afterController($controller, $methodName, $response);
}
@@ -153,8 +154,8 @@ class MiddlewareDispatcher {
* @param string $output the generated output from a response
* @return string the output that should be printed
*/
- public function beforeOutput(Controller $controller, $methodName, $output){
- for($i=count($this->middlewares)-1; $i>=0; $i--){
+ public function beforeOutput(Controller $controller, string $methodName, string $output): string {
+ for($i= \count($this->middlewares)-1; $i>=0; $i--){
$middleware = $this->middlewares[$i];
$output = $middleware->beforeOutput($controller, $methodName, $output);
}
diff --git a/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php b/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php
new file mode 100644
index 00000000000..27e57fe9505
--- /dev/null
+++ b/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace OC\AppFramework\Middleware\PublicShare\Exceptions;
+
+class NeedAuthenticationException extends \Exception {
+
+}
diff --git a/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php b/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php
new file mode 100644
index 00000000000..05783b21900
--- /dev/null
+++ b/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php
@@ -0,0 +1,112 @@
+<?php
+
+namespace OC\AppFramework\Middleware\PublicShare;
+
+use OC\AppFramework\Middleware\PublicShare\Exceptions\NeedAuthenticationException;
+use OCP\AppFramework\AuthPublicShareController;
+use OCP\AppFramework\Http\NotFoundResponse;
+use OCP\AppFramework\Http\Response;
+use OCP\AppFramework\Middleware;
+use OCP\AppFramework\PublicShareController;
+use OCP\Files\NotFoundException;
+use OCP\IConfig;
+use OCP\IRequest;
+use OCP\ISession;
+
+class PublicShareMiddleware extends Middleware {
+ /** @var IRequest */
+ private $request;
+
+ /** @var ISession */
+ private $session;
+
+ /** @var IConfig */
+ private $config;
+
+ public function __construct(IRequest $request, ISession $session, IConfig $config) {
+ $this->request = $request;
+ $this->session = $session;
+ $this->config = $config;
+ }
+
+ public function beforeController($controller, $methodName) {
+ if (!($controller instanceof PublicShareController)) {
+ return;
+ }
+
+ if (!$this->isLinkSharingEnabled()) {
+ throw new NotFoundException('Link sharing is disabled');
+ }
+
+ // We require the token parameter to be set
+ $token = $this->request->getParam('token');
+ if ($token === null) {
+ throw new NotFoundException();
+ }
+
+ // Set the token
+ $controller->setToken($token);
+
+ if (!$controller->isValidToken()) {
+ $controller->shareNotFound();
+ throw new NotFoundException();
+ }
+
+ // No need to check for authentication when we try to authenticate
+ if ($methodName === 'authenticate' || $methodName === 'showAuthenticate') {
+ return;
+ }
+
+ // If authentication succeeds just continue
+ if ($controller->isAuthenticated()) {
+ return;
+ }
+
+ // If we can authenticate to this controller do it else we throw a 404 to not leak any info
+ if ($controller instanceof AuthPublicShareController) {
+ $this->session->set('public_link_authenticate_redirect', json_encode($this->request->getParams()));
+ throw new NeedAuthenticationException();
+ }
+
+ throw new NotFoundException();
+
+ }
+
+ public function afterException($controller, $methodName, \Exception $exception) {
+ if (!($controller instanceof PublicShareController)) {
+ throw $exception;
+ }
+
+ if ($exception instanceof NotFoundException) {
+ return new NotFoundResponse();
+ }
+
+ if ($controller instanceof AuthPublicShareController && $exception instanceof NeedAuthenticationException) {
+ return $controller->getAuthenticationRedirect($this->getFunctionForRoute($this->request->getParam('_route')));
+ }
+
+ throw $exception;
+ }
+
+ private function getFunctionForRoute(string $route): string {
+ $tmp = explode('.', $route);
+ return array_pop($tmp);
+ }
+
+ /**
+ * Check if link sharing is allowed
+ */
+ private function isLinkSharingEnabled(): bool {
+ // Check if the shareAPI is enabled
+ if ($this->config->getAppValue('core', 'shareapi_enabled', 'yes') !== 'yes') {
+ return false;
+ }
+
+ // Check whether public sharing is enabled
+ if($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php b/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php
index 79359b142ac..e09dfdfcb87 100644
--- a/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/BruteForceMiddleware.php
@@ -26,7 +26,6 @@ namespace OC\AppFramework\Middleware\Security;
use OC\AppFramework\Utility\ControllerMethodReflector;
use OC\Security\Bruteforce\Throttler;
-use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Middleware;
use OCP\IRequest;
diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php
index ca8a2c89416..cd73c81e18a 100644
--- a/lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php
+++ b/lib/private/AppFramework/Middleware/Security/Exceptions/NotAdminException.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -35,7 +36,7 @@ use OCP\AppFramework\Http;
* @package OC\AppFramework\Middleware\Security\Exceptions
*/
class NotAdminException extends SecurityException {
- public function __construct($message = 'Logged in user must be an admin') {
+ public function __construct(string $message) {
parent::__construct($message, Http::STATUS_FORBIDDEN);
}
}
diff --git a/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php b/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php
index c3b5a844ed5..dca761bdfc0 100644
--- a/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php
@@ -27,7 +27,6 @@ namespace OC\AppFramework\Middleware\Security;
use OC\AppFramework\Utility\ControllerMethodReflector;
use OC\Security\RateLimiting\Exception\RateLimitExceededException;
use OC\Security\RateLimiting\Limiter;
-use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Middleware;
diff --git a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
index f45c8f8726c..2eedc39c3ab 100644
--- a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
+++ b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -39,6 +40,7 @@ use OC\AppFramework\Utility\ControllerMethodReflector;
use OC\Security\CSP\ContentSecurityPolicyManager;
use OC\Security\CSP\ContentSecurityPolicyNonceManager;
use OC\Security\CSRF\CsrfTokenManager;
+use OCP\App\AppPathNotFoundException;
use OCP\App\IAppManager;
use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\EmptyContentSecurityPolicy;
@@ -48,6 +50,7 @@ use OCP\AppFramework\Middleware;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\OCSController;
+use OCP\IL10N;
use OCP\INavigationManager;
use OCP\IURLGenerator;
use OCP\IRequest;
@@ -87,33 +90,22 @@ class SecurityMiddleware extends Middleware {
private $cspNonceManager;
/** @var IAppManager */
private $appManager;
+ /** @var IL10N */
+ private $l10n;
- /**
- * @param IRequest $request
- * @param ControllerMethodReflector $reflector
- * @param INavigationManager $navigationManager
- * @param IURLGenerator $urlGenerator
- * @param ILogger $logger
- * @param string $appName
- * @param bool $isLoggedIn
- * @param bool $isAdminUser
- * @param ContentSecurityPolicyManager $contentSecurityPolicyManager
- * @param CSRFTokenManager $csrfTokenManager
- * @param ContentSecurityPolicyNonceManager $cspNonceManager
- * @param IAppManager $appManager
- */
public function __construct(IRequest $request,
ControllerMethodReflector $reflector,
INavigationManager $navigationManager,
IURLGenerator $urlGenerator,
ILogger $logger,
- $appName,
- $isLoggedIn,
- $isAdminUser,
+ string $appName,
+ bool $isLoggedIn,
+ bool $isAdminUser,
ContentSecurityPolicyManager $contentSecurityPolicyManager,
CsrfTokenManager $csrfTokenManager,
ContentSecurityPolicyNonceManager $cspNonceManager,
- IAppManager $appManager
+ IAppManager $appManager,
+ IL10N $l10n
) {
$this->navigationManager = $navigationManager;
$this->request = $request;
@@ -127,6 +119,7 @@ class SecurityMiddleware extends Middleware {
$this->csrfTokenManager = $csrfTokenManager;
$this->cspNonceManager = $cspNonceManager;
$this->appManager = $appManager;
+ $this->l10n = $l10n;
}
/**
@@ -150,10 +143,8 @@ class SecurityMiddleware extends Middleware {
throw new NotLoggedInException();
}
- if(!$this->reflector->hasAnnotation('NoAdminRequired')) {
- if(!$this->isAdminUser) {
- throw new NotAdminException();
- }
+ if(!$this->reflector->hasAnnotation('NoAdminRequired') && !$this->isAdminUser) {
+ throw new NotAdminException($this->l10n->t('Logged in user must be an admin'));
}
}
@@ -185,15 +176,20 @@ class SecurityMiddleware extends Middleware {
}
/**
- * FIXME: Use DI once available
* Checks if app is enabled (also includes a check whether user is allowed to access the resource)
* The getAppPath() check is here since components such as settings also use the AppFramework and
* therefore won't pass this check.
+ * If page is public, app does not need to be enabled for current user/visitor
*/
- if(\OC_App::getAppPath($this->appName) !== false && !$this->appManager->isEnabledForUser($this->appName)) {
- throw new AppNotEnabledException();
+ try {
+ $appPath = $this->appManager->getAppPath($this->appName);
+ } catch (AppPathNotFoundException $e) {
+ $appPath = false;
}
+ if ($appPath !== false && !$isPublicPage && !$this->appManager->isEnabledForUser($this->appName)) {
+ throw new AppNotEnabledException();
+ }
}
/**
@@ -205,7 +201,7 @@ class SecurityMiddleware extends Middleware {
* @param Response $response
* @return Response
*/
- public function afterController($controller, $methodName, Response $response) {
+ public function afterController($controller, $methodName, Response $response): Response {
$policy = !is_null($response->getContentSecurityPolicy()) ? $response->getContentSecurityPolicy() : new ContentSecurityPolicy();
if (get_class($policy) === EmptyContentSecurityPolicy::class) {
@@ -234,14 +230,14 @@ class SecurityMiddleware extends Middleware {
* @throws \Exception the passed in exception if it can't handle it
* @return Response a Response object or null in case that the exception could not be handled
*/
- public function afterException($controller, $methodName, \Exception $exception) {
+ public function afterException($controller, $methodName, \Exception $exception): Response {
if($exception instanceof SecurityException) {
if($exception instanceof StrictCookieMissingException) {
return new RedirectResponse(\OC::$WEBROOT);
}
if (stripos($this->request->getHeader('Accept'),'html') === false) {
$response = new JSONResponse(
- array('message' => $exception->getMessage()),
+ ['message' => $exception->getMessage()],
$exception->getCode()
);
} else {
@@ -259,7 +255,7 @@ class SecurityMiddleware extends Middleware {
}
$this->logger->logException($exception, [
- 'level' => \OCP\Util::DEBUG,
+ 'level' => ILogger::DEBUG,
'app' => 'core',
]);
return $response;
diff --git a/lib/private/AppFramework/OCS/BaseResponse.php b/lib/private/AppFramework/OCS/BaseResponse.php
index 59b8660a382..b27784cfcf2 100644
--- a/lib/private/AppFramework/OCS/BaseResponse.php
+++ b/lib/private/AppFramework/OCS/BaseResponse.php
@@ -22,6 +22,7 @@
*/
namespace OC\AppFramework\OCS;
+use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\EmptyContentSecurityPolicy;
use OCP\AppFramework\Http\Response;
@@ -85,9 +86,60 @@ abstract class BaseResponse extends Response {
* @param string[] $meta
* @return string
*/
- protected function renderResult($meta) {
- // TODO rewrite functions
- return \OC_API::renderResult($this->format, $meta, $this->data);
+ protected function renderResult(array $meta): string {
+ $status = $this->getStatus();
+ if ($status === Http::STATUS_NO_CONTENT ||
+ $status === Http::STATUS_NOT_MODIFIED ||
+ ($status >= 100 && $status <= 199)) {
+ // Those status codes are not supposed to have a body:
+ // https://stackoverflow.com/q/8628725
+ return '';
+ }
+
+ $response = [
+ 'ocs' => [
+ 'meta' => $meta,
+ 'data' => $this->data,
+ ],
+ ];
+
+ if ($this->format === 'json') {
+ return json_encode($response, JSON_HEX_TAG);
+ }
+
+ $writer = new \XMLWriter();
+ $writer->openMemory();
+ $writer->setIndent(true);
+ $writer->startDocument();
+ $this->toXML($response, $writer);
+ $writer->endDocument();
+ return $writer->outputMemory(true);
+
+ }
+
+ /**
+ * @param array $array
+ * @param \XMLWriter $writer
+ */
+ protected function toXML(array $array, \XMLWriter $writer) {
+ foreach ($array as $k => $v) {
+ if ($k[0] === '@') {
+ $writer->writeAttribute(substr($k, 1), $v);
+ continue;
+ }
+
+ if (\is_numeric($k)) {
+ $k = 'element';
+ }
+
+ if (\is_array($v)) {
+ $writer->startElement($k);
+ $this->toXML($v, $writer);
+ $writer->endElement();
+ } else {
+ $writer->writeElement($k, $v);
+ }
+ }
}
public function getOCSStatus() {
diff --git a/lib/private/AppFramework/Utility/ControllerMethodReflector.php b/lib/private/AppFramework/Utility/ControllerMethodReflector.php
index 7c777c52c12..ef4a1959d66 100644
--- a/lib/private/AppFramework/Utility/ControllerMethodReflector.php
+++ b/lib/private/AppFramework/Utility/ControllerMethodReflector.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -42,32 +43,34 @@ class ControllerMethodReflector implements IControllerMethodReflector {
* @param object $object an object or classname
* @param string $method the method which we want to inspect
*/
- public function reflect($object, $method){
+ public function reflect($object, string $method){
$reflection = new \ReflectionMethod($object, $method);
$docs = $reflection->getDocComment();
- // extract everything prefixed by @ and first letter uppercase
- preg_match_all('/^\h+\*\h+@(?P<annotation>[A-Z]\w+)((?P<parameter>.*))?$/m', $docs, $matches);
- foreach($matches['annotation'] as $key => $annontation) {
- $annotationValue = $matches['parameter'][$key];
- if(isset($annotationValue[0]) && $annotationValue[0] === '(' && $annotationValue[strlen($annotationValue) - 1] === ')') {
- $cutString = substr($annotationValue, 1, -1);
- $cutString = str_replace(' ', '', $cutString);
- $splittedArray = explode(',', $cutString);
- foreach($splittedArray as $annotationValues) {
- list($key, $value) = explode('=', $annotationValues);
- $this->annotations[$annontation][$key] = $value;
+ if ($docs !== false) {
+ // extract everything prefixed by @ and first letter uppercase
+ preg_match_all('/^\h+\*\h+@(?P<annotation>[A-Z]\w+)((?P<parameter>.*))?$/m', $docs, $matches);
+ foreach ($matches['annotation'] as $key => $annontation) {
+ $annotationValue = $matches['parameter'][$key];
+ if (isset($annotationValue[0]) && $annotationValue[0] === '(' && $annotationValue[\strlen($annotationValue) - 1] === ')') {
+ $cutString = substr($annotationValue, 1, -1);
+ $cutString = str_replace(' ', '', $cutString);
+ $splittedArray = explode(',', $cutString);
+ foreach ($splittedArray as $annotationValues) {
+ list($key, $value) = explode('=', $annotationValues);
+ $this->annotations[$annontation][$key] = $value;
+ }
+ continue;
}
- continue;
+
+ $this->annotations[$annontation] = [$annotationValue];
}
- $this->annotations[$annontation] = [$annotationValue];
+ // extract type parameter information
+ preg_match_all('/@param\h+(?P<type>\w+)\h+\$(?P<var>\w+)/', $docs, $matches);
+ $this->types = array_combine($matches['var'], $matches['type']);
}
- // extract type parameter information
- preg_match_all('/@param\h+(?P<type>\w+)\h+\$(?P<var>\w+)/', $docs, $matches);
- $this->types = array_combine($matches['var'], $matches['type']);
-
foreach ($reflection->getParameters() as $param) {
// extract type information from PHP 7 scalar types and prefer them
// over phpdoc annotations
@@ -78,10 +81,9 @@ class ControllerMethodReflector implements IControllerMethodReflector {
}
}
+ $default = null;
if($param->isOptional()) {
$default = $param->getDefaultValue();
- } else {
- $default = null;
}
$this->parameters[$param->name] = $default;
}
@@ -94,18 +96,18 @@ class ControllerMethodReflector implements IControllerMethodReflector {
* @return string|null type in the type parameters (@param int $something)
* would return int or null if not existing
*/
- public function getType($parameter) {
+ public function getType(string $parameter) {
if(array_key_exists($parameter, $this->types)) {
return $this->types[$parameter];
- } else {
- return null;
}
+
+ return null;
}
/**
* @return array the arguments of the method with key => default value
*/
- public function getParameters() {
+ public function getParameters(): array {
return $this->parameters;
}
@@ -114,7 +116,7 @@ class ControllerMethodReflector implements IControllerMethodReflector {
* @param string $name the name of the annotation
* @return bool true if the annotation is found
*/
- public function hasAnnotation($name) {
+ public function hasAnnotation(string $name): bool {
return array_key_exists($name, $this->annotations);
}
@@ -125,7 +127,7 @@ class ControllerMethodReflector implements IControllerMethodReflector {
* @param string $key the string of the annotation
* @return string
*/
- public function getAnnotationParameter($name, $key) {
+ public function getAnnotationParameter(string $name, string $key): string {
if(isset($this->annotations[$name][$key])) {
return $this->annotations[$name][$key];
}
diff --git a/lib/private/AppFramework/Utility/SimpleContainer.php b/lib/private/AppFramework/Utility/SimpleContainer.php
index b86d3339264..e96f24ed284 100644
--- a/lib/private/AppFramework/Utility/SimpleContainer.php
+++ b/lib/private/AppFramework/Utility/SimpleContainer.php
@@ -46,6 +46,7 @@ class SimpleContainer extends Container implements IContainer {
/**
* @param ReflectionClass $class the class to instantiate
* @return \stdClass the created class
+ * @suppress PhanUndeclaredClassInstanceof
*/
private function buildClass(ReflectionClass $class) {
$constructor = $class->getConstructor();
@@ -66,6 +67,12 @@ class SimpleContainer extends Container implements IContainer {
try {
$parameters[] = $this->query($resolveName);
} catch (\Exception $e) {
+ if (class_exists('PHPUnit_Framework_AssertionFailedError', false) &&
+ $e instanceof \PHPUnit_Framework_AssertionFailedError) {
+ // Easier debugging of "Your test case is not allowed to access the database."
+ throw $e;
+ }
+
// Service not found, use the default value when available
if ($parameter->isDefaultValueAvailable()) {
$parameters[] = $parameter->getDefaultValue();
diff --git a/lib/private/AppHelper.php b/lib/private/AppHelper.php
deleted file mode 100644
index c99cf4a8304..00000000000
--- a/lib/private/AppHelper.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @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;
-
-/**
- * Class AppHelper
- * @deprecated 8.1.0
- */
-class AppHelper implements \OCP\IHelper {
- /**
- * Gets the content of an URL by using CURL or a fallback if it is not
- * installed
- * @param string $url the url that should be fetched
- * @return string the content of the webpage
- * @deprecated 8.1.0 Use \OCP\IServerContainer::getHTTPClientService
- */
- public function getUrlContent($url) {
- try {
- $client = \OC::$server->getHTTPClientService()->newClient();
- $response = $client->get($url);
- return $response->getBody();
- } catch (\Exception $e) {
- return false;
- }
- }
-}
diff --git a/lib/private/Archive/TAR.php b/lib/private/Archive/TAR.php
index f37da6fc52d..ef2ea83c3c6 100644
--- a/lib/private/Archive/TAR.php
+++ b/lib/private/Archive/TAR.php
@@ -139,7 +139,7 @@ class TAR extends Archive {
*/
public function rename($source, $dest) {
//no proper way to delete, rename entire archive, rename file and remake archive
- $tmp = \OCP\Files::tmpFolder();
+ $tmp = \OC::$server->getTempManager()->getTemporaryFolder();
$this->tar->extract($tmp);
rename($tmp . $source, $tmp . $dest);
$this->tar = null;
@@ -258,7 +258,7 @@ class TAR extends Archive {
* @return bool
*/
public function extractFile($path, $dest) {
- $tmp = \OCP\Files::tmpFolder();
+ $tmp = \OC::$server->getTempManager()->getTemporaryFolder();
if (!$this->fileExists($path)) {
return false;
}
@@ -323,7 +323,7 @@ class TAR extends Archive {
$this->fileList = false;
$this->cachedHeaders = false;
//no proper way to delete, extract entire archive, delete file and remake archive
- $tmp = \OCP\Files::tmpFolder();
+ $tmp = \OC::$server->getTempManager()->getTemporaryFolder();
$this->tar->extract($tmp);
\OCP\Files::rmdirr($tmp . $path);
$this->tar = null;
@@ -346,7 +346,7 @@ class TAR extends Archive {
} else {
$ext = '';
}
- $tmpFile = \OCP\Files::tmpFile($ext);
+ $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
if ($this->fileExists($path)) {
$this->extractFile($path, $tmpFile);
} elseif ($mode == 'r' or $mode == 'rb') {
diff --git a/lib/private/Archive/ZIP.php b/lib/private/Archive/ZIP.php
index fb3e2fdde97..bbfe91ada49 100644
--- a/lib/private/Archive/ZIP.php
+++ b/lib/private/Archive/ZIP.php
@@ -31,6 +31,7 @@
namespace OC\Archive;
use Icewind\Streams\CallbackWrapper;
+use OCP\ILogger;
class ZIP extends Archive{
/**
@@ -47,7 +48,7 @@ class ZIP extends Archive{
$this->zip=new \ZipArchive();
if($this->zip->open($source, \ZipArchive::CREATE)) {
}else{
- \OCP\Util::writeLog('files_archive', 'Error while opening archive '.$source, \OCP\Util::WARN);
+ \OCP\Util::writeLog('files_archive', 'Error while opening archive '.$source, ILogger::WARN);
}
}
/**
@@ -198,7 +199,7 @@ class ZIP extends Archive{
}else{
$ext='';
}
- $tmpFile=\OCP\Files::tmpFile($ext);
+ $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
if($this->fileExists($path)) {
$this->extractFile($path, $tmpFile);
}
diff --git a/lib/private/Authentication/Exceptions/ExpiredTokenException.php b/lib/private/Authentication/Exceptions/ExpiredTokenException.php
new file mode 100644
index 00000000000..a45ca5b6955
--- /dev/null
+++ b/lib/private/Authentication/Exceptions/ExpiredTokenException.php
@@ -0,0 +1,41 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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\Authentication\Token;
+
+use OC\Authentication\Exceptions\InvalidTokenException;
+
+class ExpiredTokenException extends InvalidTokenException {
+ /** @var IToken */
+ private $token;
+
+ public function __construct(IToken $token) {
+ parent::__construct();
+
+ $this->token = $token;
+ }
+
+ public function getToken(): IToken {
+ return $this->token;
+ }
+}
diff --git a/lib/private/Authentication/Token/DefaultToken.php b/lib/private/Authentication/Token/DefaultToken.php
index e06803d0bfc..85ea0dc4cdd 100644
--- a/lib/private/Authentication/Token/DefaultToken.php
+++ b/lib/private/Authentication/Token/DefaultToken.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -28,82 +29,76 @@ use OCP\AppFramework\Db\Entity;
/**
* @method void setId(int $id)
* @method void setUid(string $uid);
- * @method void setLoginName(string $loginName)
- * @method void setPassword(string $password)
+ * @method void setLoginName(string $loginname)
* @method void setName(string $name)
- * @method string getName()
- * @method void setToken(string $token)
* @method string getToken()
- * @method void setType(string $type)
+ * @method void setType(int $type)
* @method int getType()
* @method void setRemember(int $remember)
- * @method int getRemember()
- * @method void setLastActivity(int $lastActivity)
+ * @method void setLastActivity(int $lastactivity)
* @method int getLastActivity()
+ * @method void setVersion(int $version)
*/
class DefaultToken extends Entity implements IToken {
- /**
- * @var string user UID
- */
+ const VERSION = 1;
+
+ /** @var string user UID */
protected $uid;
- /**
- * @var string login name used for generating the token
- */
+ /** @var string login name used for generating the token */
protected $loginName;
- /**
- * @var string encrypted user password
- */
+ /** @var string encrypted user password */
protected $password;
- /**
- * @var string token name (e.g. browser/OS)
- */
+ /** @var string token name (e.g. browser/OS) */
protected $name;
- /**
- * @var string
- */
+ /** @var string */
protected $token;
- /**
- * @var int
- */
+ /** @var int */
protected $type;
- /**
- * @var int
- */
+ /** @var int */
protected $remember;
- /**
- * @var int
- */
+ /** @var int */
protected $lastActivity;
- /**
- * @var int
- */
+ /** @var int */
protected $lastCheck;
- /**
- * @var string
- */
+ /** @var string */
protected $scope;
+ /** @var int */
+ protected $expires;
+
+ /** @var int */
+ protected $version;
+
public function __construct() {
+ $this->addType('uid', 'string');
+ $this->addType('loginName', 'string');
+ $this->addType('password', 'string');
+ $this->addType('name', 'string');
+ $this->addType('token', 'string');
$this->addType('type', 'int');
+ $this->addType('remember', 'int');
$this->addType('lastActivity', 'int');
$this->addType('lastCheck', 'int');
+ $this->addType('scope', 'string');
+ $this->addType('expires', 'int');
+ $this->addType('version', 'int');
}
- public function getId() {
+ public function getId(): int {
return $this->id;
}
- public function getUID() {
+ public function getUID(): string {
return $this->uid;
}
@@ -112,14 +107,14 @@ class DefaultToken extends Entity implements IToken {
*
* @return string
*/
- public function getLoginName() {
+ public function getLoginName(): string {
return parent::getLoginName();
}
/**
* Get the (encrypted) login password
*
- * @return string
+ * @return string|null
*/
public function getPassword() {
return parent::getPassword();
@@ -140,7 +135,7 @@ class DefaultToken extends Entity implements IToken {
*
* @return int
*/
- public function getLastCheck() {
+ public function getLastCheck(): int {
return parent::getLastCheck();
}
@@ -149,15 +144,20 @@ class DefaultToken extends Entity implements IToken {
*
* @param int $time
*/
- public function setLastCheck($time) {
- return parent::setLastCheck($time);
+ public function setLastCheck(int $time) {
+ parent::setLastCheck($time);
}
- public function getScope() {
- return parent::getScope();
+ public function getScope(): string {
+ $scope = parent::getScope();
+ if ($scope === null) {
+ return '';
+ }
+
+ return $scope;
}
- public function getScopeAsArray() {
+ public function getScopeAsArray(): array {
$scope = json_decode($this->getScope(), true);
if (!$scope) {
return [
@@ -168,10 +168,37 @@ class DefaultToken extends Entity implements IToken {
}
public function setScope($scope) {
- if (is_array($scope)) {
+ if (\is_array($scope)) {
parent::setScope(json_encode($scope));
} else {
parent::setScope((string)$scope);
}
}
+
+ public function getName(): string {
+ return parent::getName();
+ }
+
+ public function getRemember(): int {
+ return parent::getRemember();
+ }
+
+ public function setToken(string $token) {
+ parent::setToken($token);
+ }
+
+ public function setPassword(string $password = null) {
+ parent::setPassword($password);
+ }
+
+ public function setExpires($expires) {
+ parent::setExpires($expires);
+ }
+
+ /**
+ * @return int|null
+ */
+ public function getExpires() {
+ return parent::getExpires();
+ }
}
diff --git a/lib/private/Authentication/Token/DefaultTokenMapper.php b/lib/private/Authentication/Token/DefaultTokenMapper.php
index 41d1b9f203d..b8df00ff094 100644
--- a/lib/private/Authentication/Token/DefaultTokenMapper.php
+++ b/lib/private/Authentication/Token/DefaultTokenMapper.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -29,12 +30,11 @@
namespace OC\Authentication\Token;
use OCP\AppFramework\Db\DoesNotExistException;
-use OCP\AppFramework\Db\Mapper;
+use OCP\AppFramework\Db\QBMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
-use OCP\IUser;
-class DefaultTokenMapper extends Mapper {
+class DefaultTokenMapper extends QBMapper {
public function __construct(IDBConnection $db) {
parent::__construct($db, 'authtoken');
@@ -45,12 +45,12 @@ class DefaultTokenMapper extends Mapper {
*
* @param string $token
*/
- public function invalidate($token) {
+ public function invalidate(string $token) {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->delete('authtoken')
- ->where($qb->expr()->eq('token', $qb->createParameter('token')))
- ->setParameter('token', $token)
+ ->where($qb->expr()->eq('token', $qb->createNamedParameter($token, IQueryBuilder::PARAM_STR)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(DefaultToken::VERSION, IQueryBuilder::PARAM_INT)))
->execute();
}
@@ -58,13 +58,14 @@ class DefaultTokenMapper extends Mapper {
* @param int $olderThan
* @param int $remember
*/
- public function invalidateOld($olderThan, $remember = IToken::DO_NOT_REMEMBER) {
+ public function invalidateOld(int $olderThan, int $remember = IToken::DO_NOT_REMEMBER) {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->delete('authtoken')
->where($qb->expr()->lt('last_activity', $qb->createNamedParameter($olderThan, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('type', $qb->createNamedParameter(IToken::TEMPORARY_TOKEN, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('remember', $qb->createNamedParameter($remember, IQueryBuilder::PARAM_INT)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(DefaultToken::VERSION, IQueryBuilder::PARAM_INT)))
->execute();
}
@@ -75,12 +76,13 @@ class DefaultTokenMapper extends Mapper {
* @throws DoesNotExistException
* @return DefaultToken
*/
- public function getToken($token) {
+ public function getToken(string $token): DefaultToken {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
- $result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'remember', 'token', 'last_activity', 'last_check', 'scope')
+ $result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'token', 'type', 'remember', 'last_activity', 'last_check', 'scope', 'expires', 'version')
->from('authtoken')
->where($qb->expr()->eq('token', $qb->createNamedParameter($token)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(DefaultToken::VERSION, IQueryBuilder::PARAM_INT)))
->execute();
$data = $result->fetch();
@@ -94,16 +96,17 @@ class DefaultTokenMapper extends Mapper {
/**
* Get the token for $id
*
- * @param string $id
+ * @param int $id
* @throws DoesNotExistException
* @return DefaultToken
*/
- public function getTokenById($id) {
+ public function getTokenById(int $id): DefaultToken {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
- $result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'token', 'last_activity', 'last_check', 'scope')
+ $result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'token', 'type', 'remember', 'last_activity', 'last_check', 'scope', 'expires', 'version')
->from('authtoken')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(DefaultToken::VERSION, IQueryBuilder::PARAM_INT)))
->execute();
$data = $result->fetch();
@@ -120,15 +123,16 @@ class DefaultTokenMapper extends Mapper {
* The provider may limit the number of result rows in case of an abuse
* where a high number of (session) tokens is generated
*
- * @param IUser $user
+ * @param string $uid
* @return DefaultToken[]
*/
- public function getTokenByUser(IUser $user) {
+ public function getTokenByUser(string $uid): array {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
- $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'remember', 'token', 'last_activity', 'last_check', 'scope')
+ $qb->select('id', 'uid', 'login_name', 'password', 'name', 'token', 'type', 'remember', 'last_activity', 'last_check', 'scope', 'expires', 'version')
->from('authtoken')
- ->where($qb->expr()->eq('uid', $qb->createNamedParameter($user->getUID())))
+ ->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(DefaultToken::VERSION, IQueryBuilder::PARAM_INT)))
->setMaxResults(1000);
$result = $qb->execute();
$data = $result->fetchAll();
@@ -141,16 +145,13 @@ class DefaultTokenMapper extends Mapper {
return $entities;
}
- /**
- * @param IUser $user
- * @param int $id
- */
- public function deleteById(IUser $user, $id) {
+ public function deleteById(string $uid, int $id) {
/* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder();
$qb->delete('authtoken')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
- ->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($user->getUID())));
+ ->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(DefaultToken::VERSION, IQueryBuilder::PARAM_INT)));
$qb->execute();
}
@@ -159,10 +160,11 @@ class DefaultTokenMapper extends Mapper {
*
* @param string $name
*/
- public function deleteByName($name) {
+ public function deleteByName(string $name) {
$qb = $this->db->getQueryBuilder();
$qb->delete('authtoken')
- ->where($qb->expr()->eq('name', $qb->createNamedParameter($name), IQueryBuilder::PARAM_STR));
+ ->where($qb->expr()->eq('name', $qb->createNamedParameter($name), IQueryBuilder::PARAM_STR))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(DefaultToken::VERSION, IQueryBuilder::PARAM_INT)));
$qb->execute();
}
diff --git a/lib/private/Authentication/Token/DefaultTokenProvider.php b/lib/private/Authentication/Token/DefaultTokenProvider.php
index 36a8b1d5464..8c2d8c33a97 100644
--- a/lib/private/Authentication/Token/DefaultTokenProvider.php
+++ b/lib/private/Authentication/Token/DefaultTokenProvider.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @copyright Copyright (c) 2016, Christoph Wurst <christoph@winzerhof-wurst.at>
@@ -34,7 +35,6 @@ use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\ILogger;
-use OCP\IUser;
use OCP\Security\ICrypto;
class DefaultTokenProvider implements IProvider {
@@ -85,7 +85,13 @@ class DefaultTokenProvider implements IProvider {
* @param int $remember whether the session token should be used for remember-me
* @return IToken
*/
- public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN, $remember = IToken::DO_NOT_REMEMBER) {
+ public function generateToken(string $token,
+ string $uid,
+ string $loginName,
+ $password,
+ string $name,
+ int $type = IToken::TEMPORARY_TOKEN,
+ int $remember = IToken::DO_NOT_REMEMBER): IToken {
$dbToken = new DefaultToken();
$dbToken->setUid($uid);
$dbToken->setLoginName($loginName);
@@ -98,6 +104,7 @@ class DefaultTokenProvider implements IProvider {
$dbToken->setRemember($remember);
$dbToken->setLastActivity($this->time->getTime());
$dbToken->setLastCheck($this->time->getTime());
+ $dbToken->setVersion(DefaultToken::VERSION);
$this->mapper->insert($dbToken);
@@ -136,17 +143,8 @@ class DefaultTokenProvider implements IProvider {
}
}
- /**
- * Get all tokens of a user
- *
- * The provider may limit the number of result rows in case of an abuse
- * where a high number of (session) tokens is generated
- *
- * @param IUser $user
- * @return IToken[]
- */
- public function getTokenByUser(IUser $user) {
- return $this->mapper->getTokenByUser($user);
+ public function getTokenByUser(string $uid): array {
+ return $this->mapper->getTokenByUser($uid);
}
/**
@@ -154,29 +152,43 @@ class DefaultTokenProvider implements IProvider {
*
* @param string $tokenId
* @throws InvalidTokenException
- * @return DefaultToken
+ * @throws ExpiredTokenException
+ * @return IToken
*/
- public function getToken($tokenId) {
+ public function getToken(string $tokenId): IToken {
try {
- return $this->mapper->getToken($this->hashToken($tokenId));
+ $token = $this->mapper->getToken($this->hashToken($tokenId));
} catch (DoesNotExistException $ex) {
throw new InvalidTokenException();
}
+
+ if ((int)$token->getExpires() !== 0 && $token->getExpires() < $this->time->getTime()) {
+ throw new ExpiredTokenException($token);
+ }
+
+ return $token;
}
/**
* Get a token by token id
*
- * @param string $tokenId
+ * @param int $tokenId
* @throws InvalidTokenException
- * @return DefaultToken
+ * @throws ExpiredTokenException
+ * @return IToken
*/
- public function getTokenById($tokenId) {
+ public function getTokenById(int $tokenId): IToken {
try {
- return $this->mapper->getTokenById($tokenId);
+ $token = $this->mapper->getTokenById($tokenId);
} catch (DoesNotExistException $ex) {
throw new InvalidTokenException();
}
+
+ if ($token->getExpires() !== null && $token->getExpires() < $this->time->getTime()) {
+ throw new ExpiredTokenException($token);
+ }
+
+ return $token;
}
/**
@@ -184,7 +196,7 @@ class DefaultTokenProvider implements IProvider {
* @param string $sessionId
* @throws InvalidTokenException
*/
- public function renewSessionToken($oldSessionId, $sessionId) {
+ public function renewSessionToken(string $oldSessionId, string $sessionId) {
$token = $this->getToken($oldSessionId);
$newToken = new DefaultToken();
@@ -210,7 +222,7 @@ class DefaultTokenProvider implements IProvider {
* @throws PasswordlessTokenException
* @return string
*/
- public function getPassword(IToken $savedToken, $tokenId) {
+ public function getPassword(IToken $savedToken, string $tokenId): string {
$password = $savedToken->getPassword();
if (is_null($password)) {
throw new PasswordlessTokenException();
@@ -226,7 +238,7 @@ class DefaultTokenProvider implements IProvider {
* @param string $password
* @throws InvalidTokenException
*/
- public function setPassword(IToken $token, $tokenId, $password) {
+ public function setPassword(IToken $token, string $tokenId, string $password) {
if (!($token instanceof DefaultToken)) {
throw new InvalidTokenException();
}
@@ -240,18 +252,12 @@ class DefaultTokenProvider implements IProvider {
*
* @param string $token
*/
- public function invalidateToken($token) {
+ public function invalidateToken(string $token) {
$this->mapper->invalidate($this->hashToken($token));
}
- /**
- * Invalidate (delete) the given token
- *
- * @param IUser $user
- * @param int $id
- */
- public function invalidateTokenById(IUser $user, $id) {
- $this->mapper->deleteById($user, $id);
+ public function invalidateTokenById(string $uid, int $id) {
+ $this->mapper->deleteById($uid, $id);
}
/**
@@ -267,10 +273,32 @@ class DefaultTokenProvider implements IProvider {
}
/**
+ * Rotate the token. Usefull for for example oauth tokens
+ *
+ * @param IToken $token
+ * @param string $oldTokenId
+ * @param string $newTokenId
+ * @return IToken
+ */
+ public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
+ try {
+ $password = $this->getPassword($token, $oldTokenId);
+ $token->setPassword($this->encryptPassword($password, $newTokenId));
+ } catch (PasswordlessTokenException $e) {
+
+ }
+
+ $token->setToken($this->hashToken($newTokenId));
+ $this->updateToken($token);
+
+ return $token;
+ }
+
+ /**
* @param string $token
* @return string
*/
- private function hashToken($token) {
+ private function hashToken(string $token): string {
$secret = $this->config->getSystemValue('secret');
return hash('sha512', $token . $secret);
}
@@ -284,7 +312,7 @@ class DefaultTokenProvider implements IProvider {
* @param string $token
* @return string encrypted password
*/
- private function encryptPassword($password, $token) {
+ private function encryptPassword(string $password, string $token): string {
$secret = $this->config->getSystemValue('secret');
return $this->crypto->encrypt($password, $token . $secret);
}
@@ -299,7 +327,7 @@ class DefaultTokenProvider implements IProvider {
* @throws InvalidTokenException
* @return string the decrypted key
*/
- private function decryptPassword($password, $token) {
+ private function decryptPassword(string $password, string $token): string {
$secret = $this->config->getSystemValue('secret');
try {
return $this->crypto->decrypt($password, $token . $secret);
diff --git a/lib/private/Authentication/Token/IProvider.php b/lib/private/Authentication/Token/IProvider.php
index e1cc8182ff0..ab46bd12126 100644
--- a/lib/private/Authentication/Token/IProvider.php
+++ b/lib/private/Authentication/Token/IProvider.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -27,7 +28,6 @@ namespace OC\Authentication\Token;
use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Exceptions\PasswordlessTokenException;
-use OCP\IUser;
interface IProvider {
@@ -44,25 +44,33 @@ interface IProvider {
* @param int $remember whether the session token should be used for remember-me
* @return IToken
*/
- public function generateToken($token, $uid, $loginName, $password, $name, $type = IToken::TEMPORARY_TOKEN, $remember = IToken::DO_NOT_REMEMBER);
+ public function generateToken(string $token,
+ string $uid,
+ string $loginName,
+ $password,
+ string $name,
+ int $type = IToken::TEMPORARY_TOKEN,
+ int $remember = IToken::DO_NOT_REMEMBER): IToken;
/**
* Get a token by token id
*
* @param string $tokenId
* @throws InvalidTokenException
+ * @throws ExpiredTokenException
* @return IToken
*/
- public function getToken($tokenId);
+ public function getToken(string $tokenId): IToken;
/**
* Get a token by token id
*
- * @param string $tokenId
+ * @param int $tokenId
* @throws InvalidTokenException
- * @return DefaultToken
+ * @throws ExpiredTokenException
+ * @return IToken
*/
- public function getTokenById($tokenId);
+ public function getTokenById(int $tokenId): IToken;
/**
* Duplicate an existing session token
@@ -71,22 +79,22 @@ interface IProvider {
* @param string $sessionId
* @throws InvalidTokenException
*/
- public function renewSessionToken($oldSessionId, $sessionId);
+ public function renewSessionToken(string $oldSessionId, string $sessionId);
/**
* Invalidate (delete) the given session token
*
* @param string $token
*/
- public function invalidateToken($token);
+ public function invalidateToken(string $token);
/**
* Invalidate (delete) the given token
*
- * @param IUser $user
+ * @param string $uid
* @param int $id
*/
- public function invalidateTokenById(IUser $user, $id);
+ public function invalidateTokenById(string $uid, int $id);
/**
* Invalidate (delete) old session tokens
@@ -113,10 +121,10 @@ interface IProvider {
* The provider may limit the number of result rows in case of an abuse
* where a high number of (session) tokens is generated
*
- * @param IUser $user
+ * @param string $uid
* @return IToken[]
*/
- public function getTokenByUser(IUser $user);
+ public function getTokenByUser(string $uid): array;
/**
* Get the (unencrypted) password of the given token
@@ -127,7 +135,7 @@ interface IProvider {
* @throws PasswordlessTokenException
* @return string
*/
- public function getPassword(IToken $token, $tokenId);
+ public function getPassword(IToken $token, string $tokenId): string;
/**
* Encrypt and set the password of the given token
@@ -137,5 +145,15 @@ interface IProvider {
* @param string $password
* @throws InvalidTokenException
*/
- public function setPassword(IToken $token, $tokenId, $password);
+ public function setPassword(IToken $token, string $tokenId, string $password);
+
+ /**
+ * Rotate the token. Usefull for for example oauth tokens
+ *
+ * @param IToken $token
+ * @param string $oldTokenId
+ * @param string $newTokenId
+ * @return IToken
+ */
+ public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken;
}
diff --git a/lib/private/Authentication/Token/IToken.php b/lib/private/Authentication/Token/IToken.php
index a24d31e2ed2..e122ec02764 100644
--- a/lib/private/Authentication/Token/IToken.php
+++ b/lib/private/Authentication/Token/IToken.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -37,26 +38,26 @@ interface IToken extends JsonSerializable {
*
* @return int
*/
- public function getId();
+ public function getId(): int;
/**
* Get the user UID
*
* @return string
*/
- public function getUID();
+ public function getUID(): string;
/**
* Get the login name used when generating the token
*
* @return string
*/
- public function getLoginName();
+ public function getLoginName(): string;
/**
* Get the (encrypted) login password
*
- * @return string
+ * @return string|null
*/
public function getPassword();
@@ -65,28 +66,28 @@ interface IToken extends JsonSerializable {
*
* @return int
*/
- public function getLastCheck();
+ public function getLastCheck(): int;
/**
* Set the timestamp of the last password check
*
* @param int $time
*/
- public function setLastCheck($time);
+ public function setLastCheck(int $time);
/**
* Get the authentication scope for this token
*
* @return string
*/
- public function getScope();
+ public function getScope(): string;
/**
* Get the authentication scope for this token
*
* @return array
*/
- public function getScopeAsArray();
+ public function getScopeAsArray(): array;
/**
* Set the authentication scope for this token
@@ -94,4 +95,38 @@ interface IToken extends JsonSerializable {
* @param array $scope
*/
public function setScope($scope);
+
+ /**
+ * Get the name of the token
+ * @return string
+ */
+ public function getName(): string;
+
+ /**
+ * Get the remember state of the token
+ *
+ * @return int
+ */
+ public function getRemember(): int;
+
+ /**
+ * Set the token
+ *
+ * @param string $token
+ */
+ public function setToken(string $token);
+
+ /**
+ * Set the password
+ *
+ * @param string $password
+ */
+ public function setPassword(string $password);
+
+ /**
+ * Set the expiration time of the token
+ *
+ * @param int|null $expires
+ */
+ public function setExpires($expires);
}
diff --git a/lib/private/Authentication/Token/Manager.php b/lib/private/Authentication/Token/Manager.php
new file mode 100644
index 00000000000..254a1598943
--- /dev/null
+++ b/lib/private/Authentication/Token/Manager.php
@@ -0,0 +1,230 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @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\Authentication\Token;
+
+use OC\Authentication\Exceptions\InvalidTokenException;
+use OC\Authentication\Exceptions\PasswordlessTokenException;
+
+class Manager implements IProvider {
+
+ /** @var DefaultTokenProvider */
+ private $defaultTokenProvider;
+
+ /** @var PublicKeyTokenProvider */
+ private $publicKeyTokenProvider;
+
+ public function __construct(DefaultTokenProvider $defaultTokenProvider, PublicKeyTokenProvider $publicKeyTokenProvider) {
+ $this->defaultTokenProvider = $defaultTokenProvider;
+ $this->publicKeyTokenProvider = $publicKeyTokenProvider;
+ }
+
+ /**
+ * Create and persist a new token
+ *
+ * @param string $token
+ * @param string $uid
+ * @param string $loginName
+ * @param string|null $password
+ * @param string $name
+ * @param int $type token type
+ * @param int $remember whether the session token should be used for remember-me
+ * @return IToken
+ */
+ public function generateToken(string $token,
+ string $uid,
+ string $loginName,
+ $password,
+ string $name,
+ int $type = IToken::TEMPORARY_TOKEN,
+ int $remember = IToken::DO_NOT_REMEMBER): IToken {
+ return $this->publicKeyTokenProvider->generateToken(
+ $token,
+ $uid,
+ $loginName,
+ $password,
+ $name,
+ $type,
+ $remember
+ );
+ }
+
+ /**
+ * Save the updated token
+ *
+ * @param IToken $token
+ * @throws InvalidTokenException
+ */
+ public function updateToken(IToken $token) {
+ $provider = $this->getProvider($token);
+ $provider->updateToken($token);
+ }
+
+ /**
+ * Update token activity timestamp
+ *
+ * @throws InvalidTokenException
+ * @param IToken $token
+ */
+ public function updateTokenActivity(IToken $token) {
+ $provider = $this->getProvider($token);
+ $provider->updateTokenActivity($token);
+ }
+
+ /**
+ * @param string $uid
+ * @return IToken[]
+ */
+ public function getTokenByUser(string $uid): array {
+ $old = $this->defaultTokenProvider->getTokenByUser($uid);
+ $new = $this->publicKeyTokenProvider->getTokenByUser($uid);
+
+ return array_merge($old, $new);
+ }
+
+ /**
+ * Get a token by token
+ *
+ * @param string $tokenId
+ * @throws InvalidTokenException
+ * @return IToken
+ */
+ public function getToken(string $tokenId): IToken {
+ try {
+ return $this->publicKeyTokenProvider->getToken($tokenId);
+ } catch (InvalidTokenException $e) {
+ // No worries we try to convert it to a PublicKey Token
+ }
+
+ //Convert!
+ $token = $this->defaultTokenProvider->getToken($tokenId);
+
+ try {
+ $password = $this->defaultTokenProvider->getPassword($token, $tokenId);
+ } catch (PasswordlessTokenException $e) {
+ $password = null;
+ }
+
+ return $this->publicKeyTokenProvider->convertToken($token, $tokenId, $password);
+ }
+
+ /**
+ * Get a token by token id
+ *
+ * @param int $tokenId
+ * @throws InvalidTokenException
+ * @return IToken
+ */
+ public function getTokenById(int $tokenId): IToken {
+ try {
+ return $this->publicKeyTokenProvider->getTokenById($tokenId);
+ } catch (InvalidTokenException $e) {
+ return $this->defaultTokenProvider->getTokenById($tokenId);
+ }
+ }
+
+ /**
+ * @param string $oldSessionId
+ * @param string $sessionId
+ * @throws InvalidTokenException
+ */
+ public function renewSessionToken(string $oldSessionId, string $sessionId) {
+ try {
+ $this->publicKeyTokenProvider->renewSessionToken($oldSessionId, $sessionId);
+ } catch (InvalidTokenException $e) {
+ $this->defaultTokenProvider->renewSessionToken($oldSessionId, $sessionId);
+ }
+ }
+
+ /**
+ * @param IToken $savedToken
+ * @param string $tokenId session token
+ * @throws InvalidTokenException
+ * @throws PasswordlessTokenException
+ * @return string
+ */
+ public function getPassword(IToken $savedToken, string $tokenId): string {
+ $provider = $this->getProvider($savedToken);
+ return $provider->getPassword($savedToken, $tokenId);
+ }
+
+ public function setPassword(IToken $token, string $tokenId, string $password) {
+ $provider = $this->getProvider($token);
+ $provider->setPassword($token, $tokenId, $password);
+ }
+
+ public function invalidateToken(string $token) {
+ $this->defaultTokenProvider->invalidateToken($token);
+ $this->publicKeyTokenProvider->invalidateToken($token);
+ }
+
+ public function invalidateTokenById(string $uid, int $id) {
+ $this->defaultTokenProvider->invalidateTokenById($uid, $id);
+ $this->publicKeyTokenProvider->invalidateTokenById($uid, $id);
+ }
+
+ public function invalidateOldTokens() {
+ $this->defaultTokenProvider->invalidateOldTokens();
+ $this->publicKeyTokenProvider->invalidateOldTokens();
+ }
+
+ /**
+ * @param IToken $token
+ * @param string $oldTokenId
+ * @param string $newTokenId
+ * @return IToken
+ * @throws InvalidTokenException
+ */
+ public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
+ if ($token instanceof DefaultToken) {
+ try {
+ $password = $this->defaultTokenProvider->getPassword($token, $oldTokenId);
+ } catch (PasswordlessTokenException $e) {
+ $password = null;
+ }
+
+ return $this->publicKeyTokenProvider->convertToken($token, $newTokenId, $password);
+ }
+
+ if ($token instanceof PublicKeyToken) {
+ return $this->publicKeyTokenProvider->rotate($token, $oldTokenId, $newTokenId);
+ }
+
+ throw new InvalidTokenException();
+ }
+
+ /**
+ * @param IToken $token
+ * @return IProvider
+ * @throws InvalidTokenException
+ */
+ private function getProvider(IToken $token): IProvider {
+ if ($token instanceof DefaultToken) {
+ return $this->defaultTokenProvider;
+ }
+ if ($token instanceof PublicKeyToken) {
+ return $this->publicKeyTokenProvider;
+ }
+ throw new InvalidTokenException();
+ }
+}
diff --git a/lib/private/Authentication/Token/PublicKeyToken.php b/lib/private/Authentication/Token/PublicKeyToken.php
new file mode 100644
index 00000000000..0e793ce8c7c
--- /dev/null
+++ b/lib/private/Authentication/Token/PublicKeyToken.php
@@ -0,0 +1,217 @@
+<?php
+/** @noinspection ALL */
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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\Authentication\Token;
+
+use OCP\AppFramework\Db\Entity;
+
+/**
+ * @method void setId(int $id)
+ * @method void setUid(string $uid);
+ * @method void setLoginName(string $loginname)
+ * @method void setName(string $name)
+ * @method string getToken()
+ * @method void setType(int $type)
+ * @method int getType()
+ * @method void setRemember(int $remember)
+ * @method void setLastActivity(int $lastactivity)
+ * @method int getLastActivity()
+ * @method string getPrivateKey()
+ * @method void setPrivateKey(string $key)
+ * @method string getPublicKey()
+ * @method void setPublicKey(string $key)
+ * @method void setVersion(int $version)
+ */
+class PublicKeyToken extends Entity implements IToken {
+
+ const VERSION = 2;
+
+ /** @var string user UID */
+ protected $uid;
+
+ /** @var string login name used for generating the token */
+ protected $loginName;
+
+ /** @var string encrypted user password */
+ protected $password;
+
+ /** @var string token name (e.g. browser/OS) */
+ protected $name;
+
+ /** @var string */
+ protected $token;
+
+ /** @var int */
+ protected $type;
+
+ /** @var int */
+ protected $remember;
+
+ /** @var int */
+ protected $lastActivity;
+
+ /** @var int */
+ protected $lastCheck;
+
+ /** @var string */
+ protected $scope;
+
+ /** @var int */
+ protected $expires;
+
+ /** @var string */
+ protected $privateKey;
+
+ /** @var string */
+ protected $publicKey;
+
+ /** @var int */
+ protected $version;
+
+ public function __construct() {
+ $this->addType('uid', 'string');
+ $this->addType('loginName', 'string');
+ $this->addType('password', 'string');
+ $this->addType('name', 'string');
+ $this->addType('token', 'string');
+ $this->addType('type', 'int');
+ $this->addType('remember', 'int');
+ $this->addType('lastActivity', 'int');
+ $this->addType('lastCheck', 'int');
+ $this->addType('scope', 'string');
+ $this->addType('expires', 'int');
+ $this->addType('publicKey', 'string');
+ $this->addType('privateKey', 'string');
+ $this->addType('version', 'int');
+ }
+
+ public function getId(): int {
+ return $this->id;
+ }
+
+ public function getUID(): string {
+ return $this->uid;
+ }
+
+ /**
+ * Get the login name used when generating the token
+ *
+ * @return string
+ */
+ public function getLoginName(): string {
+ return parent::getLoginName();
+ }
+
+ /**
+ * Get the (encrypted) login password
+ *
+ * @return string|null
+ */
+ public function getPassword() {
+ return parent::getPassword();
+ }
+
+ public function jsonSerialize() {
+ return [
+ 'id' => $this->id,
+ 'name' => $this->name,
+ 'lastActivity' => $this->lastActivity,
+ 'type' => $this->type,
+ 'scope' => $this->getScopeAsArray()
+ ];
+ }
+
+ /**
+ * Get the timestamp of the last password check
+ *
+ * @return int
+ */
+ public function getLastCheck(): int {
+ return parent::getLastCheck();
+ }
+
+ /**
+ * Get the timestamp of the last password check
+ *
+ * @param int $time
+ */
+ public function setLastCheck(int $time) {
+ parent::setLastCheck($time);
+ }
+
+ public function getScope(): string {
+ $scope = parent::getScope();
+ if ($scope === null) {
+ return '';
+ }
+
+ return $scope;
+ }
+
+ public function getScopeAsArray(): array {
+ $scope = json_decode($this->getScope(), true);
+ if (!$scope) {
+ return [
+ 'filesystem'=> true
+ ];
+ }
+ return $scope;
+ }
+
+ public function setScope($scope) {
+ if (is_array($scope)) {
+ parent::setScope(json_encode($scope));
+ } else {
+ parent::setScope((string)$scope);
+ }
+ }
+
+ public function getName(): string {
+ return parent::getName();
+ }
+
+ public function getRemember(): int {
+ return parent::getRemember();
+ }
+
+ public function setToken(string $token) {
+ parent::setToken($token);
+ }
+
+ public function setPassword(string $password = null) {
+ parent::setPassword($password);
+ }
+
+ public function setExpires($expires) {
+ parent::setExpires($expires);
+ }
+
+ /**
+ * @return int|null
+ */
+ public function getExpires() {
+ return parent::getExpires();
+ }
+}
diff --git a/lib/private/Authentication/Token/PublicKeyTokenMapper.php b/lib/private/Authentication/Token/PublicKeyTokenMapper.php
new file mode 100644
index 00000000000..5e5c69dbc46
--- /dev/null
+++ b/lib/private/Authentication/Token/PublicKeyTokenMapper.php
@@ -0,0 +1,172 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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\Authentication\Token;
+
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\QBMapper;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+class PublicKeyTokenMapper extends QBMapper {
+
+ public function __construct(IDBConnection $db) {
+ parent::__construct($db, 'authtoken');
+ }
+
+ /**
+ * Invalidate (delete) a given token
+ *
+ * @param string $token
+ */
+ public function invalidate(string $token) {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $qb->delete('authtoken')
+ ->where($qb->expr()->eq('token', $qb->createNamedParameter($token)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)))
+ ->execute();
+ }
+
+ /**
+ * @param int $olderThan
+ * @param int $remember
+ */
+ public function invalidateOld(int $olderThan, int $remember = IToken::DO_NOT_REMEMBER) {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $qb->delete('authtoken')
+ ->where($qb->expr()->lt('last_activity', $qb->createNamedParameter($olderThan, IQueryBuilder::PARAM_INT)))
+ ->andWhere($qb->expr()->eq('type', $qb->createNamedParameter(IToken::TEMPORARY_TOKEN, IQueryBuilder::PARAM_INT)))
+ ->andWhere($qb->expr()->eq('remember', $qb->createNamedParameter($remember, IQueryBuilder::PARAM_INT)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)))
+ ->execute();
+ }
+
+ /**
+ * Get the user UID for the given token
+ *
+ * @throws DoesNotExistException
+ */
+ public function getToken(string $token): PublicKeyToken {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $result = $qb->select('*')
+ ->from('authtoken')
+ ->where($qb->expr()->eq('token', $qb->createNamedParameter($token)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)))
+ ->execute();
+
+ $data = $result->fetch();
+ $result->closeCursor();
+ if ($data === false) {
+ throw new DoesNotExistException('token does not exist');
+ }
+ return PublicKeyToken::fromRow($data);
+ }
+
+ /**
+ * Get the token for $id
+ *
+ * @throws DoesNotExistException
+ */
+ public function getTokenById(int $id): PublicKeyToken {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $result = $qb->select('*')
+ ->from('authtoken')
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)))
+ ->execute();
+
+ $data = $result->fetch();
+ $result->closeCursor();
+ if ($data === false) {
+ throw new DoesNotExistException('token does not exist');
+ }
+ return PublicKeyToken::fromRow($data);
+ }
+
+ /**
+ * Get all tokens of a user
+ *
+ * The provider may limit the number of result rows in case of an abuse
+ * where a high number of (session) tokens is generated
+ *
+ * @param string $uid
+ * @return PublicKeyToken[]
+ */
+ public function getTokenByUser(string $uid): array {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $qb->select('*')
+ ->from('authtoken')
+ ->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)))
+ ->setMaxResults(1000);
+ $result = $qb->execute();
+ $data = $result->fetchAll();
+ $result->closeCursor();
+
+ $entities = array_map(function ($row) {
+ return PublicKeyToken::fromRow($row);
+ }, $data);
+
+ return $entities;
+ }
+
+ public function deleteById(string $uid, int $id) {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $qb->delete('authtoken')
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
+ ->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($uid)))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)));
+ $qb->execute();
+ }
+
+ /**
+ * delete all auth token which belong to a specific client if the client was deleted
+ *
+ * @param string $name
+ */
+ public function deleteByName(string $name) {
+ $qb = $this->db->getQueryBuilder();
+ $qb->delete('authtoken')
+ ->where($qb->expr()->eq('name', $qb->createNamedParameter($name), IQueryBuilder::PARAM_STR))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)));
+ $qb->execute();
+ }
+
+ public function deleteTempToken(PublicKeyToken $except) {
+ $qb = $this->db->getQueryBuilder();
+
+ $qb->delete('authtoken')
+ ->where($qb->expr()->eq('type', $qb->createNamedParameter(IToken::TEMPORARY_TOKEN)))
+ ->andWhere($qb->expr()->neq('id', $qb->createNamedParameter($except->getId())))
+ ->andWhere($qb->expr()->eq('version', $qb->createNamedParameter(PublicKeyToken::VERSION, IQueryBuilder::PARAM_INT)));
+
+ $qb->execute();
+ }
+}
diff --git a/lib/private/Authentication/Token/PublicKeyTokenProvider.php b/lib/private/Authentication/Token/PublicKeyTokenProvider.php
new file mode 100644
index 00000000000..f6a6fc3455f
--- /dev/null
+++ b/lib/private/Authentication/Token/PublicKeyTokenProvider.php
@@ -0,0 +1,320 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright 2018, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @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\Authentication\Token;
+
+use OC\Authentication\Exceptions\InvalidTokenException;
+use OC\Authentication\Exceptions\PasswordlessTokenException;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\IConfig;
+use OCP\ILogger;
+use OCP\Security\ICrypto;
+
+class PublicKeyTokenProvider implements IProvider {
+ /** @var PublicKeyTokenMapper */
+ private $mapper;
+
+ /** @var ICrypto */
+ private $crypto;
+
+ /** @var IConfig */
+ private $config;
+
+ /** @var ILogger $logger */
+ private $logger;
+
+ /** @var ITimeFactory $time */
+ private $time;
+
+ public function __construct(PublicKeyTokenMapper $mapper,
+ ICrypto $crypto,
+ IConfig $config,
+ ILogger $logger,
+ ITimeFactory $time) {
+ $this->mapper = $mapper;
+ $this->crypto = $crypto;
+ $this->config = $config;
+ $this->logger = $logger;
+ $this->time = $time;
+ }
+
+ public function generateToken(string $token,
+ string $uid,
+ string $loginName,
+ $password,
+ string $name,
+ int $type = IToken::TEMPORARY_TOKEN,
+ int $remember = IToken::DO_NOT_REMEMBER): IToken {
+ $dbToken = $this->newToken($token, $uid, $loginName, $password, $name, $type, $remember);
+
+ $this->mapper->insert($dbToken);
+
+ return $dbToken;
+ }
+
+ public function getToken(string $tokenId): IToken {
+ try {
+ $token = $this->mapper->getToken($this->hashToken($tokenId));
+ } catch (DoesNotExistException $ex) {
+ throw new InvalidTokenException();
+ }
+
+ if ($token->getExpires() !== null && $token->getExpires() < $this->time->getTime()) {
+ throw new ExpiredTokenException($token);
+ }
+
+ return $token;
+ }
+
+ public function getTokenById(int $tokenId): IToken {
+ try {
+ $token = $this->mapper->getTokenById($tokenId);
+ } catch (DoesNotExistException $ex) {
+ throw new InvalidTokenException();
+ }
+
+ if ($token->getExpires() !== null && $token->getExpires() < $this->time->getTime()) {
+ throw new ExpiredTokenException($token);
+ }
+
+ return $token;
+ }
+
+ public function renewSessionToken(string $oldSessionId, string $sessionId) {
+ $token = $this->getToken($oldSessionId);
+
+ if (!($token instanceof PublicKeyToken)) {
+ throw new InvalidTokenException();
+ }
+
+ $password = null;
+ if (!is_null($token->getPassword())) {
+ $privateKey = $this->decrypt($token->getPrivateKey(), $oldSessionId);
+ $password = $this->decryptPassword($token->getPassword(), $privateKey);
+ }
+
+ $this->generateToken(
+ $sessionId,
+ $token->getUID(),
+ $token->getLoginName(),
+ $password,
+ $token->getName(),
+ IToken::TEMPORARY_TOKEN,
+ $token->getRemember()
+ );
+
+ $this->mapper->delete($token);
+ }
+
+ public function invalidateToken(string $token) {
+ $this->mapper->invalidate($this->hashToken($token));
+ }
+
+ public function invalidateTokenById(string $uid, int $id) {
+ $this->mapper->deleteById($uid, $id);
+ }
+
+ public function invalidateOldTokens() {
+ $olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24);
+ $this->logger->debug('Invalidating session tokens older than ' . date('c', $olderThan), ['app' => 'cron']);
+ $this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER);
+ $rememberThreshold = $this->time->getTime() - (int) $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
+ $this->logger->debug('Invalidating remembered session tokens older than ' . date('c', $rememberThreshold), ['app' => 'cron']);
+ $this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER);
+ }
+
+ public function updateToken(IToken $token) {
+ if (!($token instanceof PublicKeyToken)) {
+ throw new InvalidTokenException();
+ }
+ $this->mapper->update($token);
+ }
+
+ public function updateTokenActivity(IToken $token) {
+ if (!($token instanceof PublicKeyToken)) {
+ throw new InvalidTokenException();
+ }
+ /** @var DefaultToken $token */
+ $now = $this->time->getTime();
+ if ($token->getLastActivity() < ($now - 60)) {
+ // Update token only once per minute
+ $token->setLastActivity($now);
+ $this->mapper->update($token);
+ }
+ }
+
+ public function getTokenByUser(string $uid): array {
+ return $this->mapper->getTokenByUser($uid);
+ }
+
+ public function getPassword(IToken $token, string $tokenId): string {
+ if (!($token instanceof PublicKeyToken)) {
+ throw new InvalidTokenException();
+ }
+
+ if ($token->getPassword() === null) {
+ throw new PasswordlessTokenException();
+ }
+
+ // Decrypt private key with tokenId
+ $privateKey = $this->decrypt($token->getPrivateKey(), $tokenId);
+
+ // Decrypt password with private key
+ return $this->decryptPassword($token->getPassword(), $privateKey);
+ }
+
+ public function setPassword(IToken $token, string $tokenId, string $password) {
+ if (!($token instanceof PublicKeyToken)) {
+ throw new InvalidTokenException();
+ }
+
+ // When changing passwords all temp tokens are deleted
+ $this->mapper->deleteTempToken($token);
+
+ // Update the password for all tokens
+ $tokens = $this->mapper->getTokenByUser($token->getUID());
+ foreach ($tokens as $t) {
+ $publicKey = $t->getPublicKey();
+ $t->setPassword($this->encryptPassword($password, $publicKey));
+ $this->updateToken($t);
+ }
+ }
+
+ public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
+ if (!($token instanceof PublicKeyToken)) {
+ throw new InvalidTokenException();
+ }
+
+ // Decrypt private key with oldTokenId
+ $privateKey = $this->decrypt($token->getPrivateKey(), $oldTokenId);
+ // Encrypt with the new token
+ $token->setPrivateKey($this->encrypt($privateKey, $newTokenId));
+
+ $token->setToken($this->hashToken($newTokenId));
+ $this->updateToken($token);
+
+ return $token;
+ }
+
+ private function encrypt(string $plaintext, string $token): string {
+ $secret = $this->config->getSystemValue('secret');
+ return $this->crypto->encrypt($plaintext, $token . $secret);
+ }
+
+ /**
+ * @throws InvalidTokenException
+ */
+ private function decrypt(string $cipherText, string $token): string {
+ $secret = $this->config->getSystemValue('secret');
+ try {
+ return $this->crypto->decrypt($cipherText, $token . $secret);
+ } catch (\Exception $ex) {
+ // Delete the invalid token
+ $this->invalidateToken($token);
+ throw new InvalidTokenException();
+ }
+ }
+
+ private function encryptPassword(string $password, string $publicKey): string {
+ openssl_public_encrypt($password, $encryptedPassword, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);
+ $encryptedPassword = base64_encode($encryptedPassword);
+
+ return $encryptedPassword;
+ }
+
+ private function decryptPassword(string $encryptedPassword, string $privateKey): string {
+ $encryptedPassword = base64_decode($encryptedPassword);
+ openssl_private_decrypt($encryptedPassword, $password, $privateKey, OPENSSL_PKCS1_OAEP_PADDING);
+
+ return $password;
+ }
+
+ private function hashToken(string $token): string {
+ $secret = $this->config->getSystemValue('secret');
+ return hash('sha512', $token . $secret);
+ }
+
+ /**
+ * Convert a DefaultToken to a publicKeyToken
+ * This will also be updated directly in the Database
+ */
+ public function convertToken(DefaultToken $defaultToken, string $token, $password): PublicKeyToken {
+ $pkToken = $this->newToken(
+ $token,
+ $defaultToken->getUID(),
+ $defaultToken->getLoginName(),
+ $password,
+ $defaultToken->getName(),
+ $defaultToken->getType(),
+ $defaultToken->getRemember()
+ );
+
+ $pkToken->setExpires($defaultToken->getExpires());
+ $pkToken->setId($defaultToken->getId());
+
+ return $this->mapper->update($pkToken);
+ }
+
+ private function newToken(string $token,
+ string $uid,
+ string $loginName,
+ $password,
+ string $name,
+ int $type,
+ int $remember): PublicKeyToken {
+ $dbToken = new PublicKeyToken();
+ $dbToken->setUid($uid);
+ $dbToken->setLoginName($loginName);
+
+ $config = [
+ 'digest_alg' => 'sha512',
+ 'private_key_bits' => 2048,
+ ];
+
+ // Generate new key
+ $res = openssl_pkey_new($config);
+ openssl_pkey_export($res, $privateKey);
+
+ // Extract the public key from $res to $pubKey
+ $publicKey = openssl_pkey_get_details($res);
+ $publicKey = $publicKey['key'];
+
+ $dbToken->setPublicKey($publicKey);
+ $dbToken->setPrivateKey($this->encrypt($privateKey, $token));
+
+ if (!is_null($password)) {
+ $dbToken->setPassword($this->encryptPassword($password, $publicKey));
+ }
+
+ $dbToken->setName($name);
+ $dbToken->setToken($this->hashToken($token));
+ $dbToken->setType($type);
+ $dbToken->setRemember($remember);
+ $dbToken->setLastActivity($this->time->getTime());
+ $dbToken->setLastCheck($this->time->getTime());
+ $dbToken->setVersion(PublicKeyToken::VERSION);
+
+ return $dbToken;
+ }
+}
diff --git a/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php b/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php
new file mode 100644
index 00000000000..5b3f2849433
--- /dev/null
+++ b/lib/private/Authentication/TwoFactorAuth/Db/ProviderUserAssignmentDao.php
@@ -0,0 +1,86 @@
+<?php
+
+declare(strict_types = 1);
+
+/**
+ * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @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\Authentication\TwoFactorAuth\Db;
+
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+/**
+ * Data access object to query and assign (provider_id, uid, enabled) tuples of
+ * 2FA providers
+ */
+class ProviderUserAssignmentDao {
+
+ const TABLE_NAME = 'twofactor_providers';
+
+ /** @var IDBConnection */
+ private $conn;
+
+ public function __construct(IDBConnection $dbConn) {
+ $this->conn = $dbConn;
+ }
+
+ /**
+ * Get all assigned provider IDs for the given user ID
+ *
+ * @return string[] where the array key is the provider ID (string) and the
+ * value is the enabled state (bool)
+ */
+ public function getState(string $uid): array {
+ $qb = $this->conn->getQueryBuilder();
+
+ $query = $qb->select('provider_id', 'enabled')
+ ->from(self::TABLE_NAME)
+ ->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid)));
+ $result = $query->execute();
+ $providers = [];
+ foreach ($result->fetchAll() as $row) {
+ $providers[$row['provider_id']] = 1 === (int) $row['enabled'];
+ }
+ $result->closeCursor();
+
+ return $providers;
+ }
+
+ /**
+ * Persist a new/updated (provider_id, uid, enabled) tuple
+ */
+ public function persist(string $providerId, string $uid, int $enabled) {
+ $qb = $this->conn->getQueryBuilder();
+
+ // TODO: concurrency? What if (providerId, uid) private key is inserted
+ // twice at the same time?
+ $query = $qb->insert(self::TABLE_NAME)->values([
+ 'provider_id' => $qb->createNamedParameter($providerId),
+ 'uid' => $qb->createNamedParameter($uid),
+ 'enabled' => $qb->createNamedParameter($enabled, IQueryBuilder::PARAM_INT),
+ ]);
+
+ $query->execute();
+ }
+
+}
diff --git a/lib/private/Authentication/TwoFactorAuth/Manager.php b/lib/private/Authentication/TwoFactorAuth/Manager.php
index 933b86ffda5..0837ec339a5 100644
--- a/lib/private/Authentication/TwoFactorAuth/Manager.php
+++ b/lib/private/Authentication/TwoFactorAuth/Manager.php
@@ -1,5 +1,6 @@
<?php
-declare(strict_types=1);
+
+declare(strict_types = 1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -28,15 +29,12 @@ namespace OC\Authentication\TwoFactorAuth;
use BadMethodCallException;
use Exception;
-use OC;
-use OC\App\AppManager;
-use OC_App;
use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Token\IProvider as TokenProvider;
use OCP\Activity\IManager;
-use OCP\AppFramework\QueryException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Authentication\TwoFactorAuth\IProvider;
+use OCP\Authentication\TwoFactorAuth\IRegistry;
use OCP\IConfig;
use OCP\ILogger;
use OCP\ISession;
@@ -48,12 +46,13 @@ class Manager {
const SESSION_UID_KEY = 'two_factor_auth_uid';
const SESSION_UID_DONE = 'two_factor_auth_passed';
- const BACKUP_CODES_APP_ID = 'twofactor_backupcodes';
- const BACKUP_CODES_PROVIDER_ID = 'backup_codes';
const REMEMBER_LOGIN = 'two_factor_remember_login';
- /** @var AppManager */
- private $appManager;
+ /** @var ProviderLoader */
+ private $providerLoader;
+
+ /** @var IRegistry */
+ private $providerRegistry;
/** @var ISession */
private $session;
@@ -76,25 +75,11 @@ class Manager {
/** @var EventDispatcherInterface */
private $dispatcher;
- /**
- * @param AppManager $appManager
- * @param ISession $session
- * @param IConfig $config
- * @param IManager $activityManager
- * @param ILogger $logger
- * @param TokenProvider $tokenProvider
- * @param ITimeFactory $timeFactory
- * @param EventDispatcherInterface $eventDispatcher
- */
- public function __construct(AppManager $appManager,
- ISession $session,
- IConfig $config,
- IManager $activityManager,
- ILogger $logger,
- TokenProvider $tokenProvider,
- ITimeFactory $timeFactory,
- EventDispatcherInterface $eventDispatcher) {
- $this->appManager = $appManager;
+ public function __construct(ProviderLoader $providerLoader,
+ IRegistry $providerRegistry, ISession $session, IConfig $config,
+ IManager $activityManager, ILogger $logger, TokenProvider $tokenProvider,
+ ITimeFactory $timeFactory, EventDispatcherInterface $eventDispatcher) {
+ $this->providerLoader = $providerLoader;
$this->session = $session;
$this->config = $config;
$this->activityManager = $activityManager;
@@ -102,6 +87,7 @@ class Manager {
$this->tokenProvider = $tokenProvider;
$this->timeFactory = $timeFactory;
$this->dispatcher = $eventDispatcher;
+ $this->providerRegistry = $providerRegistry;
}
/**
@@ -112,7 +98,15 @@ class Manager {
*/
public function isTwoFactorAuthenticated(IUser $user): bool {
$twoFactorEnabled = ((int) $this->config->getUserValue($user->getUID(), 'core', 'two_factor_auth_disabled', 0)) === 0;
- return $twoFactorEnabled && \count($this->getProviders($user)) > 0;
+
+ if (!$twoFactorEnabled) {
+ return false;
+ }
+
+ $providerStates = $this->providerRegistry->getProviderStates($user);
+ $enabled = array_filter($providerStates);
+
+ return $twoFactorEnabled && !empty($enabled);
}
/**
@@ -141,71 +135,96 @@ class Manager {
* @return IProvider|null
*/
public function getProvider(IUser $user, string $challengeProviderId) {
- $providers = $this->getProviders($user, true);
+ $providers = $this->getProviderSet($user)->getProviders();
return $providers[$challengeProviderId] ?? null;
}
/**
+ * Check if the persistant mapping of enabled/disabled state of each available
+ * provider is missing an entry and add it to the registry in that case.
+ *
+ * @todo remove in Nextcloud 17 as by then all providers should have been updated
+ *
+ * @param string[] $providerStates
+ * @param IProvider[] $providers
* @param IUser $user
- * @return IProvider|null the backup provider, if enabled for the given user
+ * @return string[] the updated $providerStates variable
*/
- public function getBackupProvider(IUser $user) {
- $providers = $this->getProviders($user, true);
- if (!isset($providers[self::BACKUP_CODES_PROVIDER_ID])) {
- return null;
+ private function fixMissingProviderStates(array $providerStates,
+ array $providers, IUser $user): array {
+
+ foreach ($providers as $provider) {
+ if (isset($providerStates[$provider->getId()])) {
+ // All good
+ continue;
+ }
+
+ $enabled = $provider->isTwoFactorAuthEnabledForUser($user);
+ if ($enabled) {
+ $this->providerRegistry->enableProviderFor($provider, $user);
+ } else {
+ $this->providerRegistry->disableProviderFor($provider, $user);
+ }
+ $providerStates[$provider->getId()] = $enabled;
}
- return $providers[self::BACKUP_CODES_PROVIDER_ID];
+
+ return $providerStates;
}
/**
- * Get the list of 2FA providers for the given user
- *
- * @param IUser $user
- * @param bool $includeBackupApp
- * @return IProvider[]
- * @throws Exception
+ * @param array $states
+ * @param IProvider $providers
*/
- public function getProviders(IUser $user, bool $includeBackupApp = false): array {
- $allApps = $this->appManager->getEnabledAppsForUser($user);
- $providers = [];
+ private function isProviderMissing(array $states, array $providers): bool {
+ $indexed = [];
+ foreach ($providers as $provider) {
+ $indexed[$provider->getId()] = $provider;
+ }
- foreach ($allApps as $appId) {
- if (!$includeBackupApp && $appId === self::BACKUP_CODES_APP_ID) {
+ $missing = [];
+ foreach ($states as $providerId => $enabled) {
+ if (!$enabled) {
+ // Don't care
continue;
}
- $info = $this->appManager->getAppInfo($appId);
- if (isset($info['two-factor-providers'])) {
- /** @var string[] $providerClasses */
- $providerClasses = $info['two-factor-providers'];
- foreach ($providerClasses as $class) {
- try {
- $this->loadTwoFactorApp($appId);
- $provider = OC::$server->query($class);
- $providers[$provider->getId()] = $provider;
- } catch (QueryException $exc) {
- // Provider class can not be resolved
- throw new Exception("Could not load two-factor auth provider $class");
- }
- }
+ if (!isset($indexed[$providerId])) {
+ $missing[] = $providerId;
+ $this->logger->alert("two-factor auth provider '$providerId' failed to load",
+ [
+ 'app' => 'core',
+ ]);
}
}
- return array_filter($providers, function ($provider) use ($user) {
- /* @var $provider IProvider */
- return $provider->isTwoFactorAuthEnabledForUser($user);
- });
+ if (!empty($missing)) {
+ // There was at least one provider missing
+ $this->logger->alert(count($missing) . " two-factor auth providers failed to load", ['app' => 'core']);
+
+ return true;
+ }
+
+ // If we reach this, there was not a single provider missing
+ return false;
}
/**
- * Load an app by ID if it has not been loaded yet
+ * Get the list of 2FA providers for the given user
*
- * @param string $appId
+ * @param IUser $user
+ * @throws Exception
*/
- protected function loadTwoFactorApp(string $appId) {
- if (!OC_App::isAppLoaded($appId)) {
- OC_App::loadApp($appId);
- }
+ public function getProviderSet(IUser $user): ProviderSet {
+ $providerStates = $this->providerRegistry->getProviderStates($user);
+ $providers = $this->providerLoader->getProviders($user);
+
+ $fixedStates = $this->fixMissingProviderStates($providerStates, $providers, $user);
+ $isProviderMissing = $this->isProviderMissing($fixedStates, $providers);
+
+ $enabled = array_filter($providers, function (IProvider $provider) use ($fixedStates) {
+ return $fixedStates[$provider->getId()];
+ });
+ return new ProviderSet($enabled, $isProviderMissing);
}
/**
@@ -272,7 +291,7 @@ class Manager {
try {
$this->activityManager->publish($activity);
} catch (BadMethodCallException $e) {
- $this->logger->warning('could not publish backup code creation activity', ['app' => 'core']);
+ $this->logger->warning('could not publish activity', ['app' => 'core']);
$this->logger->logException($e, ['app' => 'core']);
}
}
diff --git a/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php b/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php
new file mode 100644
index 00000000000..f735bad1695
--- /dev/null
+++ b/lib/private/Authentication/TwoFactorAuth/ProviderLoader.php
@@ -0,0 +1,89 @@
+<?php
+declare(strict_types=1);
+
+/**
+ * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @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\Authentication\TwoFactorAuth;
+
+use Exception;
+use OC;
+use OC_App;
+use OCP\App\IAppManager;
+use OCP\AppFramework\QueryException;
+use OCP\Authentication\TwoFactorAuth\IProvider;
+use OCP\IUser;
+
+class ProviderLoader {
+
+ const BACKUP_CODES_APP_ID = 'twofactor_backupcodes';
+
+ /** @var IAppManager */
+ private $appManager;
+
+ public function __construct(IAppManager $appManager) {
+ $this->appManager = $appManager;
+ }
+
+ /**
+ * Get the list of 2FA providers for the given user
+ *
+ * @return IProvider[]
+ * @throws Exception
+ */
+ public function getProviders(IUser $user): array {
+ $allApps = $this->appManager->getEnabledAppsForUser($user);
+ $providers = [];
+
+ foreach ($allApps as $appId) {
+ $info = $this->appManager->getAppInfo($appId);
+ if (isset($info['two-factor-providers'])) {
+ /** @var string[] $providerClasses */
+ $providerClasses = $info['two-factor-providers'];
+ foreach ($providerClasses as $class) {
+ try {
+ $this->loadTwoFactorApp($appId);
+ $provider = OC::$server->query($class);
+ $providers[$provider->getId()] = $provider;
+ } catch (QueryException $exc) {
+ // Provider class can not be resolved
+ throw new Exception("Could not load two-factor auth provider $class");
+ }
+ }
+ }
+ }
+
+ return $providers;
+ }
+
+ /**
+ * Load an app by ID if it has not been loaded yet
+ *
+ * @param string $appId
+ */
+ protected function loadTwoFactorApp(string $appId) {
+ if (!OC_App::isAppLoaded($appId)) {
+ OC_App::loadApp($appId);
+ }
+ }
+
+}
diff --git a/lib/private/Authentication/TwoFactorAuth/ProviderSet.php b/lib/private/Authentication/TwoFactorAuth/ProviderSet.php
new file mode 100644
index 00000000000..bbb9467798b
--- /dev/null
+++ b/lib/private/Authentication/TwoFactorAuth/ProviderSet.php
@@ -0,0 +1,72 @@
+<?php
+declare(strict_types=1);
+
+/**
+ * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @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\Authentication\TwoFactorAuth;
+
+use OCP\Authentication\TwoFactorAuth\IProvider;
+
+/**
+ * Contains all two-factor provider information for the two-factor login challenge
+ */
+class ProviderSet {
+
+ /** @var IProvider */
+ private $providers;
+
+ /** @var bool */
+ private $providerMissing;
+
+ /**
+ * @param IProvider[] $providers
+ * @param bool $providerMissing
+ */
+ public function __construct(array $providers, bool $providerMissing) {
+ $this->providers = [];
+ foreach ($providers as $provider) {
+ $this->providers[$provider->getId()] = $provider;
+ }
+ $this->providerMissing = $providerMissing;
+ }
+
+ /**
+ * @param string $providerId
+ * @return IProvider|null
+ */
+ public function getProvider(string $providerId) {
+ return $this->providers[$providerId] ?? null;
+ }
+
+ /**
+ * @return IProvider[]
+ */
+ public function getProviders(): array {
+ return $this->providers;
+ }
+
+ public function isProviderMissing(): bool {
+ return $this->providerMissing;
+ }
+
+}
diff --git a/lib/private/Authentication/TwoFactorAuth/Registry.php b/lib/private/Authentication/TwoFactorAuth/Registry.php
new file mode 100644
index 00000000000..0cfb052440e
--- /dev/null
+++ b/lib/private/Authentication/TwoFactorAuth/Registry.php
@@ -0,0 +1,55 @@
+<?php
+
+declare(strict_types = 1);
+
+/**
+ * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @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\Authentication\TwoFactorAuth;
+
+use OC\Authentication\TwoFactorAuth\Db\ProviderUserAssignmentDao;
+use OCP\Authentication\TwoFactorAuth\IProvider;
+use OCP\Authentication\TwoFactorAuth\IRegistry;
+use OCP\IUser;
+
+class Registry implements IRegistry {
+
+ /** @var ProviderUserAssignmentDao */
+ private $assignmentDao;
+
+ public function __construct(ProviderUserAssignmentDao $assignmentDao) {
+ $this->assignmentDao = $assignmentDao;
+ }
+
+ public function getProviderStates(IUser $user): array {
+ return $this->assignmentDao->getState($user->getUID());
+ }
+
+ public function enableProviderFor(IProvider $provider, IUser $user) {
+ $this->assignmentDao->persist($provider->getId(), $user->getUID(), 1);
+ }
+
+ public function disableProviderFor(IProvider $provider, IUser $user) {
+ $this->assignmentDao->persist($provider->getId(), $user->getUID(), 0);
+ }
+
+}
diff --git a/lib/private/Avatar.php b/lib/private/Avatar.php
index 4cacc801689..9dbeb4ac745 100644
--- a/lib/private/Avatar.php
+++ b/lib/private/Avatar.php
@@ -1,6 +1,7 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @copyright 2018 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Christopher Schäpers <kondou@ts.unde.re>
@@ -10,6 +11,7 @@
* @author Robin Appelman <robin@icewind.nl>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0
*
@@ -29,7 +31,6 @@
namespace OC;
-use OC\User\User;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
@@ -38,8 +39,10 @@ use OCP\IAvatar;
use OCP\IConfig;
use OCP\IImage;
use OCP\IL10N;
-use OC_Image;
use OCP\ILogger;
+use OC\User\User;
+use OC_Image;
+use Imagick;
/**
* This class gets and sets users avatars.
@@ -58,6 +61,19 @@ class Avatar implements IAvatar {
private $config;
/**
+ * https://github.com/sebdesign/cap-height -- for 500px height
+ * Open Sans cap-height is 0.72 and we want a 200px caps height size (0.4 letter-to-total-height ratio, 500*0.4=200). 200/0.72 = 278px.
+ * Since we start from the baseline (text-anchor) we need to shift the y axis by 100px (half the caps height): 500/2+100=350
+ *
+ * @var string
+ */
+ private $svgTemplate = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+ <svg width="{size}" height="{size}" version="1.1" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
+ <rect width="100%" height="100%" fill="#{fill}"></rect>
+ <text x="50%" y="350" style="font-weight:600;font-size:278px;font-family:\'Open Sans\';text-anchor:middle;fill:#fff">{letter}</text>
+ </svg>';
+
+ /**
* constructor
*
* @param ISimpleFolder $folder The folder where the avatars are
@@ -67,10 +83,10 @@ class Avatar implements IAvatar {
* @param IConfig $config
*/
public function __construct(ISimpleFolder $folder,
- IL10N $l,
- $user,
- ILogger $logger,
- IConfig $config) {
+ IL10N $l,
+ $user,
+ ILogger $logger,
+ IConfig $config) {
$this->folder = $folder;
$this->l = $l;
$this->user = $user;
@@ -81,7 +97,7 @@ class Avatar implements IAvatar {
/**
* @inheritdoc
*/
- public function get ($size = 64) {
+ public function get($size = 64) {
try {
$file = $this->getFile($size);
} catch (NotFoundException $e) {
@@ -110,17 +126,17 @@ class Avatar implements IAvatar {
* @throws \Exception if the provided image is not valid
* @throws NotSquareException if the image is not square
* @return void
- */
- public function set ($data) {
+ */
+ public function set($data) {
- if($data instanceOf IImage) {
+ if ($data instanceof IImage) {
$img = $data;
$data = $img->data();
} else {
$img = new OC_Image();
if (is_resource($data) && get_resource_type($data) === "gd") {
$img->setResource($data);
- } elseif(is_resource($data)) {
+ } elseif (is_resource($data)) {
$img->loadFromFileHandle($data);
} else {
try {
@@ -153,7 +169,7 @@ class Avatar implements IAvatar {
}
$this->remove();
- $file = $this->folder->newFile('avatar.'.$type);
+ $file = $this->folder->newFile('avatar.' . $type);
$file->putContent($data);
try {
@@ -164,17 +180,17 @@ class Avatar implements IAvatar {
//
}
$this->user->triggerChange('avatar', $file);
- }
+ }
/**
* remove the users avatar
* @return void
- */
- public function remove () {
+ */
+ public function remove() {
$avatars = $this->folder->getDirectoryListing();
$this->config->setUserValue($this->user->getUID(), 'avatar', 'version',
- (int)$this->config->getUserValue($this->user->getUID(), 'avatar', 'version', 0) + 1);
+ (int) $this->config->getUserValue($this->user->getUID(), 'avatar', 'version', 0) + 1);
foreach ($avatars as $avatar) {
$avatar->delete();
@@ -190,7 +206,9 @@ class Avatar implements IAvatar {
try {
$ext = $this->getExtension();
} catch (NotFoundException $e) {
- $data = $this->generateAvatar($this->user->getDisplayName(), 1024);
+ if (!$data = $this->generateAvatarFromSvg(1024)) {
+ $data = $this->generateAvatar($this->user->getDisplayName(), 1024);
+ }
$avatar = $this->folder->newFile('avatar.png');
$avatar->putContent($data);
$ext = 'png';
@@ -213,7 +231,9 @@ class Avatar implements IAvatar {
}
if ($this->folder->fileExists('generated')) {
- $data = $this->generateAvatar($this->user->getDisplayName(), $size);
+ if (!$data = $this->generateAvatarFromSvg($size)) {
+ $data = $this->generateAvatar($this->user->getDisplayName(), $size);
+ }
} else {
$avatar = new OC_Image();
@@ -234,7 +254,7 @@ class Avatar implements IAvatar {
}
- if($this->config->getUserValue($this->user->getUID(), 'avatar', 'generated', null) === null) {
+ if ($this->config->getUserValue($this->user->getUID(), 'avatar', 'generated', null) === null) {
$generated = $this->folder->fileExists('generated') ? 'true' : 'false';
$this->config->setUserValue($this->user->getUID(), 'avatar', 'generated', $generated);
}
@@ -256,30 +276,74 @@ class Avatar implements IAvatar {
}
throw new NotFoundException;
}
+
+ /**
+ * {size} = 500
+ * {fill} = hex color to fill
+ * {letter} = Letter to display
+ *
+ * Generate SVG avatar
+ * @return string
+ *
+ */
+ private function getAvatarVector(int $size): string {
+ $userDisplayName = $this->user->getDisplayName();
+
+ $bgRGB = $this->avatarBackgroundColor($userDisplayName);
+ $bgHEX = sprintf("%02x%02x%02x", $bgRGB->r, $bgRGB->g, $bgRGB->b);
+ $letter = mb_strtoupper(mb_substr($userDisplayName, 0, 1), 'UTF-8');
+
+ $toReplace = ['{size}', '{fill}', '{letter}'];
+ return str_replace($toReplace, [$size, $bgHEX, $letter], $this->svgTemplate);
+ }
+
+ /**
+ * Generate png avatar from svg with Imagick
+ *
+ * @param int $size
+ * @return string|boolean
+ */
+ private function generateAvatarFromSvg(int $size) {
+ if (!extension_loaded('imagick')) {
+ return false;
+ }
+ try {
+ $font = __DIR__ . '/../../core/fonts/OpenSans-Semibold.ttf';
+ $svg = $this->getAvatarVector($size);
+ $avatar = new Imagick();
+ $avatar->setFont($font);
+ $avatar->readImageBlob($svg);
+ $avatar->setImageFormat('png');
+ $image = new OC_Image();
+ $image->loadFromData($avatar);
+ return $image->data();
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
/**
+ * Generate png avatar with GD
+ *
* @param string $userDisplayName
* @param int $size
* @return string
*/
private function generateAvatar($userDisplayName, $size) {
- $text = strtoupper($userDisplayName[0]);
+ $text = mb_strtoupper(mb_substr($userDisplayName, 0, 1), 'UTF-8');
$backgroundColor = $this->avatarBackgroundColor($userDisplayName);
$im = imagecreatetruecolor($size, $size);
- $background = imagecolorallocate($im, $backgroundColor[0], $backgroundColor[1], $backgroundColor[2]);
+ $background = imagecolorallocate($im, $backgroundColor->r, $backgroundColor->g, $backgroundColor->b);
$white = imagecolorallocate($im, 255, 255, 255);
imagefilledrectangle($im, 0, 0, $size, $size, $background);
- $font = __DIR__ . '/../../core/fonts/OpenSans-Semibold.woff';
+ $font = __DIR__ . '/../../core/fonts/OpenSans-Semibold.ttf';
$fontSize = $size * 0.4;
- $box = imagettfbbox($fontSize, 0, $font, $text);
- $x = ($size - ($box[2] - $box[0])) / 2;
- $y = ($size - ($box[1] - $box[7])) / 2;
- $x += 1;
- $y -= $box[7];
+ list($x, $y) = $this->imageTTFCenter($im, $text, $font, $fontSize);
+
imagettftext($im, $fontSize, 0, $x, $y, $white, $font, $text);
ob_start();
@@ -291,131 +355,121 @@ class Avatar implements IAvatar {
}
/**
- * @param int $r
- * @param int $g
- * @param int $b
- * @return double[] Array containing h s l in [0, 1] range
+ * Calculate real image ttf center
+ *
+ * @param resource $image
+ * @param string $text text string
+ * @param string $font font path
+ * @param int $size font size
+ * @param int $angle
+ * @return Array
*/
- private function rgbToHsl($r, $g, $b) {
- $r /= 255.0;
- $g /= 255.0;
- $b /= 255.0;
+ protected function imageTTFCenter($image, string $text, string $font, int $size, $angle = 0): array {
+ // Image width & height
+ $xi = imagesx($image);
+ $yi = imagesy($image);
- $max = max($r, $g, $b);
- $min = min($r, $g, $b);
+ // bounding box
+ $box = imagettfbbox($size, $angle, $font, $text);
+ // imagettfbbox can return negative int
+ $xr = abs(max($box[2], $box[4]));
+ $yr = abs(max($box[5], $box[7]));
- $h = ($max + $min) / 2.0;
- $l = ($max + $min) / 2.0;
-
- if($max === $min) {
- $h = $s = 0; // Achromatic
- } else {
- $d = $max - $min;
- $s = $l > 0.5 ? $d / (2 - $max - $min) : $d / ($max + $min);
- switch($max) {
- case $r:
- $h = ($g - $b) / $d + ($g < $b ? 6 : 0);
- break;
- case $g:
- $h = ($b - $r) / $d + 2.0;
- break;
- case $b:
- $h = ($r - $g) / $d + 4.0;
- break;
- }
- $h /= 6.0;
- }
- return [$h, $s, $l];
+ // calculate bottom left placement
+ $x = intval(($xi - $xr) / 2);
+ $y = intval(($yi + $yr) / 2);
+ return array($x, $y);
}
/**
- * @param string $text
- * @return int[] Array containting r g b in the range [0, 255]
+ * Calculate steps between two Colors
+ * @param object Color $steps start color
+ * @param object Color $ends end color
+ * @return array [r,g,b] steps for each color to go from $steps to $ends
*/
- private function avatarBackgroundColor($text) {
- $hash = preg_replace('/[^0-9a-f]+/', '', $text);
-
- $hash = md5($hash);
- $hashChars = str_split($hash);
-
+ private function stepCalc($steps, $ends) {
+ $step = array();
+ $step[0] = ($ends[1]->r - $ends[0]->r) / $steps;
+ $step[1] = ($ends[1]->g - $ends[0]->g) / $steps;
+ $step[2] = ($ends[1]->b - $ends[0]->b) / $steps;
+ return $step;
+ }
- // Init vars
- $result = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'];
- $rgb = [0, 0, 0];
- $sat = 0.70;
- $lum = 0.68;
- $modulo = 16;
+ /**
+ * Convert a string to an integer evenly
+ * @param string $hash the text to parse
+ * @param int $maximum the maximum range
+ * @return int between 0 and $maximum
+ */
+ private function mixPalette($steps, $color1, $color2) {
+ $count = $steps + 1;
+ $palette = array($color1);
+ $step = $this->stepCalc($steps, [$color1, $color2]);
+ for ($i = 1; $i < $steps; $i++) {
+ $r = intval($color1->r + ($step[0] * $i));
+ $g = intval($color1->g + ($step[1] * $i));
+ $b = intval($color1->b + ($step[2] * $i));
+ $palette[] = new Color($r, $g, $b);
+ }
+ return $palette;
+ }
+ /**
+ * Convert a string to an integer evenly
+ * @param string $hash the text to parse
+ * @param int $maximum the maximum range
+ * @return int between 0 and $maximum
+ */
+ private function hashToInt($hash, $maximum) {
+ $final = 0;
+ $result = array();
// Splitting evenly the string
- foreach($hashChars as $i => $char) {
- $result[$i % $modulo] .= intval($char, 16);
+ for ($i = 0; $i < strlen($hash); $i++) {
+ // chars in md5 goes up to f, hex:16
+ $result[] = intval(substr($hash, $i, 1), 16) % 16;
+ }
+ // Adds up all results
+ foreach ($result as $value) {
+ $final += $value;
}
+ // chars in md5 goes up to f, hex:16
+ return intval($final % $maximum);
+ }
- // Converting our data into a usable rgb format
- // Start at 1 because 16%3=1 but 15%3=0 and makes the repartition even
- for($count = 1; $count < $modulo; $count++) {
- $rgb[$count%3] += (int)$result[$count];
+ /**
+ * @param string $hash
+ * @return Color Object containting r g b int in the range [0, 255]
+ */
+ public function avatarBackgroundColor(string $hash) {
+ // Normalize hash
+ $hash = strtolower($hash);
+
+ // Already a md5 hash?
+ if( preg_match('/^([0-9a-f]{4}-?){8}$/', $hash, $matches) !== 1 ) {
+ $hash = md5($hash);
}
- // Reduce values bigger than rgb requirements
- $rgb[0] %= 255;
- $rgb[1] %= 255;
- $rgb[2] %= 255;
+ // Remove unwanted char
+ $hash = preg_replace('/[^0-9a-f]+/', '', $hash);
- $hsl = $this->rgbToHsl($rgb[0], $rgb[1], $rgb[2]);
+ $red = new Color(182, 70, 157);
+ $yellow = new Color(221, 203, 85);
+ $blue = new Color(0, 130, 201); // Nextcloud blue
- // Classic formula to check the brightness for our eye
- // If too bright, lower the sat
- $bright = sqrt(0.299 * ($rgb[0] ** 2) + 0.587 * ($rgb[1] ** 2) + 0.114 * ($rgb[2] ** 2));
- if ($bright >= 200) {
- $sat = 0.60;
- }
+ // Number of steps to go from a color to another
+ // 3 colors * 6 will result in 18 generated colors
+ $steps = 6;
- return $this->hslToRgb($hsl[0], $sat, $lum);
- }
+ $palette1 = $this->mixPalette($steps, $red, $yellow);
+ $palette2 = $this->mixPalette($steps, $yellow, $blue);
+ $palette3 = $this->mixPalette($steps, $blue, $red);
- /**
- * @param double $h Hue in range [0, 1]
- * @param double $s Saturation in range [0, 1]
- * @param double $l Lightness in range [0, 1]
- * @return int[] Array containing r g b in the range [0, 255]
- */
- private function hslToRgb($h, $s, $l){
- $hue2rgb = function ($p, $q, $t){
- if($t < 0) {
- $t += 1;
- }
- if($t > 1) {
- $t -= 1;
- }
- if($t < 1/6) {
- return $p + ($q - $p) * 6 * $t;
- }
- if($t < 1/2) {
- return $q;
- }
- if($t < 2/3) {
- return $p + ($q - $p) * (2/3 - $t) * 6;
- }
- return $p;
- };
-
- if($s === 0){
- $r = $l;
- $g = $l;
- $b = $l; // achromatic
- }else{
- $q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s;
- $p = 2 * $l - $q;
- $r = $hue2rgb($p, $q, $h + 1/3);
- $g = $hue2rgb($p, $q, $h);
- $b = $hue2rgb($p, $q, $h - 1/3);
- }
+ $finalPalette = array_merge($palette1, $palette2, $palette3);
- return array(round($r * 255), round($g * 255), round($b * 255));
+ return $finalPalette[$this->hashToInt($hash, $steps * 3)];
}
public function userChanged($feature, $oldValue, $newValue) {
diff --git a/lib/private/BackgroundJob/JobList.php b/lib/private/BackgroundJob/JobList.php
index 1399683dc9b..fab608cf164 100644
--- a/lib/private/BackgroundJob/JobList.php
+++ b/lib/private/BackgroundJob/JobList.php
@@ -48,6 +48,9 @@ class JobList implements IJobList {
/**@var ITimeFactory */
protected $timeFactory;
+ /** @var int - 12 hours * 3600 seconds*/
+ private $jobTimeOut = 43200;
+
/**
* @param IDBConnection $connection
* @param IConfig $config
@@ -177,12 +180,14 @@ class JobList implements IJobList {
* get the next job in the list
*
* @return IJob|null
+ * @suppress SqlInjectionChecker
*/
public function getNext() {
$query = $this->connection->getQueryBuilder();
$query->select('*')
->from('jobs')
- ->where($query->expr()->lte('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - 12 * 3600, IQueryBuilder::PARAM_INT)))
+ ->where($query->expr()->lte('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - $this->jobTimeOut, IQueryBuilder::PARAM_INT)))
+ ->andWhere($query->expr()->lte('last_checked', $query->createNamedParameter($this->timeFactory->getTime(), IQueryBuilder::PARAM_INT)))
->orderBy('last_checked', 'ASC')
->setMaxResults(1);
@@ -211,6 +216,14 @@ class JobList implements IJobList {
$job = $this->buildJob($row);
if ($job === null) {
+ // set the last_checked to 12h in the future to not check failing jobs all over again
+ $reset = $this->connection->getQueryBuilder();
+ $reset->update('jobs')
+ ->set('reserved_at', $reset->expr()->literal(0, IQueryBuilder::PARAM_INT))
+ ->set('last_checked', $reset->createNamedParameter($this->timeFactory->getTime() + 12 * 3600, IQueryBuilder::PARAM_INT))
+ ->where($reset->expr()->eq('id', $reset->createNamedParameter($row['id'], IQueryBuilder::PARAM_INT)));
+ $reset->execute();
+
// Background job from disabled app, try again.
return $this->getNext();
}
@@ -333,4 +346,39 @@ class JobList implements IJobList {
->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
$query->execute();
}
+
+ /**
+ * checks if a job is still running (reserved_at time is smaller than 12 hours ago)
+ *
+ * Background information:
+ *
+ * The 12 hours is the same timeout that is also used to re-schedule an non-terminated
+ * job (see getNext()). The idea here is to give a job enough time to run very
+ * long but still be able to recognize that it maybe crashed and re-schedule it
+ * after the timeout. It's more likely to be crashed at that time than it ran
+ * that long.
+ *
+ * In theory it could lead to an nearly endless loop (as in - at most 12 hours).
+ * The cron command will not start new jobs when maintenance mode is active and
+ * this method is only executed in maintenance mode (see where it is called in
+ * the upgrader class. So this means in the worst case we wait 12 hours when a
+ * job has crashed. On the other hand: then the instance should be fixed anyways.
+ *
+ * @return bool
+ */
+ public function isAnyJobRunning(): bool {
+ $query = $this->connection->getQueryBuilder();
+ $query->select('*')
+ ->from('jobs')
+ ->where($query->expr()->gt('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - $this->jobTimeOut, IQueryBuilder::PARAM_INT)))
+ ->setMaxResults(1);
+ $result = $query->execute();
+ $row = $result->fetch();
+ $result->closeCursor();
+
+ if ($row) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/lib/private/Cache/File.php b/lib/private/Cache/File.php
index ab51b54b8c8..fdf7606de0f 100644
--- a/lib/private/Cache/File.php
+++ b/lib/private/Cache/File.php
@@ -30,6 +30,7 @@ namespace OC\Cache;
use OC\Files\Filesystem;
use OC\Files\View;
use OCP\ICache;
+use OCP\ILogger;
use OCP\Security\ISecureRandom;
class File implements ICache {
@@ -58,7 +59,7 @@ class File implements ICache {
$this->storage = new View('/' . $user->getUID() . '/cache');
return $this->storage;
} else {
- \OCP\Util::writeLog('core', 'Can\'t get cache storage, user not logged in', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'Can\'t get cache storage, user not logged in', ILogger::ERROR);
throw new \OC\ForbiddenException('Can\t get cache storage, user not logged in');
}
}
@@ -173,7 +174,7 @@ class File implements ICache {
*/
public function gc() {
$storage = $this->getStorage();
- if ($storage and $storage->is_dir('/')) {
+ if ($storage) {
// extra hour safety, in case of stray part chunks that take longer to write,
// because touch() is only called after the chunk was finished
$now = time() - 3600;
diff --git a/lib/private/Calendar/Resource/Manager.php b/lib/private/Calendar/Resource/Manager.php
new file mode 100644
index 00000000000..baa8117e85a
--- /dev/null
+++ b/lib/private/Calendar/Resource/Manager.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
+ *
+ * @author Georg Ehrke <oc.list@georgehrke.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Calendar\Resource;
+
+use OCP\Calendar\Resource\IBackend;
+
+class Manager implements \OCP\Calendar\Resource\IManager {
+
+ /** @var IBackend[] holds all registered resource backends */
+ private $backends = [];
+
+ /**
+ * Registers a resource backend
+ *
+ * @param IBackend $backend
+ * @return void
+ * @since 14.0.0
+ */
+ public function registerBackend(IBackend $backend) {
+ $this->backends[$backend->getBackendIdentifier()] = $backend;
+ }
+
+ /**
+ * Unregisters a resource backend
+ *
+ * @param IBackend $backend
+ * @return void
+ * @since 14.0.0
+ */
+ public function unregisterBackend(IBackend $backend) {
+ unset($this->backends[$backend->getBackendIdentifier()]);
+ }
+
+ /**
+ * @return IBackend[]
+ * @since 14.0.0
+ */
+ public function getBackends():array {
+ return array_values($this->backends);
+ }
+
+ /**
+ * @param string $backendId
+ * @return IBackend|null
+ */
+ public function getBackend($backendId):IBackend {
+ if (!isset($this->backends[$backendId])) {
+ return null;
+ }
+
+ return $this->backends[$backendId];
+ }
+
+ /**
+ * removes all registered backend instances
+ * @return void
+ * @since 14.0.0
+ */
+ public function clear() {
+ $this->backends = [];
+ }
+}
diff --git a/lib/private/Calendar/Room/Manager.php b/lib/private/Calendar/Room/Manager.php
new file mode 100644
index 00000000000..aef9f2ed32b
--- /dev/null
+++ b/lib/private/Calendar/Room/Manager.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
+ *
+ * @author Georg Ehrke <oc.list@georgehrke.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Calendar\Room;
+
+use OCP\Calendar\Room\IBackend;
+
+class Manager implements \OCP\Calendar\Room\IManager {
+
+ /** @var IBackend[] holds all registered resource backends */
+ private $backends = [];
+
+ /**
+ * Registers a resource backend
+ *
+ * @param IBackend $backend
+ * @return void
+ * @since 14.0.0
+ */
+ public function registerBackend(IBackend $backend) {
+ $this->backends[$backend->getBackendIdentifier()] = $backend;
+ }
+
+ /**
+ * Unregisters a resource backend
+ *
+ * @param IBackend $backend
+ * @return void
+ * @since 14.0.0
+ */
+ public function unregisterBackend(IBackend $backend) {
+ unset($this->backends[$backend->getBackendIdentifier()]);
+ }
+
+ /**
+ * @return IBackend[]
+ * @since 14.0.0
+ */
+ public function getBackends():array {
+ return array_values($this->backends);
+ }
+
+ /**
+ * @param string $backendId
+ * @return IBackend|null
+ */
+ public function getBackend($backendId):IBackend {
+ if (!isset($this->backends[$backendId])) {
+ return null;
+ }
+
+ return $this->backends[$backendId];
+ }
+
+ /**
+ * removes all registered backend instances
+ * @return void
+ * @since 14.0.0
+ */
+ public function clear() {
+ $this->backends = [];
+ }
+}
diff --git a/lib/private/CapabilitiesManager.php b/lib/private/CapabilitiesManager.php
index fb272764597..ceb8205a7bb 100644
--- a/lib/private/CapabilitiesManager.php
+++ b/lib/private/CapabilitiesManager.php
@@ -57,7 +57,7 @@ class CapabilitiesManager {
} catch (QueryException $e) {
$this->logger->logException($e, [
'message' => 'CapabilitiesManager',
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
continue;
diff --git a/lib/private/Collaboration/Collaborators/GroupPlugin.php b/lib/private/Collaboration/Collaborators/GroupPlugin.php
index b147d2d7b58..7eee042076e 100644
--- a/lib/private/Collaboration/Collaborators/GroupPlugin.php
+++ b/lib/private/Collaboration/Collaborators/GroupPlugin.php
@@ -59,7 +59,7 @@ class GroupPlugin implements ISearchPlugin {
$groups = $this->groupManager->search($search, $limit, $offset);
$groupIds = array_map(function (IGroup $group) { return $group->getGID(); }, $groups);
- if (!$this->shareeEnumeration || sizeof($groups) < $limit) {
+ if (!$this->shareeEnumeration || count($groups) < $limit) {
$hasMoreResults = true;
}
diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php
index 2e946c4a872..101d6845ec3 100644
--- a/lib/private/Collaboration/Collaborators/MailPlugin.php
+++ b/lib/private/Collaboration/Collaborators/MailPlugin.php
@@ -28,9 +28,11 @@ use OCP\Collaboration\Collaborators\ISearchPlugin;
use OCP\Collaboration\Collaborators\ISearchResult;
use OCP\Collaboration\Collaborators\SearchResultType;
use OCP\Contacts\IManager;
+use OCP\Federation\ICloudId;
use OCP\Federation\ICloudIdManager;
use OCP\IConfig;
use OCP\IGroupManager;
+use OCP\IUser;
use OCP\IUserSession;
use OCP\Share;
@@ -71,7 +73,7 @@ class MailPlugin implements ISearchPlugin {
* @since 13.0.0
*/
public function search($search, $limit, $offset, ISearchResult $searchResult) {
- $result = ['wide' => [], 'exact' => []];
+ $result = $userResults = ['wide' => [], 'exact' => []];
$userType = new SearchResultType('users');
$emailType = new SearchResultType('emails');
@@ -86,6 +88,10 @@ class MailPlugin implements ISearchPlugin {
$emailAddresses = [$emailAddresses];
}
foreach ($emailAddresses as $emailAddress) {
+ $displayName = $emailAddress;
+ if (isset($contact['FN'])) {
+ $displayName = $contact['FN'] . ' (' . $emailAddress . ')';
+ }
$exactEmailMatch = strtolower($emailAddress) === $lowerSearch;
if (isset($contact['isLocalSystemBook'])) {
@@ -112,9 +118,9 @@ class MailPlugin implements ISearchPlugin {
continue;
}
- if (!$searchResult->hasResult($userType, $cloud->getUser())) {
+ if (!$this->isCurrentUser($cloud) && !$searchResult->hasResult($userType, $cloud->getUser())) {
$singleResult = [[
- 'label' => $contact['FN'] . " ($emailAddress)",
+ 'label' => $displayName,
'value' => [
'shareType' => Share::SHARE_TYPE_USER,
'shareWith' => $cloud->getUser(),
@@ -133,26 +139,27 @@ class MailPlugin implements ISearchPlugin {
continue;
}
- if (!$searchResult->hasResult($userType, $cloud->getUser())) {
- $singleResult = [[
- 'label' => $contact['FN'] . " ($emailAddress)",
+ if (!$this->isCurrentUser($cloud) && !$searchResult->hasResult($userType, $cloud->getUser())) {
+ $userResults['wide'][] = [
+ 'label' => $displayName,
'value' => [
'shareType' => Share::SHARE_TYPE_USER,
'shareWith' => $cloud->getUser(),
- ]],
+ ],
];
- $searchResult->addResultSet($userType, $singleResult, []);
}
}
continue;
}
- if ($exactEmailMatch || strtolower($contact['FN']) === $lowerSearch) {
+ if ($exactEmailMatch
+ || isset($contact['FN']) && strtolower($contact['FN']) === $lowerSearch)
+ {
if ($exactEmailMatch) {
$searchResult->markExactIdMatch($emailType);
}
$result['exact'][] = [
- 'label' => $contact['FN'] . " ($emailAddress)",
+ 'label' => $displayName,
'value' => [
'shareType' => Share::SHARE_TYPE_EMAIL,
'shareWith' => $emailAddress,
@@ -160,7 +167,7 @@ class MailPlugin implements ISearchPlugin {
];
} else {
$result['wide'][] = [
- 'label' => $contact['FN'] . " ($emailAddress)",
+ 'label' => $displayName,
'value' => [
'shareType' => Share::SHARE_TYPE_EMAIL,
'shareWith' => $emailAddress,
@@ -171,10 +178,19 @@ class MailPlugin implements ISearchPlugin {
}
}
+ $reachedEnd = true;
if (!$this->shareeEnumeration) {
$result['wide'] = [];
+ $userResults['wide'] = [];
+ } else {
+ $reachedEnd = (count($result['wide']) < $offset + $limit) &&
+ (count($userResults['wide']) < $offset + $limit);
+
+ $result['wide'] = array_slice($result['wide'], $offset, $limit);
+ $userResults['wide'] = array_slice($userResults['wide'], $offset, $limit);
}
+
if (!$searchResult->hasExactIdMatch($emailType) && filter_var($search, FILTER_VALIDATE_EMAIL)) {
$result['exact'][] = [
'label' => $search,
@@ -185,8 +201,16 @@ class MailPlugin implements ISearchPlugin {
];
}
+ if (!empty($userResults['wide'])) {
+ $searchResult->addResultSet($userType, $userResults['wide'], []);
+ }
$searchResult->addResultSet($emailType, $result['wide'], $result['exact']);
- return true;
+ return !$reachedEnd;
+ }
+
+ public function isCurrentUser(ICloudId $cloud): bool {
+ $currentUser = $this->userSession->getUser();
+ return $currentUser instanceof IUser ? $currentUser->getUID() === $cloud->getUser() : false;
}
}
diff --git a/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php b/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php
new file mode 100644
index 00000000000..c48a1fbae20
--- /dev/null
+++ b/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php
@@ -0,0 +1,78 @@
+<?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\ICloudFederationProviderManager;
+use OCP\Federation\ICloudIdManager;
+use OCP\IConfig;
+use OCP\Share;
+
+class RemoteGroupPlugin implements ISearchPlugin {
+ protected $shareeEnumeration;
+
+ /** @var ICloudIdManager */
+ private $cloudIdManager;
+ /** @var IConfig */
+ private $config;
+ /** @var bool */
+ private $enabled = false;
+
+ public function __construct(ICloudFederationProviderManager $cloudFederationProviderManager, ICloudIdManager $cloudIdManager) {
+ try {
+ $fileSharingProvider = $cloudFederationProviderManager->getCloudFederationProvider('file');
+ $supportedShareTypes = $fileSharingProvider->getSupportedShareTypes();
+ if (in_array('group', $supportedShareTypes)) {
+ $this->enabled = true;
+ }
+ } catch (\Exception $e) {
+ // do nothing, just don't enable federated group shares
+ }
+ $this->cloudIdManager = $cloudIdManager;
+ }
+
+ public function search($search, $limit, $offset, ISearchResult $searchResult) {
+ $result = ['wide' => [], 'exact' => []];
+ $resultType = new SearchResultType('remote_groups');
+
+ if ($this->enabled && $this->cloudIdManager->isValidCloudId($search) && $offset === 0) {
+ $result['exact'][] = [
+ 'label' => $search,
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_REMOTE_GROUP,
+ 'shareWith' => $search,
+ ],
+ ];
+ }
+
+ $searchResult->addResultSet($resultType, $result['wide'], $result['exact']);
+
+ return true;
+ }
+
+}
diff --git a/lib/private/Collaboration/Collaborators/RemotePlugin.php b/lib/private/Collaboration/Collaborators/RemotePlugin.php
index b17a64e4ff1..e0f5298f83b 100644
--- a/lib/private/Collaboration/Collaborators/RemotePlugin.php
+++ b/lib/private/Collaboration/Collaborators/RemotePlugin.php
@@ -102,6 +102,8 @@ class RemotePlugin implements ISearchPlugin {
if (!$this->shareeEnumeration) {
$result['wide'] = [];
+ } else {
+ $result['wide'] = array_slice($result['wide'], $offset, $limit);
}
if (!$searchResult->hasExactIdMatch($resultType) && $this->cloudIdManager->isValidCloudId($search) && $offset === 0) {
diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php
index d2639249d56..62f76876031 100644
--- a/lib/private/Collaboration/Collaborators/UserPlugin.php
+++ b/lib/private/Collaboration/Collaborators/UserPlugin.php
@@ -85,7 +85,7 @@ class UserPlugin implements ISearchPlugin {
$this->takeOutCurrentUser($users);
- if (!$this->shareeEnumeration || sizeof($users) < $limit) {
+ if (!$this->shareeEnumeration || count($users) < $limit) {
$hasMoreResults = true;
}
diff --git a/lib/private/Color.php b/lib/private/Color.php
new file mode 100644
index 00000000000..78e8d49a401
--- /dev/null
+++ b/lib/private/Color.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016, John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC;
+
+class Color {
+ public $r, $g, $b;
+ public function __construct($r, $g, $b) {
+ $this->r = $r;
+ $this->g = $g;
+ $this->b = $b;
+ }
+}
diff --git a/lib/private/Comments/Comment.php b/lib/private/Comments/Comment.php
index dd790c2e50a..94c43be622b 100644
--- a/lib/private/Comments/Comment.php
+++ b/lib/private/Comments/Comment.php
@@ -225,7 +225,7 @@ class Comment implements IComment {
*
*/
public function getMentions() {
- $ok = preg_match_all('/\B@[a-z0-9_\-@\.\']+/i', $this->getMessage(), $mentions);
+ $ok = preg_match_all("/\B(?<![^a-z0-9_\-@\.\'\s])@[a-z0-9_\-@\.\']+/i", $this->getMessage(), $mentions);
if(!$ok || !isset($mentions[0]) || !is_array($mentions[0])) {
return [];
}
diff --git a/lib/private/Comments/Manager.php b/lib/private/Comments/Manager.php
index 2b43a27b7ac..d96c22aad51 100644
--- a/lib/private/Comments/Manager.php
+++ b/lib/private/Comments/Manager.php
@@ -377,6 +377,123 @@ class Manager implements ICommentsManager {
}
/**
+ * @param string $objectType the object type, e.g. 'files'
+ * @param string $objectId the id of the object
+ * @param int $lastKnownCommentId the last known comment (will be used as offset)
+ * @param string $sortDirection direction of the comments (`asc` or `desc`)
+ * @param int $limit optional, number of maximum comments to be returned. if
+ * set to 0, all comments are returned.
+ * @return IComment[]
+ * @return array
+ */
+ public function getForObjectSince(
+ string $objectType,
+ string $objectId,
+ int $lastKnownCommentId,
+ string $sortDirection = 'asc',
+ int $limit = 30
+ ): array {
+ $comments = [];
+
+ $query = $this->dbConn->getQueryBuilder();
+ $query->select('*')
+ ->from('comments')
+ ->where($query->expr()->eq('object_type', $query->createNamedParameter($objectType)))
+ ->andWhere($query->expr()->eq('object_id', $query->createNamedParameter($objectId)))
+ ->orderBy('creation_timestamp', $sortDirection === 'desc' ? 'DESC' : 'ASC')
+ ->addOrderBy('id', $sortDirection === 'desc' ? 'DESC' : 'ASC');
+
+ if ($limit > 0) {
+ $query->setMaxResults($limit);
+ }
+
+ $lastKnownComment = $lastKnownCommentId > 0 ? $this->getLastKnownComment(
+ $objectType,
+ $objectId,
+ $lastKnownCommentId
+ ) : null;
+ if ($lastKnownComment instanceof IComment) {
+ $lastKnownCommentDateTime = $lastKnownComment->getCreationDateTime();
+ if ($sortDirection === 'desc') {
+ $query->andWhere(
+ $query->expr()->orX(
+ $query->expr()->lt(
+ 'creation_timestamp',
+ $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATE),
+ IQueryBuilder::PARAM_DATE
+ ),
+ $query->expr()->andX(
+ $query->expr()->eq(
+ 'creation_timestamp',
+ $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATE),
+ IQueryBuilder::PARAM_DATE
+ ),
+ $query->expr()->lt('id', $query->createNamedParameter($lastKnownCommentId))
+ )
+ )
+ );
+ } else {
+ $query->andWhere(
+ $query->expr()->orX(
+ $query->expr()->gt(
+ 'creation_timestamp',
+ $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATE),
+ IQueryBuilder::PARAM_DATE
+ ),
+ $query->expr()->andX(
+ $query->expr()->eq(
+ 'creation_timestamp',
+ $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATE),
+ IQueryBuilder::PARAM_DATE
+ ),
+ $query->expr()->gt('id', $query->createNamedParameter($lastKnownCommentId))
+ )
+ )
+ );
+ }
+ }
+
+ $resultStatement = $query->execute();
+ while ($data = $resultStatement->fetch()) {
+ $comment = new Comment($this->normalizeDatabaseData($data));
+ $this->cache($comment);
+ $comments[] = $comment;
+ }
+ $resultStatement->closeCursor();
+
+ return $comments;
+ }
+
+ /**
+ * @param string $objectType the object type, e.g. 'files'
+ * @param string $objectId the id of the object
+ * @param int $id the comment to look for
+ * @return Comment|null
+ */
+ protected function getLastKnownComment(string $objectType,
+ string $objectId,
+ int $id) {
+ $query = $this->dbConn->getQueryBuilder();
+ $query->select('*')
+ ->from('comments')
+ ->where($query->expr()->eq('object_type', $query->createNamedParameter($objectType)))
+ ->andWhere($query->expr()->eq('object_id', $query->createNamedParameter($objectId)))
+ ->andWhere($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
+
+ $result = $query->execute();
+ $row = $result->fetch();
+ $result->closeCursor();
+
+ if ($row) {
+ $comment = new Comment($this->normalizeDatabaseData($row));
+ $this->cache($comment);
+ return $comment;
+ }
+
+ return null;
+ }
+
+ /**
* @param $objectType string the object type, e.g. 'files'
* @param $objectId string the id of the object
* @param \DateTime $notOlderThan optional, timestamp of the oldest comments
diff --git a/lib/private/Config.php b/lib/private/Config.php
index 2abf00a718c..c881e485006 100644
--- a/lib/private/Config.php
+++ b/lib/private/Config.php
@@ -37,7 +37,7 @@ namespace OC;
/**
* This class is responsible for reading and writing config.php, the very basic
- * configuration file of ownCloud.
+ * configuration file of Nextcloud.
*/
class Config {
diff --git a/lib/private/Console/Application.php b/lib/private/Console/Application.php
index c85b67217b4..1de5fbd6ca3 100644
--- a/lib/private/Console/Application.php
+++ b/lib/private/Console/Application.php
@@ -39,6 +39,7 @@ use OCP\IRequest;
use Symfony\Component\Console\Application as SymfonyApplication;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -69,10 +70,13 @@ class Application {
/**
* @param InputInterface $input
- * @param OutputInterface $output
+ * @param ConsoleOutputInterface $output
* @throws \Exception
*/
- public function loadCommands(InputInterface $input, OutputInterface $output) {
+ public function loadCommands(
+ InputInterface $input,
+ ConsoleOutputInterface $output
+ ) {
// $application is required to be defined in the register_command scripts
$application = $this->application;
$inputDefinition = $application->getDefinition();
@@ -99,10 +103,7 @@ class Application {
if (\OCP\Util::needUpgrade()) {
throw new NeedsUpdateException();
} elseif ($this->config->getSystemValue('maintenance', false)) {
- if ($input->getArgument('command') !== '_completion') {
- $errOutput = $output->getErrorOutput();
- $errOutput->writeln('<comment>Nextcloud is in maintenance mode - no apps have been loaded</comment>' . PHP_EOL);
- }
+ $this->writeMaintenanceModeInfo($input, $output);
} else {
OC_App::loadApps();
foreach (\OC::$server->getAppManager()->getInstalledApps() as $app) {
@@ -151,6 +152,28 @@ class Application {
}
/**
+ * Write a maintenance mode info.
+ * The commands "_completion" and "maintenance:mode" are excluded.
+ *
+ * @param InputInterface $input The input implementation for reading inputs.
+ * @param ConsoleOutputInterface $output The output implementation
+ * for writing outputs.
+ * @return void
+ */
+ private function writeMaintenanceModeInfo(
+ InputInterface $input, ConsoleOutputInterface $output
+ ) {
+ if ($input->getArgument('command') !== '_completion'
+ && $input->getArgument('command') !== 'maintenance:mode') {
+ $errOutput = $output->getErrorOutput();
+ $errOutput->writeln(
+ '<comment>Nextcloud is in maintenance mode - ' .
+ 'no apps have been loaded</comment>' . PHP_EOL
+ );
+ }
+ }
+
+ /**
* Sets whether to automatically exit after a command execution or not.
*
* @param bool $boolean Whether to automatically exit after a command execution or not
diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php
index 43600470e1f..05ef9cca53a 100644
--- a/lib/private/Contacts/ContactsMenu/ContactsStore.php
+++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php
@@ -27,14 +27,12 @@
namespace OC\Contacts\ContactsMenu;
-use OC\Share\Share;
use OCP\Contacts\ContactsMenu\IEntry;
use OCP\Contacts\IManager;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserManager;
-use OCP\IUserSession;
use OCP\Contacts\ContactsMenu\IContactsStore;
class ContactsStore implements IContactsStore {
@@ -157,7 +155,13 @@ class ContactsStore implements IContactsStore {
}
if ($ownGroupsOnly && $entry->getProperty('isLocalSystemBook') === true) {
- $contactGroups = $this->groupManager->getUserGroupIds($this->userManager->get($entry->getProperty('UID')));
+ $uid = $this->userManager->get($entry->getProperty('UID'));
+
+ if ($uid === NULL) {
+ return false;
+ }
+
+ $contactGroups = $this->groupManager->getUserGroupIds($uid);
if (count(array_intersect($contactGroups, $selfGroups)) === 0) {
// no groups in common, so shouldn't see the contact
return false;
@@ -202,7 +206,8 @@ class ContactsStore implements IContactsStore {
}
}
if ($shareType === 0 || $shareType === 6) {
- if ($contact['UID'] === $shareWith && $contact['isLocalSystemBook'] === true) {
+ $isLocal = $contact['isLocalSystemBook'] ?? false;
+ if ($contact['UID'] === $shareWith && $isLocal === true) {
$match = $contact;
break;
}
diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php
index b9ef447b74b..8bb959ffbc1 100644
--- a/lib/private/DB/Connection.php
+++ b/lib/private/DB/Connection.php
@@ -43,7 +43,7 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\PreConditionNotMetException;
-class Connection extends \Doctrine\DBAL\Connection implements IDBConnection {
+class Connection extends ReconnectWrapper implements IDBConnection {
/**
* @var string $tablePrefix
*/
@@ -401,7 +401,7 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection {
}
/**
- * Espace a parameter to be used in a LIKE query
+ * Escape a parameter to be used in a LIKE query
*
* @param string $param
* @return string
diff --git a/lib/private/DB/ConnectionFactory.php b/lib/private/DB/ConnectionFactory.php
index c841a36bb5a..9fc2ed42c33 100644
--- a/lib/private/DB/ConnectionFactory.php
+++ b/lib/private/DB/ConnectionFactory.php
@@ -193,16 +193,7 @@ class ConnectionFactory {
$connectionParams['path'] = $dataDir . '/' . $name . '.db';
} else {
$host = $this->config->getValue('dbhost', '');
- if (strpos($host, ':')) {
- // Host variable may carry a port or socket.
- list($host, $portOrSocket) = explode(':', $host, 2);
- if (ctype_digit($portOrSocket)) {
- $connectionParams['port'] = $portOrSocket;
- } else {
- $connectionParams['unix_socket'] = $portOrSocket;
- }
- }
- $connectionParams['host'] = $host;
+ $connectionParams = array_merge($connectionParams, $this->splitHostFromPortAndSocket($host));
$connectionParams['dbname'] = $name;
}
@@ -232,4 +223,27 @@ class ConnectionFactory {
return $connectionParams;
}
+
+ /**
+ * @param string $host
+ * @return array
+ */
+ protected function splitHostFromPortAndSocket($host): array {
+ $params = [
+ 'host' => $host,
+ ];
+
+ $matches = [];
+ if (preg_match('/^(.*):([^\]:]+)$/', $host, $matches)) {
+ // Host variable carries a port or socket.
+ $params['host'] = $matches[1];
+ if (is_numeric($matches[2])) {
+ $params['port'] = (int) $matches[2];
+ } else {
+ $params['unix_socket'] = $matches[2];
+ }
+ }
+
+ return $params;
+ }
}
diff --git a/lib/private/DB/MigrationService.php b/lib/private/DB/MigrationService.php
index 29f717b886c..cc2889dae0c 100644
--- a/lib/private/DB/MigrationService.php
+++ b/lib/private/DB/MigrationService.php
@@ -31,8 +31,6 @@ use OCP\AppFramework\QueryException;
use OCP\IDBConnection;
use OCP\Migration\IMigrationStep;
use OCP\Migration\IOutput;
-use Doctrine\DBAL\Schema\Column;
-use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Types\Type;
class MigrationService {
@@ -389,14 +387,36 @@ class MigrationService {
}
/**
+ * Get the human readable descriptions for the migration steps to run
+ *
+ * @param string $to
+ * @return string[] [$name => $description]
+ */
+ public function describeMigrationStep($to = 'latest') {
+ $toBeExecuted = $this->getMigrationsToExecute($to);
+ $description = [];
+ foreach ($toBeExecuted as $version) {
+ $migration = $this->createInstance($version);
+ if ($migration->name()) {
+ $description[$migration->name()] = $migration->description();
+ }
+ }
+ return $description;
+ }
+
+ /**
* @param string $version
- * @return mixed
+ * @return IMigrationStep
* @throws \InvalidArgumentException
*/
protected function createInstance($version) {
$class = $this->getClass($version);
try {
$s = \OC::$server->query($class);
+
+ if (!$s instanceof IMigrationStep) {
+ throw new \InvalidArgumentException('Not a valid migration');
+ }
} catch (QueryException $e) {
if (class_exists($class)) {
$s = new $class();
@@ -416,9 +436,6 @@ class MigrationService {
*/
public function executeStep($version) {
$instance = $this->createInstance($version);
- if (!$instance instanceof IMigrationStep) {
- throw new \InvalidArgumentException('Not a valid migration');
- }
$instance->preSchemaChange($this->output, function() {
return new SchemaWrapper($this->connection);
diff --git a/lib/private/DB/MissingIndexInformation.php b/lib/private/DB/MissingIndexInformation.php
new file mode 100644
index 00000000000..0cb9852d0d4
--- /dev/null
+++ b/lib/private/DB/MissingIndexInformation.php
@@ -0,0 +1,39 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 Morris Jobke <hey@morrisjobke.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\DB;
+
+class MissingIndexInformation {
+
+ private $listOfMissingIndexes = [];
+
+ public function addHintForMissingSubject(string $tableName, string $indexName) {
+ $this->listOfMissingIndexes[] = [
+ 'tableName' => $tableName,
+ 'indexName' => $indexName
+ ];
+ }
+
+ public function getListOfMissingIndexes(): array {
+ return $this->listOfMissingIndexes;
+ }
+} \ No newline at end of file
diff --git a/lib/private/DB/MySqlTools.php b/lib/private/DB/MySqlTools.php
index 7f0ba473268..b67aaffe5b4 100644
--- a/lib/private/DB/MySqlTools.php
+++ b/lib/private/DB/MySqlTools.php
@@ -34,17 +34,36 @@ class MySqlTools {
* @return bool
*/
public function supports4ByteCharset(IDBConnection $connection) {
- foreach (['innodb_file_format' => 'Barracuda', 'innodb_large_prefix' => 'ON', 'innodb_file_per_table' => 'ON'] as $var => $val) {
+ $variables = ['innodb_file_per_table' => 'ON'];
+ if (!$this->isMariaDBWithLargePrefix($connection)) {
+ $variables['innodb_file_format'] = 'Barracuda';
+ $variables['innodb_large_prefix'] = 'ON';
+ }
+
+ foreach ($variables as $var => $val) {
$result = $connection->executeQuery("SHOW VARIABLES LIKE '$var'");
- $rows = $result->fetch();
+ $row = $result->fetch();
$result->closeCursor();
- if ($rows === false) {
+ if ($row === false) {
return false;
}
- if (strcasecmp($rows['Value'], $val) !== 0) {
+ if (strcasecmp($row['Value'], $val) !== 0) {
return false;
}
}
return true;
}
+
+ protected function isMariaDBWithLargePrefix(IDBConnection $connection) {
+ $result = $connection->executeQuery('SELECT VERSION()');
+ $row = strtolower($result->fetchColumn());
+ $result->closeCursor();
+
+ if ($row === false) {
+ return false;
+ }
+
+ return strpos($row, 'maria') && version_compare($row, '10.3', '>=') ||
+ strpos($row, 'maria') === false && version_compare($row, '8.0', '>=');
+ }
}
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php
index a32ae4a1827..6e4a2061832 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php
@@ -26,6 +26,7 @@ namespace OC\DB\QueryBuilder\ExpressionBuilder;
use Doctrine\DBAL\Query\Expression\ExpressionBuilder as DoctrineExpressionBuilder;
use OC\DB\QueryBuilder\CompositeExpression;
+use OC\DB\QueryBuilder\FunctionBuilder\FunctionBuilder;
use OC\DB\QueryBuilder\Literal;
use OC\DB\QueryBuilder\QueryFunction;
use OC\DB\QueryBuilder\QuoteHelper;
@@ -45,15 +46,20 @@ class ExpressionBuilder implements IExpressionBuilder {
/** @var IDBConnection */
protected $connection;
+ /** @var FunctionBuilder */
+ protected $functionBuilder;
+
/**
* Initializes a new <tt>ExpressionBuilder</tt>.
*
- * @param \OCP\IDBConnection $connection
+ * @param IDBConnection $connection
+ * @param IQueryBuilder $queryBuilder
*/
- public function __construct(IDBConnection $connection) {
+ public function __construct(IDBConnection $connection, IQueryBuilder $queryBuilder) {
$this->connection = $connection;
$this->helper = new QuoteHelper();
$this->expressionBuilder = new DoctrineExpressionBuilder($connection);
+ $this->functionBuilder = $queryBuilder->func();
}
/**
@@ -65,14 +71,13 @@ class ExpressionBuilder implements IExpressionBuilder {
* // (u.type = ?) AND (u.role = ?)
* $expr->andX('u.type = ?', 'u.role = ?'));
*
- * @param mixed $x Optional clause. Defaults = null, but requires
+ * @param mixed ...$x Optional clause. Defaults = null, but requires
* at least one defined when converting to string.
*
* @return \OCP\DB\QueryBuilder\ICompositeExpression
*/
- public function andX($x = null) {
- $arguments = func_get_args();
- $compositeExpression = call_user_func_array([$this->expressionBuilder, 'andX'], $arguments);
+ public function andX(...$x) {
+ $compositeExpression = call_user_func_array([$this->expressionBuilder, 'andX'], $x);
return new CompositeExpression($compositeExpression);
}
@@ -85,14 +90,13 @@ class ExpressionBuilder implements IExpressionBuilder {
* // (u.type = ?) OR (u.role = ?)
* $qb->where($qb->expr()->orX('u.type = ?', 'u.role = ?'));
*
- * @param mixed $x Optional clause. Defaults = null, but requires
+ * @param mixed ...$x Optional clause. Defaults = null, but requires
* at least one defined when converting to string.
*
* @return \OCP\DB\QueryBuilder\ICompositeExpression
*/
- public function orX($x = null) {
- $arguments = func_get_args();
- $compositeExpression = call_user_func_array([$this->expressionBuilder, 'orX'], $arguments);
+ public function orX(...$x) {
+ $compositeExpression = call_user_func_array([$this->expressionBuilder, 'orX'], $x);
return new CompositeExpression($compositeExpression);
}
@@ -298,9 +302,7 @@ class ExpressionBuilder implements IExpressionBuilder {
* @since 9.0.0
*/
public function iLike($x, $y, $type = null) {
- $x = $this->helper->quoteColumnName($x);
- $y = $this->helper->quoteColumnName($y);
- return $this->expressionBuilder->comparison("LOWER($x)", 'LIKE', "LOWER($y)");
+ return $this->expressionBuilder->like($this->functionBuilder->lower($x), $this->functionBuilder->lower($y));
}
/**
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php
index 17f7fd5aa47..aa7ef8e70be 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php
@@ -25,6 +25,7 @@ namespace OC\DB\QueryBuilder\ExpressionBuilder;
use OC\DB\Connection;
+use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
class MySqlExpressionBuilder extends ExpressionBuilder {
@@ -34,9 +35,10 @@ class MySqlExpressionBuilder extends ExpressionBuilder {
/**
* @param \OCP\IDBConnection|Connection $connection
+ * @param IQueryBuilder $queryBuilder
*/
- public function __construct(IDBConnection $connection) {
- parent::__construct($connection);
+ public function __construct(IDBConnection $connection, IQueryBuilder $queryBuilder) {
+ parent::__construct($connection, $queryBuilder);
$params = $connection->getParams();
$this->charset = isset($params['charset']) ? $params['charset'] : 'utf8';
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php
index 14d8ad33e40..d9e8a1279cc 100644
--- a/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php
+++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php
@@ -31,4 +31,8 @@ class SqliteExpressionBuilder extends ExpressionBuilder {
public function like($x, $y, $type = null) {
return parent::like($x, $y, $type) . " ESCAPE '\\'";
}
+
+ public function iLike($x, $y, $type = null) {
+ return $this->like($this->functionBuilder->lower($x), $this->functionBuilder->lower($y), $type);
+ }
}
diff --git a/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php b/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php
index 2789b8cb356..cf6183b0238 100644
--- a/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php
+++ b/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php
@@ -59,4 +59,20 @@ class FunctionBuilder implements IFunctionBuilder {
public function sum($field) {
return new QueryFunction('SUM(' . $this->helper->quoteColumnName($field) . ')');
}
+
+ public function lower($field) {
+ return new QueryFunction('LOWER(' . $this->helper->quoteColumnName($field) . ')');
+ }
+
+ public function add($x, $y) {
+ return new QueryFunction($this->helper->quoteColumnName($x) . ' + ' . $this->helper->quoteColumnName($y));
+ }
+
+ public function subtract($x, $y) {
+ return new QueryFunction($this->helper->quoteColumnName($x) . ' - ' . $this->helper->quoteColumnName($y));
+ }
+
+ public function count($input) {
+ return new QueryFunction('COUNT(' . $this->helper->quoteColumnName($input) . ')');
+ }
}
diff --git a/lib/private/DB/QueryBuilder/QueryBuilder.php b/lib/private/DB/QueryBuilder/QueryBuilder.php
index 58be4b43255..ebbcdeb0870 100644
--- a/lib/private/DB/QueryBuilder/QueryBuilder.php
+++ b/lib/private/DB/QueryBuilder/QueryBuilder.php
@@ -112,15 +112,15 @@ class QueryBuilder implements IQueryBuilder {
*/
public function expr() {
if ($this->connection instanceof OracleConnection) {
- return new OCIExpressionBuilder($this->connection);
+ return new OCIExpressionBuilder($this->connection, $this);
} else if ($this->connection->getDatabasePlatform() instanceof PostgreSqlPlatform) {
- return new PgSqlExpressionBuilder($this->connection);
+ return new PgSqlExpressionBuilder($this->connection, $this);
} else if ($this->connection->getDatabasePlatform() instanceof MySqlPlatform) {
- return new MySqlExpressionBuilder($this->connection);
+ return new MySqlExpressionBuilder($this->connection, $this);
} else if ($this->connection->getDatabasePlatform() instanceof SqlitePlatform) {
- return new SqliteExpressionBuilder($this->connection);
+ return new SqliteExpressionBuilder($this->connection, $this);
} else {
- return new ExpressionBuilder($this->connection);
+ return new ExpressionBuilder($this->connection, $this);
}
}
@@ -379,12 +379,14 @@ class QueryBuilder implements IQueryBuilder {
* ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
* </code>
*
- * @param mixed $select The selection expressions.
+ * @param mixed ...$selects The selection expressions.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
*/
- public function select($select = null) {
- $selects = is_array($select) ? $select : func_get_args();
+ public function select(...$selects) {
+ if (count($selects) === 1 && is_array($selects[0])) {
+ $selects = $selects[0];
+ }
$this->queryBuilder->select(
$this->helper->quoteColumnNames($selects)
@@ -450,12 +452,14 @@ class QueryBuilder implements IQueryBuilder {
* ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id');
* </code>
*
- * @param mixed $select The selection expression.
+ * @param mixed ...$selects The selection expression.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
*/
- public function addSelect($select = null) {
- $selects = is_array($select) ? $select : func_get_args();
+ public function addSelect(...$selects) {
+ if (count($selects) === 1 && is_array($selects[0])) {
+ $selects = $selects[0];
+ }
$this->queryBuilder->addSelect(
$this->helper->quoteColumnNames($selects)
@@ -725,14 +729,14 @@ class QueryBuilder implements IQueryBuilder {
* ->where($or);
* </code>
*
- * @param mixed $predicates The restriction predicates.
+ * @param mixed ...$predicates The restriction predicates.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
*/
- public function where($predicates) {
+ public function where(...$predicates) {
call_user_func_array(
[$this->queryBuilder, 'where'],
- func_get_args()
+ $predicates
);
return $this;
@@ -750,16 +754,16 @@ class QueryBuilder implements IQueryBuilder {
* ->andWhere('u.is_active = 1');
* </code>
*
- * @param mixed $where The query restrictions.
+ * @param mixed ...$where The query restrictions.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
*
* @see where()
*/
- public function andWhere($where) {
+ public function andWhere(...$where) {
call_user_func_array(
[$this->queryBuilder, 'andWhere'],
- func_get_args()
+ $where
);
return $this;
@@ -777,16 +781,16 @@ class QueryBuilder implements IQueryBuilder {
* ->orWhere('u.id = 2');
* </code>
*
- * @param mixed $where The WHERE statement.
+ * @param mixed ...$where The WHERE statement.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
*
* @see where()
*/
- public function orWhere($where) {
+ public function orWhere(...$where) {
call_user_func_array(
[$this->queryBuilder, 'orWhere'],
- func_get_args()
+ $where
);
return $this;
@@ -803,12 +807,14 @@ class QueryBuilder implements IQueryBuilder {
* ->groupBy('u.id');
* </code>
*
- * @param mixed $groupBy The grouping expression.
+ * @param mixed ...$groupBys The grouping expression.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
*/
- public function groupBy($groupBy) {
- $groupBys = is_array($groupBy) ? $groupBy : func_get_args();
+ public function groupBy(...$groupBys) {
+ if (count($groupBys) === 1 && is_array($groupBys[0])) {
+ $groupBys = $groupBys[0];
+ }
call_user_func_array(
[$this->queryBuilder, 'groupBy'],
@@ -829,12 +835,14 @@ class QueryBuilder implements IQueryBuilder {
* ->addGroupBy('u.createdAt')
* </code>
*
- * @param mixed $groupBy The grouping expression.
+ * @param mixed ...$groupBy The grouping expression.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
*/
- public function addGroupBy($groupBy) {
- $groupBys = is_array($groupBy) ? $groupBy : func_get_args();
+ public function addGroupBy(...$groupBys) {
+ if (count($groupBys) === 1 && is_array($groupBys[0])) {
+ $$groupBys = $groupBys[0];
+ }
call_user_func_array(
[$this->queryBuilder, 'addGroupBy'],
@@ -906,14 +914,14 @@ class QueryBuilder implements IQueryBuilder {
* Specifies a restriction over the groups of the query.
* Replaces any previous having restrictions, if any.
*
- * @param mixed $having The restriction over the groups.
+ * @param mixed ...$having The restriction over the groups.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
*/
- public function having($having) {
+ public function having(...$having) {
call_user_func_array(
[$this->queryBuilder, 'having'],
- func_get_args()
+ $having
);
return $this;
@@ -923,14 +931,14 @@ class QueryBuilder implements IQueryBuilder {
* Adds a restriction over the groups of the query, forming a logical
* conjunction with any existing having restrictions.
*
- * @param mixed $having The restriction to append.
+ * @param mixed ...$having The restriction to append.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
*/
- public function andHaving($having) {
+ public function andHaving(...$having) {
call_user_func_array(
[$this->queryBuilder, 'andHaving'],
- func_get_args()
+ $having
);
return $this;
@@ -940,14 +948,14 @@ class QueryBuilder implements IQueryBuilder {
* Adds a restriction over the groups of the query, forming a logical
* disjunction with any existing having restrictions.
*
- * @param mixed $having The restriction to add.
+ * @param mixed ...$having The restriction to add.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
*/
- public function orHaving($having) {
+ public function orHaving(...$having) {
call_user_func_array(
[$this->queryBuilder, 'orHaving'],
- func_get_args()
+ $having
);
return $this;
diff --git a/lib/private/DB/ReconnectWrapper.php b/lib/private/DB/ReconnectWrapper.php
new file mode 100644
index 00000000000..27a34c862a7
--- /dev/null
+++ b/lib/private/DB/ReconnectWrapper.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\DB;
+
+use Doctrine\Common\EventManager;
+use Doctrine\DBAL\Configuration;
+use Doctrine\DBAL\Driver;
+
+class ReconnectWrapper extends \Doctrine\DBAL\Connection {
+ const CHECK_CONNECTION_INTERVAL = 60;
+
+ private $lastConnectionCheck = null;
+
+ public function __construct(array $params, Driver $driver, Configuration $config = null, EventManager $eventManager = null) {
+ parent::__construct($params, $driver, $config, $eventManager);
+ $this->lastConnectionCheck = time();
+ }
+
+ public function connect() {
+ $now = time();
+ $checkTime = $now - self::CHECK_CONNECTION_INTERVAL;
+
+ if ($this->lastConnectionCheck > $checkTime || $this->isTransactionActive()) {
+ return parent::connect();
+ } else {
+ $this->lastConnectionCheck = $now;
+ if (!$this->ping()) {
+ $this->close();
+ }
+ return parent::connect();
+ }
+ }
+}
diff --git a/lib/private/DB/SchemaWrapper.php b/lib/private/DB/SchemaWrapper.php
index 4f05b7b00ef..35aae082699 100644
--- a/lib/private/DB/SchemaWrapper.php
+++ b/lib/private/DB/SchemaWrapper.php
@@ -23,7 +23,6 @@
namespace OC\DB;
-use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\Schema;
use OCP\DB\ISchemaWrapper;
use OCP\IDBConnection;
diff --git a/lib/private/DateTimeZone.php b/lib/private/DateTimeZone.php
index 59da2f601ab..5bd5735226c 100644
--- a/lib/private/DateTimeZone.php
+++ b/lib/private/DateTimeZone.php
@@ -26,6 +26,7 @@ namespace OC;
use OCP\IConfig;
use OCP\IDateTimeZone;
+use OCP\ILogger;
use OCP\ISession;
class DateTimeZone implements IDateTimeZone {
@@ -64,7 +65,7 @@ class DateTimeZone implements IDateTimeZone {
try {
return new \DateTimeZone($timeZone);
} catch (\Exception $e) {
- \OCP\Util::writeLog('datetimezone', 'Failed to created DateTimeZone "' . $timeZone . "'", \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('datetimezone', 'Failed to created DateTimeZone "' . $timeZone . "'", ILogger::DEBUG);
return new \DateTimeZone($this->getDefaultTimeZone());
}
}
@@ -109,7 +110,7 @@ class DateTimeZone implements IDateTimeZone {
}
// No timezone found, fallback to UTC
- \OCP\Util::writeLog('datetimezone', 'Failed to find DateTimeZone for offset "' . $offset . "'", \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('datetimezone', 'Failed to find DateTimeZone for offset "' . $offset . "'", ILogger::DEBUG);
return new \DateTimeZone($this->getDefaultTimeZone());
}
}
diff --git a/lib/private/Encryption/Manager.php b/lib/private/Encryption/Manager.php
index fe34ef4555b..9bec1db73e3 100644
--- a/lib/private/Encryption/Manager.php
+++ b/lib/private/Encryption/Manager.php
@@ -101,15 +101,6 @@ class Manager implements IManager {
* @throws ServiceUnavailableException
*/
public function isReady() {
- // check if we are still in transit between the old and the new encryption
- $oldEncryption = $this->config->getAppValue('files_encryption', 'installed_version');
- if (!empty($oldEncryption)) {
- $warning = 'Installation is in transit between the old Encryption (ownCloud <= 8.0)
- and the new encryption. Please enable the "Default encryption module"
- and run \'occ encryption:migrate\'';
- $this->logger->warning($warning);
- return false;
- }
if ($this->isKeyStorageReady() === false) {
throw new ServiceUnavailableException('Key Storage is not ready');
diff --git a/lib/private/Encryption/Util.php b/lib/private/Encryption/Util.php
index fc0adbbd47b..ddd19ac6345 100644
--- a/lib/private/Encryption/Util.php
+++ b/lib/private/Encryption/Util.php
@@ -35,6 +35,7 @@ use OC\Files\Filesystem;
use OC\Files\View;
use OCP\Encryption\IEncryptionModule;
use OCP\IConfig;
+use OCP\IUser;
class Util {
@@ -271,9 +272,12 @@ class Util {
}
public function getUserWithAccessToMountPoint($users, $groups) {
- $result = array();
+ $result = [];
if (in_array('all', $users)) {
- $result = \OCP\User::getUsers();
+ $users = $this->userManager->search('', null, null);
+ $result = array_map(function(IUser $user) {
+ return $user->getUID();
+ }, $users);
} else {
$result = array_merge($result, $users);
diff --git a/lib/private/Federation/CloudFederationFactory.php b/lib/private/Federation/CloudFederationFactory.php
new file mode 100644
index 00000000000..11566dd44a9
--- /dev/null
+++ b/lib/private/Federation/CloudFederationFactory.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation;
+
+use OCP\Federation\ICloudFederationFactory;
+use OCP\Federation\ICloudFederationNotification;
+use OCP\Federation\ICloudFederationShare;
+
+class CloudFederationFactory implements ICloudFederationFactory {
+
+ /**
+ * get a CloudFederationShare Object to prepare a share you want to send
+ *
+ * @param string $shareWith
+ * @param string $name resource name (e.g. document.odt)
+ * @param string $description share description (optional)
+ * @param string $providerId resource UID on the provider side
+ * @param string $owner provider specific UID of the user who owns the resource
+ * @param string $ownerDisplayName display name of the user who shared the item
+ * @param string $sharedBy provider specific UID of the user who shared the resource
+ * @param string $sharedByDisplayName display name of the user who shared the resource
+ * @param string $sharedSecret used to authenticate requests across servers
+ * @param string $shareType ('group' or 'user' share)
+ * @param $resourceType ('file', 'calendar',...)
+ * @return ICloudFederationShare
+ *
+ * @since 14.0.0
+ */
+ public function getCloudFederationShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $sharedSecret, $shareType, $resourceType) {
+ return new CloudFederationShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $shareType, $resourceType, $sharedSecret);
+ }
+
+ /**
+ * get a Cloud FederationNotification object to prepare a notification you
+ * want to send
+ *
+ * @return ICloudFederationNotification
+ *
+ * @since 14.0.0
+ */
+ public function getCloudFederationNotification() {
+ return new CloudFederationNotification();
+ }
+}
diff --git a/lib/private/Federation/CloudFederationNotification.php b/lib/private/Federation/CloudFederationNotification.php
new file mode 100644
index 00000000000..62af67079e5
--- /dev/null
+++ b/lib/private/Federation/CloudFederationNotification.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation;
+
+use OCP\Federation\ICloudFederationNotification;
+
+/**
+ * Class CloudFederationNotification
+ *
+ * @package OC\Federation
+ *
+ * @since 14.0.0
+ */
+class CloudFederationNotification implements ICloudFederationNotification {
+
+ private $message = [];
+
+ /**
+ * add a message to the notification
+ *
+ * @param string $notificationType (e.g. SHARE_ACCEPTED)
+ * @param string $resourceType (e.g. file, calendar, contact,...)
+ * @param string $providerId id of the share
+ * @param array $notification payload of the notification
+ *
+ * @since 14.0.0
+ */
+ public function setMessage($notificationType, $resourceType, $providerId, array $notification) {
+ $this->message = [
+ 'notificationType' => $notificationType,
+ 'resourceType' => $resourceType,
+ 'providerId' => $providerId,
+ 'notification' => $notification,
+ ];
+
+ }
+
+ /**
+ * get message, ready to send out
+ *
+ * @return array
+ *
+ * @since 14.0.0
+ */
+ public function getMessage() {
+ return $this->message;
+ }
+}
diff --git a/lib/private/Federation/CloudFederationProviderManager.php b/lib/private/Federation/CloudFederationProviderManager.php
new file mode 100644
index 00000000000..94b2f052747
--- /dev/null
+++ b/lib/private/Federation/CloudFederationProviderManager.php
@@ -0,0 +1,243 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation;
+
+use OC\AppFramework\Http;
+use OCP\App\IAppManager;
+use OCP\Federation\Exceptions\ProviderDoesNotExistsException;
+use OCP\Federation\ICloudFederationNotification;
+use OCP\Federation\ICloudFederationProvider;
+use OCP\Federation\ICloudFederationProviderManager;
+use OCP\Federation\ICloudFederationShare;
+use OCP\Federation\ICloudIdManager;
+use OCP\Http\Client\IClientService;
+use OCP\ILogger;
+
+/**
+ * Class Manager
+ *
+ * Manage Cloud Federation Providers
+ *
+ * @package OC\Federation
+ */
+class CloudFederationProviderManager implements ICloudFederationProviderManager {
+
+ /** @var array list of available cloud federation providers */
+ private $cloudFederationProvider;
+
+ /** @var IAppManager */
+ private $appManager;
+
+ /** @var IClientService */
+ private $httpClientService;
+
+ /** @var ICloudIdManager */
+ private $cloudIdManager;
+
+ /** @var ILogger */
+ private $logger;
+
+ /** @var array cache OCM end-points */
+ private $ocmEndPoints = [];
+
+ private $supportedAPIVersion = '1.0-proposal1';
+
+ /**
+ * CloudFederationProviderManager constructor.
+ *
+ * @param IAppManager $appManager
+ * @param IClientService $httpClientService
+ * @param ICloudIdManager $cloudIdManager
+ * @param ILogger $logger
+ */
+ public function __construct(IAppManager $appManager,
+ IClientService $httpClientService,
+ ICloudIdManager $cloudIdManager,
+ ILogger $logger) {
+ $this->cloudFederationProvider= [];
+ $this->appManager = $appManager;
+ $this->httpClientService = $httpClientService;
+ $this->cloudIdManager = $cloudIdManager;
+ $this->logger = $logger;
+ }
+
+
+ /**
+ * Registers an callback function which must return an cloud federation provider
+ *
+ * @param string $resourceType which resource type does the provider handles
+ * @param string $displayName user facing name of the federated share provider
+ * @param callable $callback
+ */
+ public function addCloudFederationProvider($resourceType, $displayName, callable $callback) {
+ $this->cloudFederationProvider[$resourceType] = [
+ 'resourceType' => $resourceType,
+ 'displayName' => $displayName,
+ 'callback' => $callback,
+ ];
+
+ }
+
+ /**
+ * remove cloud federation provider
+ *
+ * @param string $providerId
+ */
+ public function removeCloudFederationProvider($providerId) {
+ unset($this->cloudFederationProvider[$providerId]);
+ }
+
+ /**
+ * get a list of all cloudFederationProviders
+ *
+ * @return array [resourceType => ['resourceType' => $resourceType, 'displayName' => $displayName, 'callback' => callback]]
+ */
+ public function getAllCloudFederationProviders() {
+ return $this->cloudFederationProvider;
+ }
+
+ /**
+ * get a specific cloud federation provider
+ *
+ * @param string $resourceType
+ * @return ICloudFederationProvider
+ * @throws ProviderDoesNotExistsException
+ */
+ public function getCloudFederationProvider($resourceType) {
+ if (isset($this->cloudFederationProvider[$resourceType])) {
+ return call_user_func($this->cloudFederationProvider[$resourceType]['callback']);
+ } else {
+ throw new ProviderDoesNotExistsException($resourceType);
+ }
+ }
+
+ public function sendShare(ICloudFederationShare $share) {
+ $cloudID = $this->cloudIdManager->resolveCloudId($share->getShareWith());
+ $ocmEndPoint = $this->getOCMEndPoint($cloudID->getRemote());
+
+ if (empty($ocmEndPoint)) {
+ return false;
+ }
+
+ $client = $this->httpClientService->newClient();
+ try {
+ $response = $client->post($ocmEndPoint . '/shares', [
+ 'body' => $share->getShare(),
+ 'timeout' => 10,
+ 'connect_timeout' => 10,
+ ]);
+
+ if ($response->getStatusCode() === Http::STATUS_CREATED) {
+ $result = json_decode($response->getBody(), true);
+ return (is_array($result)) ? $result : [];
+ }
+
+ } catch (\Exception $e) {
+ // if flat re-sharing is not supported by the remote server
+ // we re-throw the exception and fall back to the old behaviour.
+ // (flat re-shares has been introduced in Nextcloud 9.1)
+ if ($e->getCode() === Http::STATUS_INTERNAL_SERVER_ERROR) {
+ $this->logger->debug($e->getMessage());
+ throw $e;
+ }
+ }
+
+ return false;
+
+ }
+
+ /**
+ * @param string $url
+ * @param ICloudFederationNotification $notification
+ * @return mixed
+ */
+ public function sendNotification($url, ICloudFederationNotification $notification) {
+ $ocmEndPoint = $this->getOCMEndPoint($url);
+
+ if (empty($ocmEndPoint)) {
+ return false;
+ }
+
+ $client = $this->httpClientService->newClient();
+ try {
+ $response = $client->post($ocmEndPoint . '/notifications', [
+ 'body' => $notification->getMessage(),
+ 'timeout' => 10,
+ 'connect_timeout' => 10,
+ ]);
+ if ($response->getStatusCode() === Http::STATUS_CREATED) {
+ $result = json_decode($response->getBody(), true);
+ return (is_array($result)) ? $result : [];
+ }
+ } catch (\Exception $e) {
+ // log the error and return false
+ $this->logger->error('error while sending notification for federated share: ' . $e->getMessage());
+ }
+
+ return false;
+ }
+
+ /**
+ * check if the new cloud federation API is ready to be used
+ *
+ * @return bool
+ */
+ public function isReady() {
+ return $this->appManager->isEnabledForUser('cloud_federation_api');
+ }
+ /**
+ * check if server supports the new OCM api and ask for the correct end-point
+ *
+ * @param string $url full base URL of the cloud server
+ * @return string
+ */
+ protected function getOCMEndPoint($url) {
+
+ if (isset($this->ocmEndPoints[$url])) {
+ return $this->ocmEndPoints[$url];
+ }
+
+ $client = $this->httpClientService->newClient();
+ try {
+ $response = $client->get($url . '/ocm-provider/', ['timeout' => 10, 'connect_timeout' => 10]);
+ } catch (\Exception $e) {
+ $this->ocmEndPoints[$url] = '';
+ return '';
+ }
+
+ $result = $response->getBody();
+ $result = json_decode($result, true);
+
+ $supportedVersion = isset($result['apiVersion']) && $result['apiVersion'] === $this->supportedAPIVersion;
+
+ if (isset($result['endPoint']) && $supportedVersion) {
+ $this->ocmEndPoints[$url] = $result['endPoint'];
+ return $result['endPoint'];
+ }
+
+ $this->ocmEndPoints[$url] = '';
+ return '';
+ }
+
+
+}
diff --git a/lib/private/Federation/CloudFederationShare.php b/lib/private/Federation/CloudFederationShare.php
new file mode 100644
index 00000000000..e0360d78cb2
--- /dev/null
+++ b/lib/private/Federation/CloudFederationShare.php
@@ -0,0 +1,356 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation;
+
+use OCP\Federation\ICloudFederationShare;
+
+class CloudFederationShare implements ICloudFederationShare {
+
+ private $share = [
+ 'shareWith' => '',
+ 'shareType' => '',
+ 'name' => '',
+ 'resourceType' => '',
+ 'description' => '',
+ 'providerId' => '',
+ 'owner' => '',
+ 'ownerDisplayName' => '',
+ 'sharedBy' => '',
+ 'sharedByDisplayName' => '',
+ 'protocol' => []
+ ];
+
+ /**
+ * get a CloudFederationShare Object to prepare a share you want to send
+ *
+ * @param string $shareWith
+ * @param string $name resource name (e.g. document.odt)
+ * @param string $description share description (optional)
+ * @param string $providerId resource UID on the provider side
+ * @param string $owner provider specific UID of the user who owns the resource
+ * @param string $ownerDisplayName display name of the user who shared the item
+ * @param string $sharedBy provider specific UID of the user who shared the resource
+ * @param string $sharedByDisplayName display name of the user who shared the resource
+ * @param string $shareType ('group' or 'user' share)
+ * @param string $resourceType ('file', 'calendar',...)
+ * @param string $sharedSecret
+ */
+ public function __construct($shareWith = '',
+ $name = '',
+ $description = '',
+ $providerId = '',
+ $owner = '',
+ $ownerDisplayName = '',
+ $sharedBy = '',
+ $sharedByDisplayName = '',
+ $shareType = '',
+ $resourceType = '',
+ $sharedSecret = ''
+ ) {
+ $this->setShareWith($shareWith);
+ $this->setResourceName($name);
+ $this->setDescription($description);
+ $this->setProviderId($providerId);
+ $this->setOwner($owner);
+ $this->setOwnerDisplayName($ownerDisplayName);
+ $this->setSharedBy($sharedBy);
+ $this->setSharedByDisplayName($sharedByDisplayName);
+ $this->setProtocol([
+ 'name' => 'webdav',
+ 'options' => [
+ 'sharedSecret' => $sharedSecret,
+ 'permissions' => '{http://open-cloud-mesh.org/ns}share-permissions'
+ ]
+ ]);
+ $this->setShareType($shareType);
+ $this->setResourceType($resourceType);
+
+ }
+
+ /**
+ * set uid of the recipient
+ *
+ * @param string $user
+ *
+ * @since 14.0.0
+ */
+ public function setShareWith($user) {
+ $this->share['shareWith'] = $user;
+ }
+
+ /**
+ * set resource name (e.g. document.odt)
+ *
+ * @param string $name
+ *
+ * @since 14.0.0
+ */
+ public function setResourceName($name) {
+ $this->share['name'] = $name;
+ }
+
+ /**
+ * set resource type (e.g. file, calendar, contact,...)
+ *
+ * @param string $resourceType
+ *
+ * @since 14.0.0
+ */
+ public function setResourceType($resourceType) {
+ $this->share['resourceType'] = $resourceType;
+ }
+
+ /**
+ * set resource description (optional)
+ *
+ * @param string $description
+ *
+ * @since 14.0.0
+ */
+ public function setDescription($description) {
+ $this->share['description'] = $description;
+ }
+
+ /**
+ * set provider ID (e.g. file ID)
+ *
+ * @param string $providerId
+ *
+ * @since 14.0.0
+ */
+ public function setProviderId($providerId) {
+ $this->share['providerId'] = $providerId;
+ }
+
+ /**
+ * set owner UID
+ *
+ * @param string $owner
+ *
+ * @since 14.0.0
+ */
+ public function setOwner($owner) {
+ $this->share['owner'] = $owner;
+ }
+
+ /**
+ * set owner display name
+ *
+ * @param string $ownerDisplayName
+ *
+ * @since 14.0.0
+ */
+ public function setOwnerDisplayName($ownerDisplayName) {
+ $this->share['ownerDisplayName'] = $ownerDisplayName;
+ }
+
+ /**
+ * set UID of the user who sends the share
+ *
+ * @param string $sharedBy
+ *
+ * @since 14.0.0
+ */
+ public function setSharedBy($sharedBy) {
+ $this->share['sharedBy'] = $sharedBy;
+ }
+
+ /**
+ * set display name of the user who sends the share
+ *
+ * @param $sharedByDisplayName
+ *
+ * @since 14.0.0
+ */
+ public function setSharedByDisplayName($sharedByDisplayName) {
+ $this->share['sharedByDisplayName'] = $sharedByDisplayName;
+ }
+
+ /**
+ * set protocol specification
+ *
+ * @param array $protocol
+ *
+ * @since 14.0.0
+ */
+ public function setProtocol(array $protocol) {
+ $this->share['protocol'] = $protocol;
+ }
+
+ /**
+ * share type (group or user)
+ *
+ * @param string $shareType
+ *
+ * @since 14.0.0
+ */
+ public function setShareType($shareType) {
+ if ($shareType === 'group' || $shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
+ $this->share['shareType'] = 'group';
+ } else {
+ $this->share['shareType'] = 'user';
+ }
+ }
+
+ /**
+ * get the whole share, ready to send out
+ *
+ * @return array
+ *
+ * @since 14.0.0
+ */
+ public function getShare() {
+ return $this->share;
+ }
+
+ /**
+ * get uid of the recipient
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getShareWith() {
+ return $this->share['shareWith'];
+ }
+
+ /**
+ * get resource name (e.g. file, calendar, contact,...)
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getResourceName() {
+ return $this->share['name'];
+ }
+
+ /**
+ * get resource type (e.g. file, calendar, contact,...)
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getResourceType() {
+ return $this->share['resourceType'];
+ }
+
+ /**
+ * get resource description (optional)
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getDescription() {
+ return $this->share['description'];
+ }
+
+ /**
+ * get provider ID (e.g. file ID)
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getProviderId() {
+ return $this->share['providerId'];
+ }
+
+ /**
+ * get owner UID
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getOwner() {
+ return $this->share['owner'];
+ }
+
+ /**
+ * get owner display name
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getOwnerDisplayName() {
+ return $this->share['ownerDisplayName'];
+ }
+
+ /**
+ * get UID of the user who sends the share
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getSharedBy() {
+ return $this->share['sharedBy'];
+ }
+
+ /**
+ * get display name of the user who sends the share
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getSharedByDisplayName() {
+ return $this->share['sharedByDisplayName'];
+ }
+
+ /**
+ * get share type (group or user)
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getShareType() {
+ return $this->share['shareType'];
+ }
+
+ /**
+ * get share Secret
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getShareSecret() {
+ return $this->share['protocol']['options']['sharedSecret'];
+ }
+
+ /**
+ * get protocol specification
+ *
+ * @return array
+ *
+ * @since 14.0.0
+ */
+ public function getProtocol() {
+ return $this->share['protocol'];
+ }
+}
diff --git a/lib/private/Files/AppData/AppData.php b/lib/private/Files/AppData/AppData.php
index 270e834b8e5..e25bf450446 100644
--- a/lib/private/Files/AppData/AppData.php
+++ b/lib/private/Files/AppData/AppData.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
*
@@ -31,6 +32,7 @@ use OC\SystemConfig;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
+use OCP\Files\SimpleFS\ISimpleFolder;
class AppData implements IAppData {
@@ -55,7 +57,7 @@ class AppData implements IAppData {
*/
public function __construct(IRootFolder $rootFolder,
SystemConfig $systemConfig,
- $appId) {
+ string $appId) {
$this->rootFolder = $rootFolder;
$this->config = $systemConfig;
@@ -66,7 +68,7 @@ class AppData implements IAppData {
* @return Folder
* @throws \RuntimeException
*/
- private function getAppDataFolder() {
+ private function getAppDataFolder(): Folder {
if ($this->folder === null) {
$instanceId = $this->config->getValue('instanceid', null);
if ($instanceId === null) {
@@ -101,20 +103,20 @@ class AppData implements IAppData {
return $this->folder;
}
- public function getFolder($name) {
+ public function getFolder(string $name): ISimpleFolder {
$node = $this->getAppDataFolder()->get($name);
/** @var Folder $node */
return new SimpleFolder($node);
}
- public function newFolder($name) {
+ public function newFolder(string $name): ISimpleFolder {
$folder = $this->getAppDataFolder()->newFolder($name);
return new SimpleFolder($folder);
}
- public function getDirectoryListing() {
+ public function getDirectoryListing(): array {
$listing = $this->getAppDataFolder()->getDirectoryListing();
$fileListing = array_map(function(Node $folder) {
@@ -128,4 +130,8 @@ class AppData implements IAppData {
return array_values($fileListing);
}
+
+ public function getId(): int {
+ return $this->getAppDataFolder()->getId();
+ }
}
diff --git a/lib/private/Files/AppData/Factory.php b/lib/private/Files/AppData/Factory.php
index 85c75733796..fba2232db06 100644
--- a/lib/private/Files/AppData/Factory.php
+++ b/lib/private/Files/AppData/Factory.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl>
*
@@ -44,7 +45,7 @@ class Factory {
* @param string $appId
* @return AppData
*/
- public function get($appId) {
+ public function get(string $appId): AppData {
return new AppData($this->rootFolder, $this->config, $appId);
}
}
diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php
index 8f5f09319dd..ca9a0b794f9 100644
--- a/lib/private/Files/Cache/Scanner.php
+++ b/lib/private/Files/Cache/Scanner.php
@@ -38,6 +38,7 @@ use OC\Files\Filesystem;
use OC\Hooks\BasicEmitter;
use OCP\Files\Cache\IScanner;
use OCP\Files\ForbiddenException;
+use OCP\ILogger;
use OCP\Lock\ILockingProvider;
/**
@@ -110,7 +111,7 @@ class Scanner extends BasicEmitter implements IScanner {
protected function getData($path) {
$data = $this->storage->getMetaData($path);
if (is_null($data)) {
- \OCP\Util::writeLog(Scanner::class, "!!! Path '$path' is not accessible or present !!!", \OCP\Util::DEBUG);
+ \OCP\Util::writeLog(Scanner::class, "!!! Path '$path' is not accessible or present !!!", ILogger::DEBUG);
}
return $data;
}
@@ -331,15 +332,18 @@ class Scanner extends BasicEmitter implements IScanner {
$this->storage->acquireLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
}
}
- $data = $this->scanFile($path, $reuse, -1, null, $lock);
- if ($data and $data['mimetype'] === 'httpd/unix-directory') {
- $size = $this->scanChildren($path, $recursive, $reuse, $data['fileid'], $lock);
- $data['size'] = $size;
- }
- if ($lock) {
- if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
- $this->storage->releaseLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
- $this->storage->releaseLock('scanner::' . $path, ILockingProvider::LOCK_EXCLUSIVE, $this->lockingProvider);
+ try {
+ $data = $this->scanFile($path, $reuse, -1, null, $lock);
+ if ($data and $data['mimetype'] === 'httpd/unix-directory') {
+ $size = $this->scanChildren($path, $recursive, $reuse, $data['fileid'], $lock);
+ $data['size'] = $size;
+ }
+ } finally {
+ if ($lock) {
+ if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
+ $this->storage->releaseLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
+ $this->storage->releaseLock('scanner::' . $path, ILockingProvider::LOCK_EXCLUSIVE, $this->lockingProvider);
+ }
}
}
return $data;
@@ -454,7 +458,7 @@ class Scanner extends BasicEmitter implements IScanner {
}
\OC::$server->getLogger()->logException($ex, [
'message' => 'Exception while scanning file "' . $child . '"',
- 'level' => \OCP\Util::DEBUG,
+ 'level' => ILogger::DEBUG,
'app' => 'core',
]);
$exceptionOccurred = true;
diff --git a/lib/private/Files/Cache/Wrapper/CacheJail.php b/lib/private/Files/Cache/Wrapper/CacheJail.php
index 1ad00ba44c5..75df45e257b 100644
--- a/lib/private/Files/Cache/Wrapper/CacheJail.php
+++ b/lib/private/Files/Cache/Wrapper/CacheJail.php
@@ -29,6 +29,7 @@
namespace OC\Files\Cache\Wrapper;
use OC\Files\Cache\Cache;
+use OC\Files\Search\SearchQuery;
use OCP\Files\Cache\ICacheEntry;
use OCP\Files\Search\ISearchQuery;
@@ -236,8 +237,14 @@ class CacheJail extends CacheWrapper {
}
public function searchQuery(ISearchQuery $query) {
- $results = $this->getCache()->searchQuery($query);
- return $this->formatSearchResults($results);
+ $simpleQuery = new SearchQuery($query->getSearchOperation(), 0, 0, $query->getOrder(), $query->getUser());
+ $results = $this->getCache()->searchQuery($simpleQuery);
+ $results = $this->formatSearchResults($results);
+
+ $limit = $query->getLimit() === 0 ? NULL : $query->getLimit();
+ $results = array_slice($results, $query->getOffset(), $limit);
+
+ return $results;
}
/**
diff --git a/lib/private/Files/Config/MountProviderCollection.php b/lib/private/Files/Config/MountProviderCollection.php
index f3252f0fd65..a3c88dd6b4b 100644
--- a/lib/private/Files/Config/MountProviderCollection.php
+++ b/lib/private/Files/Config/MountProviderCollection.php
@@ -57,6 +57,9 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
*/
private $mountCache;
+ /** @var callable[] */
+ private $mountFilters = [];
+
/**
* @param \OCP\Files\Storage\IStorageFactory $loader
* @param IUserMountCache $mountCache
@@ -80,9 +83,10 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
$mounts = array_filter($mounts, function ($result) {
return is_array($result);
});
- return array_reduce($mounts, function (array $mounts, array $providerMounts) {
+ $mounts = array_reduce($mounts, function (array $mounts, array $providerMounts) {
return array_merge($mounts, $providerMounts);
}, array());
+ return $this->filterMounts($user, $mounts);
}
public function addMountForUser(IUser $user, IMountManager $mountManager) {
@@ -101,6 +105,7 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
$firstMounts = array_merge($firstMounts, $mounts);
}
}
+ $firstMounts = $this->filterMounts($user, $firstMounts);
array_walk($firstMounts, [$mountManager, 'addMount']);
$lateMounts = [];
@@ -111,6 +116,7 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
}
}
+ $lateMounts = $this->filterMounts($user, $lateMounts);
array_walk($lateMounts, [$mountManager, 'addMount']);
return array_merge($lateMounts, $firstMounts);
@@ -146,6 +152,21 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
$this->emit('\OC\Files\Config', 'registerMountProvider', [$provider]);
}
+ public function registerMountFilter(callable $filter) {
+ $this->mountFilters[] = $filter;
+ }
+
+ private function filterMounts(IUser $user, array $mountPoints) {
+ return array_filter($mountPoints, function (IMountPoint $mountPoint) use ($user) {
+ foreach ($this->mountFilters as $filter) {
+ if ($filter($mountPoint, $user) === false) {
+ return false;
+ }
+ }
+ return true;
+ });
+ }
+
/**
* Add a provider for home mount points
*
diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php
index 384e6e5e457..a6741652308 100644
--- a/lib/private/Files/Config/UserMountCache.php
+++ b/lib/private/Files/Config/UserMountCache.php
@@ -25,7 +25,6 @@
namespace OC\Files\Config;
-use OC\DB\QueryBuilder\Literal;
use OCA\Files_Sharing\SharedMount;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\Config\ICachedMountFileInfo;
@@ -376,7 +375,7 @@ class UserMountCache implements IUserMountCache {
->innerJoin('m', 'filecache', 'f',
$builder->expr()->andX(
$builder->expr()->eq('m.storage_id', 'f.storage'),
- $builder->expr()->eq('f.path', $builder->createNamedParameter('files'))
+ $builder->expr()->eq('f.path_hash', $builder->createNamedParameter(md5('files')))
))
->where($builder->expr()->eq('m.mount_point', $mountPoint))
->andWhere($builder->expr()->in('m.user_id', $builder->createNamedParameter($userIds, IQueryBuilder::PARAM_STR_ARRAY)));
diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php
index 95703eab925..12e59e5ba2d 100644
--- a/lib/private/Files/Filesystem.php
+++ b/lib/private/Files/Filesystem.php
@@ -65,6 +65,7 @@ use OC\Files\Storage\StorageFactory;
use OC\Lockdown\Filesystem\NullStorage;
use OCP\Files\Config\IMountProvider;
use OCP\Files\NotFoundException;
+use OCP\ILogger;
use OCP\IUserManager;
class Filesystem {
@@ -408,7 +409,7 @@ class Filesystem {
$userObject = $userManager->get($user);
if (is_null($userObject)) {
- \OCP\Util::writeLog('files', ' Backends provided no user object for ' . $user, \OCP\Util::ERROR);
+ \OCP\Util::writeLog('files', ' Backends provided no user object for ' . $user, ILogger::ERROR);
// reset flag, this will make it possible to rethrow the exception if called again
unset(self::$usersSetup[$user]);
throw new \OC\User\NoUserException('Backends provided no user object for ' . $user);
@@ -418,7 +419,7 @@ class Filesystem {
// workaround in case of different casings
if ($user !== $realUid) {
$stack = json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 50));
- \OCP\Util::writeLog('files', 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "' . $realUid . '" got "' . $user . '". Stack: ' . $stack, \OCP\Util::WARN);
+ \OCP\Util::writeLog('files', 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "' . $realUid . '" got "' . $user . '". Stack: ' . $stack, ILogger::WARN);
$user = $realUid;
// again with the correct casing
@@ -794,7 +795,7 @@ class Filesystem {
*/
public static function normalizePath($path, $stripTrailingSlash = true, $isAbsolutePath = false, $keepUnicode = false) {
if (is_null(self::$normalizedPathCache)) {
- self::$normalizedPathCache = new CappedMemoryCache();
+ self::$normalizedPathCache = new CappedMemoryCache(2048);
}
/**
diff --git a/lib/private/Files/Mount/Manager.php b/lib/private/Files/Mount/Manager.php
index 7bd888a6389..019dda03a40 100644
--- a/lib/private/Files/Mount/Manager.php
+++ b/lib/private/Files/Mount/Manager.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -25,69 +26,86 @@
namespace OC\Files\Mount;
-use \OC\Files\Filesystem;
+use OC\Cache\CappedMemoryCache;
+use OC\Files\Filesystem;
use OCP\Files\Mount\IMountManager;
use OCP\Files\Mount\IMountPoint;
class Manager implements IMountManager {
- /**
- * @var MountPoint[]
- */
- private $mounts = array();
+ /** @var MountPoint[] */
+ private $mounts = [];
+
+ /** @var CappedMemoryCache */
+ private $pathCache;
+
+ public function __construct() {
+ $this->pathCache = new CappedMemoryCache();
+ }
/**
* @param IMountPoint $mount
*/
public function addMount(IMountPoint $mount) {
$this->mounts[$mount->getMountPoint()] = $mount;
+ $this->pathCache->clear();
}
/**
* @param string $mountPoint
*/
- public function removeMount($mountPoint) {
+ public function removeMount(string $mountPoint) {
$mountPoint = Filesystem::normalizePath($mountPoint);
- if (strlen($mountPoint) > 1) {
+ if (\strlen($mountPoint) > 1) {
$mountPoint .= '/';
}
unset($this->mounts[$mountPoint]);
+ $this->pathCache->clear();
}
/**
* @param string $mountPoint
* @param string $target
*/
- public function moveMount($mountPoint, $target){
+ public function moveMount(string $mountPoint, string $target){
$this->mounts[$target] = $this->mounts[$mountPoint];
unset($this->mounts[$mountPoint]);
+ $this->pathCache->clear();
}
/**
* Find the mount for $path
*
* @param string $path
- * @return MountPoint
+ * @return MountPoint|null
*/
- public function find($path) {
+ public function find(string $path) {
\OC_Util::setupFS();
$path = $this->formatPath($path);
if (isset($this->mounts[$path])) {
return $this->mounts[$path];
}
- \OC_Hook::emit('OC_Filesystem', 'get_mountpoint', array('path' => $path));
+ if (isset($this->pathCache[$path])) {
+ return $this->pathCache[$path];
+ }
+
+ \OC_Hook::emit('OC_Filesystem', 'get_mountpoint', ['path' => $path]);
$foundMountPoint = '';
$mountPoints = array_keys($this->mounts);
+ $foundMountPointLength = 0;
foreach ($mountPoints as $mountpoint) {
- if (strpos($path, $mountpoint) === 0 and strlen($mountpoint) > strlen($foundMountPoint)) {
+ if (\strlen($mountpoint) > $foundMountPointLength && strpos($path, $mountpoint) === 0) {
$foundMountPoint = $mountpoint;
+ $foundMountPointLength = \strlen($foundMountPoint);
}
}
+
if (isset($this->mounts[$foundMountPoint])) {
+ $this->pathCache[$path] = $this->mounts[$foundMountPoint];
return $this->mounts[$foundMountPoint];
- } else {
- return null;
}
+
+ return null;
}
/**
@@ -96,14 +114,14 @@ class Manager implements IMountManager {
* @param string $path
* @return MountPoint[]
*/
- public function findIn($path) {
+ public function findIn(string $path): array {
\OC_Util::setupFS();
$path = $this->formatPath($path);
- $result = array();
- $pathLength = strlen($path);
+ $result = [];
+ $pathLength = \strlen($path);
$mountPoints = array_keys($this->mounts);
foreach ($mountPoints as $mountPoint) {
- if (substr($mountPoint, 0, $pathLength) === $path and strlen($mountPoint) > $pathLength) {
+ if (substr($mountPoint, 0, $pathLength) === $path && \strlen($mountPoint) > $pathLength) {
$result[] = $this->mounts[$mountPoint];
}
}
@@ -111,7 +129,8 @@ class Manager implements IMountManager {
}
public function clear() {
- $this->mounts = array();
+ $this->mounts = [];
+ $this->pathCache->clear();
}
/**
@@ -120,12 +139,12 @@ class Manager implements IMountManager {
* @param string $id
* @return MountPoint[]
*/
- public function findByStorageId($id) {
+ public function findByStorageId(string $id): array {
\OC_Util::setupFS();
- if (strlen($id) > 64) {
+ if (\strlen($id) > 64) {
$id = md5($id);
}
- $result = array();
+ $result = [];
foreach ($this->mounts as $mount) {
if ($mount->getStorageId() === $id) {
$result[] = $mount;
@@ -137,7 +156,7 @@ class Manager implements IMountManager {
/**
* @return MountPoint[]
*/
- public function getAll() {
+ public function getAll(): array {
return $this->mounts;
}
@@ -147,7 +166,7 @@ class Manager implements IMountManager {
* @param int $id
* @return MountPoint[]
*/
- public function findByNumericId($id) {
+ public function findByNumericId(int $id): array {
$storageId = \OC\Files\Cache\Storage::getStorageId($id);
return $this->findByStorageId($storageId);
}
@@ -156,9 +175,9 @@ class Manager implements IMountManager {
* @param string $path
* @return string
*/
- private function formatPath($path) {
+ private function formatPath(string $path): string {
$path = Filesystem::normalizePath($path);
- if (strlen($path) > 1) {
+ if (\strlen($path) > 1) {
$path .= '/';
}
return $path;
diff --git a/lib/private/Files/Mount/MountPoint.php b/lib/private/Files/Mount/MountPoint.php
index 26150de2bd1..36e10bfb45a 100644
--- a/lib/private/Files/Mount/MountPoint.php
+++ b/lib/private/Files/Mount/MountPoint.php
@@ -33,6 +33,7 @@ use \OC\Files\Filesystem;
use OC\Files\Storage\StorageFactory;
use OC\Files\Storage\Storage;
use OCP\Files\Mount\IMountPoint;
+use OCP\ILogger;
class MountPoint implements IMountPoint {
/**
@@ -152,12 +153,12 @@ class MountPoint implements IMountPoint {
// the root storage could not be initialized, show the user!
throw new \Exception('The root storage could not be initialized. Please contact your local administrator.', $exception->getCode(), $exception);
} else {
- \OC::$server->getLogger()->logException($exception, ['level' => \OCP\Util::ERROR]);
+ \OC::$server->getLogger()->logException($exception, ['level' => ILogger::ERROR]);
}
return;
}
} else {
- \OCP\Util::writeLog('core', 'storage backend ' . $this->class . ' not found', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'storage backend ' . $this->class . ' not found', ILogger::ERROR);
$this->invalidStorage = true;
return;
}
diff --git a/lib/private/Files/Mount/ObjectHomeMountProvider.php b/lib/private/Files/Mount/ObjectHomeMountProvider.php
index 440a8bc4608..62669020884 100644
--- a/lib/private/Files/Mount/ObjectHomeMountProvider.php
+++ b/lib/private/Files/Mount/ObjectHomeMountProvider.php
@@ -26,6 +26,7 @@ namespace OC\Files\Mount;
use OCP\Files\Config\IHomeMountProvider;
use OCP\Files\Storage\IStorageFactory;
use OCP\IConfig;
+use OCP\ILogger;
use OCP\IUser;
/**
@@ -79,15 +80,16 @@ class ObjectHomeMountProvider implements IHomeMountProvider {
// sanity checks
if (empty($config['class'])) {
- \OCP\Util::writeLog('files', 'No class given for objectstore', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('files', 'No class given for objectstore', ILogger::ERROR);
}
if (!isset($config['arguments'])) {
$config['arguments'] = [];
}
- $config['arguments']['user'] = $user;
// instantiate object store implementation
$config['arguments']['objectstore'] = new $config['class']($config['arguments']);
+ $config['arguments']['user'] = $user;
+
return $config;
}
@@ -103,7 +105,7 @@ class ObjectHomeMountProvider implements IHomeMountProvider {
// sanity checks
if (empty($config['class'])) {
- \OCP\Util::writeLog('files', 'No class given for objectstore', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('files', 'No class given for objectstore', ILogger::ERROR);
}
if (!isset($config['arguments'])) {
$config['arguments'] = [];
diff --git a/lib/private/Files/Node/File.php b/lib/private/Files/Node/File.php
index 4bfa5d583f7..7c411620ca0 100644
--- a/lib/private/Files/Node/File.php
+++ b/lib/private/Files/Node/File.php
@@ -26,6 +26,7 @@
namespace OC\Files\Node;
+use OCP\Files\GenericFileException;
use OCP\Files\NotPermittedException;
class File extends Node implements \OCP\Files\File {
@@ -55,13 +56,16 @@ class File extends Node implements \OCP\Files\File {
}
/**
- * @param string $data
+ * @param string|resource $data
* @throws \OCP\Files\NotPermittedException
+ * @throws \OCP\Files\GenericFileException
*/
public function putContent($data) {
if ($this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE)) {
$this->sendHooks(array('preWrite'));
- $this->view->file_put_contents($this->path, $data);
+ if ($this->view->file_put_contents($this->path, $data) === false) {
+ throw new GenericFileException('file_put_contents failed');
+ }
$this->fileInfo = null;
$this->sendHooks(array('postWrite'));
} else {
diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php
index fcadbe27393..0eb119eb0de 100644
--- a/lib/private/Files/Node/Folder.php
+++ b/lib/private/Files/Node/Folder.php
@@ -258,7 +258,7 @@ class Folder extends Node implements \OCP\Files\Folder {
if ($storage) {
$cache = $storage->getCache('');
- $relativeMountPoint = substr($mount->getMountPoint(), $rootLength);
+ $relativeMountPoint = ltrim(substr($mount->getMountPoint(), $rootLength), '/');
$results = call_user_func_array(array($cache, $method), $args);
foreach ($results as $result) {
$result['internalPath'] = $result['path'];
@@ -302,18 +302,15 @@ class Folder extends Node implements \OCP\Files\Folder {
return [];
}
- // we only need to get the cache info once, since all mounts we found point to the same storage
-
- $mount = $folderMounts[$mountsContainingFile[0]->getMountPoint()];
- $cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
- if (!$cacheEntry) {
- return [];
- }
- // cache jails will hide the "true" internal path
- $internalPath = ltrim($mountsContainingFile[0]->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
-
- $nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($cacheEntry, $folderMounts, $internalPath) {
+ $nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($folderMounts, $id) {
$mount = $folderMounts[$cachedMountInfo->getMountPoint()];
+ $cacheEntry = $mount->getStorage()->getCache()->get((int)$id);
+ if (!$cacheEntry) {
+ return null;
+ }
+
+ // cache jails will hide the "true" internal path
+ $internalPath = ltrim($cachedMountInfo->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/');
$pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath()));
$pathRelativeToMount = ltrim($pathRelativeToMount, '/');
$absolutePath = $cachedMountInfo->getMountPoint() . $pathRelativeToMount;
@@ -323,6 +320,8 @@ class Folder extends Node implements \OCP\Files\Folder {
));
}, $mountsContainingFile);
+ $nodes = array_filter($nodes);
+
return array_filter($nodes, function (Node $node) {
return $this->getRelativePath($node->getPath());
});
diff --git a/lib/private/Files/Node/HookConnector.php b/lib/private/Files/Node/HookConnector.php
index 27f65d9987b..f5adcde4a00 100644
--- a/lib/private/Files/Node/HookConnector.php
+++ b/lib/private/Files/Node/HookConnector.php
@@ -72,6 +72,8 @@ class HookConnector {
Util::connectHook('OC_Filesystem', 'touch', $this, 'touch');
Util::connectHook('OC_Filesystem', 'post_touch', $this, 'postTouch');
+
+ Util::connectHook('OC_Filesystem', 'read', $this, 'read');
}
public function write($arguments) {
@@ -140,6 +142,11 @@ class HookConnector {
$this->root->emit('\OC\Files', 'postCopy', [$source, $target]);
}
+ public function read($arguments) {
+ $node = $this->getNodeForPath($arguments['path']);
+ $this->root->emit('\OC\Files', 'read', [$node]);
+ }
+
private function getNodeForPath($path) {
$info = Filesystem::getView()->getFileInfo($path);
if (!$info) {
diff --git a/lib/private/Files/Node/Node.php b/lib/private/Files/Node/Node.php
index 304b2ccf464..d2232624b9b 100644
--- a/lib/private/Files/Node/Node.php
+++ b/lib/private/Files/Node/Node.php
@@ -265,7 +265,11 @@ class Node implements \OCP\Files\Node {
* @return Node
*/
public function getParent() {
- return $this->root->get(dirname($this->path));
+ $newPath = dirname($this->path);
+ if ($newPath === '' || $newPath === '.' || $newPath === '/') {
+ return $this->root;
+ }
+ return $this->root->get($newPath);
}
/**
diff --git a/lib/private/Files/ObjectStore/Azure.php b/lib/private/Files/ObjectStore/Azure.php
new file mode 100644
index 00000000000..899c826ec19
--- /dev/null
+++ b/lib/private/Files/ObjectStore/Azure.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Files\ObjectStore;
+
+use MicrosoftAzure\Storage\Blob\BlobRestProxy;
+use MicrosoftAzure\Storage\Common\Exceptions\ServiceException;
+use OCP\Files\ObjectStore\IObjectStore;
+
+class Azure implements IObjectStore {
+ /** @var string */
+ private $containerName;
+ /** @var string */
+ private $accountName;
+ /** @var string */
+ private $accountKey;
+ /** @var BlobRestProxy|null */
+ private $blobClient = null;
+ /** @var string|null */
+ private $endpoint = null;
+ /** @var bool */
+ private $autoCreate = false;
+
+ /**
+ * @param array $parameters
+ */
+ public function __construct($parameters) {
+ $this->containerName = $parameters['container'];
+ $this->accountName = $parameters['account_name'];
+ $this->accountKey = $parameters['account_key'];
+ if (isset($parameters['endpoint'])) {
+ $this->endpoint = $parameters['endpoint'];
+ }
+ if (isset($parameters['autocreate'])) {
+ $this->autoCreate = $parameters['autocreate'];
+ }
+ }
+
+ /**
+ * @return BlobRestProxy
+ */
+ private function getBlobClient() {
+ if (!$this->blobClient) {
+ $protocol = $this->endpoint ? substr($this->endpoint, 0, strpos($this->endpoint, ':')) : 'https';
+ $connectionString = "DefaultEndpointsProtocol=" . $protocol . ";AccountName=" . $this->accountName . ";AccountKey=" . $this->accountKey;
+ if ($this->endpoint) {
+ $connectionString .= ';BlobEndpoint=' . $this->endpoint;
+ }
+ $this->blobClient = BlobRestProxy::createBlobService($connectionString);
+
+ if ($this->autoCreate) {
+ try {
+ $this->blobClient->createContainer($this->containerName);
+ } catch (ServiceException $e) {
+ if ($e->getCode() === 409) {
+ // already exists
+ } else {
+ throw $e;
+ }
+ }
+ }
+ }
+ return $this->blobClient;
+ }
+
+ /**
+ * @return string the container or bucket name where objects are stored
+ */
+ public function getStorageId() {
+ return 'azure::blob::' . $this->containerName;
+ }
+
+ /**
+ * @param string $urn the unified resource name used to identify the object
+ * @return resource stream with the read data
+ * @throws \Exception when something goes wrong, message will be logged
+ */
+ public function readObject($urn) {
+ $blob = $this->getBlobClient()->getBlob($this->containerName, $urn);
+ return $blob->getContentStream();
+ }
+
+ /**
+ * @param string $urn the unified resource name used to identify the object
+ * @param resource $stream stream with the data to write
+ * @throws \Exception when something goes wrong, message will be logged
+ */
+ public function writeObject($urn, $stream) {
+ $this->getBlobClient()->createBlockBlob($this->containerName, $urn, $stream);
+ }
+
+ /**
+ * @param string $urn the unified resource name used to identify the object
+ * @return void
+ * @throws \Exception when something goes wrong, message will be logged
+ */
+ public function deleteObject($urn) {
+ $this->getBlobClient()->deleteBlob($this->containerName, $urn);
+ }
+}
diff --git a/lib/private/Files/ObjectStore/ObjectStoreStorage.php b/lib/private/Files/ObjectStore/ObjectStoreStorage.php
index 094a2915730..3ce919a4cbe 100644
--- a/lib/private/Files/ObjectStore/ObjectStoreStorage.php
+++ b/lib/private/Files/ObjectStore/ObjectStoreStorage.php
@@ -261,6 +261,12 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common {
public function fopen($path, $mode) {
$path = $this->normalizePath($path);
+ if (strrpos($path, '.') !== false) {
+ $ext = substr($path, strrpos($path, '.'));
+ } else {
+ $ext = '';
+ }
+
switch ($mode) {
case 'r':
case 'rb':
@@ -280,21 +286,21 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common {
}
case 'w':
case 'wb':
+ case 'w+':
+ case 'wb+':
+ $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
+ $handle = fopen($tmpFile, $mode);
+ return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
+ $this->writeBack($tmpFile, $path);
+ });
case 'a':
case 'ab':
case 'r+':
- case 'w+':
- case 'wb+':
case 'a+':
case 'x':
case 'x+':
case 'c':
case 'c+':
- if (strrpos($path, '.') !== false) {
- $ext = substr($path, strrpos($path, '.'));
- } else {
- $ext = '';
- }
$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
if ($this->file_exists($path)) {
$source = $this->fopen($path, 'r');
@@ -369,7 +375,7 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common {
'app' => 'objectstore',
'message' => 'Could not create object for ' . $path,
]);
- return false;
+ throw $ex;
}
}
return true;
@@ -423,4 +429,8 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common {
public function hasUpdated($path, $time) {
return false;
}
+
+ public function needsPartFile() {
+ return false;
+ }
}
diff --git a/lib/private/Files/ObjectStore/S3ConnectionTrait.php b/lib/private/Files/ObjectStore/S3ConnectionTrait.php
index 188012b7c1f..feca792848e 100644
--- a/lib/private/Files/ObjectStore/S3ConnectionTrait.php
+++ b/lib/private/Files/ObjectStore/S3ConnectionTrait.php
@@ -27,6 +27,7 @@ namespace OC\Files\ObjectStore;
use Aws\ClientResolver;
use Aws\S3\Exception\S3Exception;
use Aws\S3\S3Client;
+use OCP\ILogger;
trait S3ConnectionTrait {
/** @var array */
@@ -103,21 +104,28 @@ trait S3ConnectionTrait {
}
if (!$this->connection->doesBucketExist($this->bucket)) {
+ $logger = \OC::$server->getLogger();
try {
+ $logger->info('Bucket "' . $this->bucket . '" does not exist - creating it.', ['app' => 'objectstore']);
$this->connection->createBucket(array(
'Bucket' => $this->bucket
));
$this->testTimeout();
} catch (S3Exception $e) {
- \OC::$server->getLogger()->logException($e, [
+ $logger->logException($e, [
'message' => 'Invalid remote storage.',
- 'level' => \OCP\Util::DEBUG,
- 'app' => 'files_external',
+ 'level' => ILogger::DEBUG,
+ 'app' => 'objectstore',
]);
- throw new \Exception('Creation of bucket failed. ' . $e->getMessage());
+ throw new \Exception('Creation of bucket "' . $this->bucket . '" failed. ' . $e->getMessage());
}
}
+ // google cloud's s3 compatibility doesn't like the EncodingType parameter
+ if (strpos($base_url, 'storage.googleapis.com')) {
+ $this->connection->getHandlerList()->remove('s3.auto_encode');
+ }
+
return $this->connection;
}
diff --git a/lib/private/Files/ObjectStore/S3ObjectTrait.php b/lib/private/Files/ObjectStore/S3ObjectTrait.php
index 9c5cf9ccc6c..280a8efa81c 100644
--- a/lib/private/Files/ObjectStore/S3ObjectTrait.php
+++ b/lib/private/Files/ObjectStore/S3ObjectTrait.php
@@ -23,10 +23,7 @@
namespace OC\Files\ObjectStore;
-use Aws\Exception\MultipartUploadException;
-use Aws\S3\MultipartUploader;
use Aws\S3\S3Client;
-use Psr\Http\Message\StreamInterface;
const S3_UPLOAD_PART_SIZE = 524288000; // 500MB
@@ -75,51 +72,10 @@ trait S3ObjectTrait {
* @since 7.0.0
*/
function writeObject($urn, $stream) {
- $stat = fstat($stream);
-
- if ($stat['size'] && $stat['size'] < S3_UPLOAD_PART_SIZE) {
- $this->singlePartUpload($urn, $stream);
- } else {
- $this->multiPartUpload($urn, $stream);
- }
-
- }
-
- protected function singlePartUpload($urn, $stream) {
- $this->getConnection()->putObject([
- 'Bucket' => $this->bucket,
- 'Key' => $urn,
- 'Body' => $stream
- ]);
- }
-
- protected function multiPartUpload($urn, $stream) {
- $uploader = new MultipartUploader($this->getConnection(), $stream, [
- 'bucket' => $this->bucket,
- 'key' => $urn,
+ $this->getConnection()->upload($this->bucket, $urn, $stream, 'private', [
+ 'mup_threshold' => S3_UPLOAD_PART_SIZE,
'part_size' => S3_UPLOAD_PART_SIZE
]);
-
- $tries = 0;
-
- do {
- try {
- $result = $uploader->upload();
- } catch (MultipartUploadException $e) {
- \OC::$server->getLogger()->logException($e);
- rewind($stream);
- $tries++;
-
- if ($tries < 5) {
- $uploader = new MultipartUploader($this->getConnection(), $stream, [
- 'state' => $e->getState()
- ]);
- } else {
- $this->getConnection()->abortMultipartUpload($e->getState()->getId());
- throw $e;
- }
- }
- } while (!isset($result) && $tries < 5);
}
/**
diff --git a/lib/private/Files/ObjectStore/Swift.php b/lib/private/Files/ObjectStore/Swift.php
index 629fb3ba7ff..6bb01506c4c 100644
--- a/lib/private/Files/ObjectStore/Swift.php
+++ b/lib/private/Files/ObjectStore/Swift.php
@@ -25,263 +25,96 @@
namespace OC\Files\ObjectStore;
-use Guzzle\Http\Exception\ClientErrorResponseException;
+use function GuzzleHttp\Psr7\stream_for;
use Icewind\Streams\RetryWrapper;
use OCP\Files\ObjectStore\IObjectStore;
use OCP\Files\StorageAuthException;
-use OCP\Files\StorageNotAvailableException;
-use OpenCloud\Common\Service\Catalog;
-use OpenCloud\Common\Service\CatalogItem;
-use OpenCloud\Identity\Resource\Token;
-use OpenCloud\ObjectStore\Service;
-use OpenCloud\OpenStack;
-use OpenCloud\Rackspace;
class Swift implements IObjectStore {
-
- /**
- * @var \OpenCloud\OpenStack
- */
- private $client;
-
/**
* @var array
*/
private $params;
- /**
- * @var \OpenCloud\ObjectStore\Service
- */
- private $objectStoreService;
-
- /**
- * @var \OpenCloud\ObjectStore\Resource\Container
- */
- private $container;
-
- private $memcache;
-
- public function __construct($params) {
- if (isset($params['bucket'])) {
- $params['container'] = $params['bucket'];
- }
- if (!isset($params['container'])) {
- $params['container'] = 'owncloud';
- }
- if (!isset($params['autocreate'])) {
- // should only be true for tests
- $params['autocreate'] = false;
- }
-
- if (isset($params['apiKey'])) {
- $this->client = new Rackspace($params['url'], $params);
- $cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket'];
- } else {
- $this->client = new OpenStack($params['url'], $params);
- $cacheKey = $params['username'] . '@' . $params['url'] . '/' . $params['bucket'];
- }
-
- $cacheFactory = \OC::$server->getMemCacheFactory();
- $this->memcache = $cacheFactory->createDistributed('swift::' . $cacheKey);
+ /** @var SwiftFactory */
+ private $swiftFactory;
+ public function __construct($params, SwiftFactory $connectionFactory = null) {
+ $this->swiftFactory = $connectionFactory ?: new SwiftFactory(
+ \OC::$server->getMemCacheFactory()->createDistributed('swift::'),
+ $params,
+ \OC::$server->getLogger()
+ );
$this->params = $params;
}
- protected function init() {
- if ($this->container) {
- return;
- }
-
- $this->importToken();
-
- /** @var Token $token */
- $token = $this->client->getTokenObject();
-
- if (!$token || $token->hasExpired()) {
- try {
- $this->client->authenticate();
- $this->exportToken();
- } catch (ClientErrorResponseException $e) {
- $statusCode = $e->getResponse()->getStatusCode();
- if ($statusCode == 412) {
- throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
- } else if ($statusCode === 401) {
- throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
- } else {
- throw new StorageAuthException('Unknown error', $e);
- }
- }
- }
-
-
- /** @var Catalog $catalog */
- $catalog = $this->client->getCatalog();
-
- if (isset($this->params['serviceName'])) {
- $serviceName = $this->params['serviceName'];
- } else {
- $serviceName = Service::DEFAULT_NAME;
- }
-
- if (isset($this->params['urlType'])) {
- $urlType = $this->params['urlType'];
- if ($urlType !== 'internalURL' && $urlType !== 'publicURL') {
- throw new StorageNotAvailableException('Invalid url type');
- }
- } else {
- $urlType = Service::DEFAULT_URL_TYPE;
- }
-
- $catalogItem = $this->getCatalogForService($catalog, $serviceName);
- if (!$catalogItem) {
- $available = implode(', ', $this->getAvailableServiceNames($catalog));
- throw new StorageNotAvailableException(
- "Service $serviceName not found in service catalog, available services: $available"
- );
- } else if (isset($this->params['region'])) {
- $this->validateRegion($catalogItem, $this->params['region']);
- }
-
- $this->objectStoreService = $this->client->objectStoreService($serviceName, $this->params['region'], $urlType);
-
- try {
- $this->container = $this->objectStoreService->getContainer($this->params['container']);
- } catch (ClientErrorResponseException $ex) {
- // if the container does not exist and autocreate is true try to create the container on the fly
- if (isset($this->params['autocreate']) && $this->params['autocreate'] === true) {
- $this->container = $this->objectStoreService->createContainer($this->params['container']);
- } else {
- throw $ex;
- }
- }
- }
-
- private function exportToken() {
- $export = $this->client->exportCredentials();
- $export['catalog'] = array_map(function (CatalogItem $item) {
- return [
- 'name' => $item->getName(),
- 'endpoints' => $item->getEndpoints(),
- 'type' => $item->getType()
- ];
- }, $export['catalog']->getItems());
- $this->memcache->set('token', json_encode($export));
- }
-
- private function importToken() {
- $cachedTokenString = $this->memcache->get('token');
- if ($cachedTokenString) {
- $cachedToken = json_decode($cachedTokenString, true);
- $cachedToken['catalog'] = array_map(function (array $item) {
- $itemClass = new \stdClass();
- $itemClass->name = $item['name'];
- $itemClass->endpoints = array_map(function (array $endpoint) {
- return (object) $endpoint;
- }, $item['endpoints']);
- $itemClass->type = $item['type'];
-
- return $itemClass;
- }, $cachedToken['catalog']);
- try {
- $this->client->importCredentials($cachedToken);
- } catch (\Exception $e) {
- $this->client->setTokenObject(new Token());
- }
- }
- }
-
/**
- * @param Catalog $catalog
- * @param $name
- * @return null|CatalogItem
+ * @return \OpenStack\ObjectStore\v1\Models\Container
+ * @throws StorageAuthException
+ * @throws \OCP\Files\StorageNotAvailableException
*/
- private function getCatalogForService(Catalog $catalog, $name) {
- foreach ($catalog->getItems() as $item) {
- /** @var CatalogItem $item */
- if ($item->hasType(Service::DEFAULT_TYPE) && $item->hasName($name)) {
- return $item;
- }
- }
-
- return null;
- }
-
- private function validateRegion(CatalogItem $item, $region) {
- $endPoints = $item->getEndpoints();
- foreach ($endPoints as $endPoint) {
- if ($endPoint->region === $region) {
- return;
- }
- }
-
- $availableRegions = implode(', ', array_map(function ($endpoint) {
- return $endpoint->region;
- }, $endPoints));
-
- throw new StorageNotAvailableException("Invalid region '$region', available regions: $availableRegions");
- }
-
- private function getAvailableServiceNames(Catalog $catalog) {
- return array_map(function (CatalogItem $item) {
- return $item->getName();
- }, array_filter($catalog->getItems(), function (CatalogItem $item) {
- return $item->hasType(Service::DEFAULT_TYPE);
- }));
+ private function getContainer() {
+ return $this->swiftFactory->getContainer();
}
/**
* @return string the container name where objects are stored
*/
public function getStorageId() {
+ if (isset($this->params['bucket'])) {
+ return $this->params['bucket'];
+ }
+
return $this->params['container'];
}
/**
* @param string $urn the unified resource name used to identify the object
* @param resource $stream stream with the data to write
- * @throws Exception from openstack lib when something goes wrong
+ * @throws \Exception from openstack lib when something goes wrong
*/
public function writeObject($urn, $stream) {
- $this->init();
- $this->container->uploadObject($urn, $stream);
+ $this->getContainer()->createObject([
+ 'name' => $urn,
+ 'stream' => stream_for($stream)
+ ]);
}
/**
* @param string $urn the unified resource name used to identify the object
* @return resource stream with the read data
- * @throws Exception from openstack lib when something goes wrong
+ * @throws \Exception from openstack lib when something goes wrong
*/
public function readObject($urn) {
- $this->init();
- $object = $this->container->getObject($urn);
+ $object = $this->getContainer()->getObject($urn);
// we need to keep a reference to objectContent or
// the stream will be closed before we can do anything with it
- /** @var $objectContent \Guzzle\Http\EntityBody * */
- $objectContent = $object->getContent();
+ $objectContent = $object->download();
$objectContent->rewind();
- $stream = $objectContent->getStream();
+ $stream = $objectContent->detach();
// save the object content in the context of the stream to prevent it being gc'd until the stream is closed
stream_context_set_option($stream, 'swift', 'content', $objectContent);
- RetryWrapper::wrap($stream);
+ return RetryWrapper::wrap($stream);
}
/**
* @param string $urn Unified Resource Name
* @return void
- * @throws Exception from openstack lib when something goes wrong
+ * @throws \Exception from openstack lib when something goes wrong
*/
public function deleteObject($urn) {
- $this->init();
- // see https://github.com/rackspace/php-opencloud/issues/243#issuecomment-30032242
- $this->container->dataObject()->setName($urn)->delete();
+ $this->getContainer()->getObject($urn)->delete();
}
- public function deleteContainer($recursive = false) {
- $this->init();
- $this->container->delete($recursive);
+ /**
+ * @return void
+ * @throws \Exception from openstack lib when something goes wrong
+ */
+ public function deleteContainer() {
+ $this->getContainer()->delete();
}
}
diff --git a/lib/private/Files/ObjectStore/SwiftFactory.php b/lib/private/Files/ObjectStore/SwiftFactory.php
new file mode 100644
index 00000000000..3ff534b4e64
--- /dev/null
+++ b/lib/private/Files/ObjectStore/SwiftFactory.php
@@ -0,0 +1,216 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Files\ObjectStore;
+
+use GuzzleHttp\Client;
+use GuzzleHttp\Exception\ClientException;
+use GuzzleHttp\Exception\ConnectException;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\HandlerStack;
+use OCP\Files\StorageAuthException;
+use OCP\Files\StorageNotAvailableException;
+use OCP\ICache;
+use OCP\ILogger;
+use OpenStack\Common\Error\BadResponseError;
+use OpenStack\Common\Auth\Token;
+use OpenStack\Identity\v2\Service as IdentityV2Service;
+use OpenStack\Identity\v3\Service as IdentityV3Service;
+use OpenStack\OpenStack;
+use OpenStack\Common\Transport\Utils as TransportUtils;
+use Psr\Http\Message\RequestInterface;
+use OpenStack\ObjectStore\v1\Models\Container;
+
+class SwiftFactory {
+ private $cache;
+ private $params;
+ /** @var Container|null */
+ private $container = null;
+ private $logger;
+
+ public function __construct(ICache $cache, array $params, ILogger $logger) {
+ $this->cache = $cache;
+ $this->params = $params;
+ $this->logger = $logger;
+ }
+
+ private function getCachedToken(string $cacheKey) {
+ $cachedTokenString = $this->cache->get($cacheKey . '/token');
+ if ($cachedTokenString) {
+ return json_decode($cachedTokenString, true);
+ } else {
+ return null;
+ }
+ }
+
+ private function cacheToken(Token $token, string $cacheKey) {
+ if ($token instanceof \OpenStack\Identity\v3\Models\Token) {
+ $value = json_encode($token->export());
+ } else {
+ $value = json_encode($token);
+ }
+ $this->cache->set($cacheKey . '/token', $value);
+ }
+
+ /**
+ * @return OpenStack
+ * @throws StorageAuthException
+ */
+ private function getClient() {
+ if (isset($this->params['bucket'])) {
+ $this->params['container'] = $this->params['bucket'];
+ }
+ if (!isset($this->params['container'])) {
+ $this->params['container'] = 'nextcloud';
+ }
+ if (!isset($this->params['autocreate'])) {
+ // should only be true for tests
+ $this->params['autocreate'] = false;
+ }
+ if (isset($this->params['user']) && is_array($this->params['user'])) {
+ $userName = $this->params['user']['name'];
+ } else {
+ if (!isset($this->params['username']) && isset($this->params['user'])) {
+ $this->params['username'] = $this->params['user'];
+ }
+ $userName = $this->params['username'];
+ }
+ if (!isset($this->params['tenantName']) && isset($this->params['tenant'])) {
+ $this->params['tenantName'] = $this->params['tenant'];
+ }
+
+ $cacheKey = $userName . '@' . $this->params['url'] . '/' . $this->params['container'];
+ $token = $this->getCachedToken($cacheKey);
+ $this->params['cachedToken'] = $token;
+
+ $httpClient = new Client([
+ 'base_uri' => TransportUtils::normalizeUrl($this->params['url']),
+ 'handler' => HandlerStack::create()
+ ]);
+
+ if (isset($this->params['user']) && isset($this->params['user']['name'])) {
+ if (!isset($this->params['scope'])) {
+ throw new StorageAuthException('Scope has to be defined for V3 requests');
+ }
+
+ return $this->auth(IdentityV3Service::factory($httpClient), $cacheKey);
+ } else {
+ return $this->auth(IdentityV2Service::factory($httpClient), $cacheKey);
+ }
+ }
+
+ /**
+ * @param IdentityV2Service|IdentityV3Service $authService
+ * @param string $cacheKey
+ * @return OpenStack
+ * @throws StorageAuthException
+ */
+ private function auth($authService, string $cacheKey) {
+ $this->params['identityService'] = $authService;
+ $this->params['authUrl'] = $this->params['url'];
+ $client = new OpenStack($this->params);
+
+ $cachedToken = $this->params['cachedToken'];
+ $hasValidCachedToken = false;
+ if (\is_array($cachedToken) && ($authService instanceof IdentityV3Service)) {
+ $token = $authService->generateTokenFromCache($cachedToken);
+ if (\is_null($token->catalog)) {
+ $this->logger->warning('Invalid cached token for swift, no catalog set: ' . json_encode($cachedToken));
+ } else if ($token->hasExpired()) {
+ $this->logger->debug('Cached token for swift expired');
+ } else {
+ $hasValidCachedToken = true;
+ }
+ }
+
+ if (!$hasValidCachedToken) {
+ try {
+ $token = $authService->generateToken($this->params);
+ $this->cacheToken($token, $cacheKey);
+ } catch (ConnectException $e) {
+ throw new StorageAuthException('Failed to connect to keystone, verify the keystone url', $e);
+ } catch (ClientException $e) {
+ $statusCode = $e->getResponse()->getStatusCode();
+ if ($statusCode === 404) {
+ throw new StorageAuthException('Keystone not found, verify the keystone url', $e);
+ } else if ($statusCode === 412) {
+ throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
+ } else if ($statusCode === 401) {
+ throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
+ } else {
+ throw new StorageAuthException('Unknown error', $e);
+ }
+ } catch (RequestException $e) {
+ throw new StorageAuthException('Connection reset while connecting to keystone, verify the keystone url', $e);
+ }
+ }
+
+ return $client;
+ }
+
+ /**
+ * @return \OpenStack\ObjectStore\v1\Models\Container
+ * @throws StorageAuthException
+ * @throws StorageNotAvailableException
+ */
+ public function getContainer() {
+ if (is_null($this->container)) {
+ $this->container = $this->createContainer();
+ }
+
+ return $this->container;
+ }
+
+ /**
+ * @return \OpenStack\ObjectStore\v1\Models\Container
+ * @throws StorageAuthException
+ * @throws StorageNotAvailableException
+ */
+ private function createContainer() {
+ $client = $this->getClient();
+ $objectStoreService = $client->objectStoreV1();
+
+ $autoCreate = isset($this->params['autocreate']) && $this->params['autocreate'] === true;
+ try {
+ $container = $objectStoreService->getContainer($this->params['container']);
+ if ($autoCreate) {
+ $container->getMetadata();
+ }
+ return $container;
+ } catch (BadResponseError $ex) {
+ // if the container does not exist and autocreate is true try to create the container on the fly
+ if ($ex->getResponse()->getStatusCode() === 404 && $autoCreate) {
+ return $objectStoreService->createContainer([
+ 'name' => $this->params['container']
+ ]);
+ } else {
+ throw new StorageNotAvailableException('Invalid response while trying to get container info', StorageNotAvailableException::STATUS_ERROR, $ex);
+ }
+ } catch (ConnectException $e) {
+ /** @var RequestInterface $request */
+ $request = $e->getRequest();
+ $host = $request->getUri()->getHost() . ':' . $request->getUri()->getPort();
+ \OC::$server->getLogger()->error("Can't connect to object storage server at $host");
+ throw new StorageNotAvailableException("Can't connect to object storage server at $host", StorageNotAvailableException::STATUS_ERROR, $e);
+ }
+ }
+}
diff --git a/lib/private/Files/SimpleFS/SimpleFile.php b/lib/private/Files/SimpleFS/SimpleFile.php
index 5eadfd98b60..7b83e9372f7 100644
--- a/lib/private/Files/SimpleFS/SimpleFile.php
+++ b/lib/private/Files/SimpleFS/SimpleFile.php
@@ -23,6 +23,7 @@
namespace OC\Files\SimpleFS;
use OCP\Files\File;
+use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
@@ -79,16 +80,24 @@ class SimpleFile implements ISimpleFile {
/**
* Get the content
*
+ * @throws NotPermittedException
+ * @throws NotFoundException
* @return string
*/
public function getContent() {
- return $this->file->getContent();
+ $result = $this->file->getContent();
+
+ if ($result === false) {
+ $this->checkFile();
+ }
+
+ return $result;
}
/**
* Overwrite the file
*
- * @param string $data
+ * @param string|resource $data
* @throws NotPermittedException
*/
public function putContent($data) {
@@ -96,6 +105,31 @@ class SimpleFile implements ISimpleFile {
}
/**
+ * Sometimes there are some issues with the AppData. Most of them are from
+ * user error. But we should handle them gracefull anyway.
+ *
+ * If for some reason the current file can't be found. We remove it.
+ * Then traverse up and check all folders if they exists. This so that the
+ * next request will have a valid appdata structure again.
+ *
+ * @throws NotFoundException
+ */
+ private function checkFile() {
+ $cur = $this->file;
+
+ while ($cur->stat() === false) {
+ $parent = $cur->getParent();
+ $cur->delete();
+ $cur = $parent;
+ }
+
+ if ($cur !== $this->file) {
+ throw new NotFoundException('File does not exist');
+ }
+ }
+
+
+ /**
* Delete the file
*
* @throws NotPermittedException
@@ -112,4 +146,27 @@ class SimpleFile implements ISimpleFile {
public function getMimeType() {
return $this->file->getMimeType();
}
+
+ /**
+ * Open the file as stream for reading, resulting resource can be operated as stream like the result from php's own fopen
+ *
+ * @return resource
+ * @throws \OCP\Files\NotPermittedException
+ * @since 14.0.0
+ */
+ public function read() {
+ return $this->file->fopen('r');
+ }
+
+ /**
+ * Open the file as stream for writing, resulting resource can be operated as stream like the result from php's own fopen
+ *
+ * @return resource
+ * @throws \OCP\Files\NotPermittedException
+ * @since 14.0.0
+ */
+ public function write() {
+ return $this->file->fopen('w');
+ }
+
}
diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php
index 56d683ffa25..b6c82f3a1df 100644
--- a/lib/private/Files/Storage/Common.php
+++ b/lib/private/Files/Storage/Common.php
@@ -54,6 +54,7 @@ use OCP\Files\InvalidPathException;
use OCP\Files\ReservedWordException;
use OCP\Files\Storage\ILockingStorage;
use OCP\Files\Storage\IStorage;
+use OCP\ILogger;
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
@@ -449,8 +450,11 @@ abstract class Common implements Storage, ILockingStorage {
if ($this->stat('')) {
return true;
}
+ \OC::$server->getLogger()->info("External storage not available: stat() failed");
return false;
} catch (\Exception $e) {
+ \OC::$server->getLogger()->info("External storage not available: " . $e->getMessage());
+ \OC::$server->getLogger()->logException($e, ['level' => ILogger::DEBUG]);
return false;
}
}
@@ -772,9 +776,7 @@ abstract class Common implements Storage, ILockingStorage {
try {
$provider->changeLock('files/' . md5($this->getId() . '::' . trim($path, '/')), $type);
} catch (LockedException $e) {
- if ($logger) {
- $logger->logException($e);
- }
+ \OC::$server->getLogger()->logException($e);
throw $e;
}
}
diff --git a/lib/private/Files/Storage/DAV.php b/lib/private/Files/Storage/DAV.php
index f9c6175308c..b5537b65747 100644
--- a/lib/private/Files/Storage/DAV.php
+++ b/lib/private/Files/Storage/DAV.php
@@ -35,7 +35,8 @@ namespace OC\Files\Storage;
use Exception;
use GuzzleHttp\Exception\RequestException;
-use GuzzleHttp\Message\ResponseInterface;
+use OCP\ILogger;
+use Psr\Http\Message\ResponseInterface;
use Icewind\Streams\CallbackWrapper;
use OC\Files\Filesystem;
use Icewind\Streams\IteratorDirectory;
@@ -205,7 +206,7 @@ class DAV extends Common {
try {
$response = $this->client->propFind(
$this->encodePath($path),
- ['{DAV:}href'],
+ ['{DAV:}getetag'],
1
);
if ($response === false) {
@@ -344,7 +345,7 @@ class DAV extends Common {
'auth' => [$this->user, $this->password],
'stream' => true
]);
- } catch (RequestException $e) {
+ } catch (\GuzzleHttp\Exception\ClientException $e) {
if ($e->getResponse() instanceof ResponseInterface
&& $e->getResponse()->getStatusCode() === 404) {
return false;
@@ -357,7 +358,7 @@ class DAV extends Common {
if ($response->getStatusCode() === Http::STATUS_LOCKED) {
throw new \OCP\Lock\LockedException($path);
} else {
- Util::writeLog("webdav client", 'Guzzle get returned status code ' . $response->getStatusCode(), Util::ERROR);
+ Util::writeLog("webdav client", 'Guzzle get returned status code ' . $response->getStatusCode(), ILogger::ERROR);
}
}
@@ -770,7 +771,7 @@ class DAV extends Common {
if ($response === false) {
if ($path === '') {
// if root is gone it means the storage is not available
- throw new StorageNotAvailableException(get_class($e) . ': ' . $e->getMessage());
+ throw new StorageNotAvailableException('root is gone');
}
return false;
}
diff --git a/lib/private/Files/Storage/Flysystem.php b/lib/private/Files/Storage/Flysystem.php
index 423a6f0d83e..232222db358 100644
--- a/lib/private/Files/Storage/Flysystem.php
+++ b/lib/private/Files/Storage/Flysystem.php
@@ -206,7 +206,7 @@ abstract class Flysystem extends Common {
if (!$this->isCreatable(dirname($path))) {
return false;
}
- $tmpFile = \OCP\Files::tmpFile();
+ $tmpFile = \OC::$server->getTempManager()->getTemporaryFile();
}
$source = fopen($tmpFile, $mode);
return CallbackWrapper::wrap($source, null, null, function () use ($tmpFile, $fullPath) {
diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php
index a0e20f4cba1..46b53dcf95c 100644
--- a/lib/private/Files/Storage/Local.php
+++ b/lib/private/Files/Storage/Local.php
@@ -42,6 +42,7 @@ namespace OC\Files\Storage;
use OC\Files\Storage\Wrapper\Jail;
use OCP\Files\ForbiddenException;
use OCP\Files\Storage\IStorage;
+use OCP\ILogger;
/**
* for local filestore, we only have to map the paths
@@ -235,17 +236,17 @@ class Local extends \OC\Files\Storage\Common {
$dstParent = dirname($path2);
if (!$this->isUpdatable($srcParent)) {
- \OCP\Util::writeLog('core', 'unable to rename, source directory is not writable : ' . $srcParent, \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'unable to rename, source directory is not writable : ' . $srcParent, ILogger::ERROR);
return false;
}
if (!$this->isUpdatable($dstParent)) {
- \OCP\Util::writeLog('core', 'unable to rename, destination directory is not writable : ' . $dstParent, \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'unable to rename, destination directory is not writable : ' . $dstParent, ILogger::ERROR);
return false;
}
if (!$this->file_exists($path1)) {
- \OCP\Util::writeLog('core', 'unable to rename, file does not exists : ' . $path1, \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'unable to rename, file does not exists : ' . $path1, ILogger::ERROR);
return false;
}
@@ -382,7 +383,7 @@ class Local extends \OC\Files\Storage\Common {
return $fullPath;
}
- \OCP\Util::writeLog('core', "Following symlinks is not allowed ('$fullPath' -> '$realPath' not inside '{$this->realDataDir}')", \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', "Following symlinks is not allowed ('$fullPath' -> '$realPath' not inside '{$this->realDataDir}')", ILogger::ERROR);
throw new ForbiddenException('Following symlinks is not allowed', false);
}
diff --git a/lib/private/Files/Storage/Wrapper/Encryption.php b/lib/private/Files/Storage/Wrapper/Encryption.php
index e40a4830953..42653b2d4a6 100644
--- a/lib/private/Files/Storage/Wrapper/Encryption.php
+++ b/lib/private/Files/Storage/Wrapper/Encryption.php
@@ -351,9 +351,7 @@ class Encryption extends Wrapper {
// need to stream copy file by file in case we copy between a encrypted
// and a unencrypted storage
$this->unlink($path2);
- $result = $this->copyFromStorage($this, $path1, $path2);
-
- return $result;
+ return $this->copyFromStorage($this, $path1, $path2);
}
/**
@@ -414,9 +412,13 @@ class Encryption extends Wrapper {
|| $mode === 'wb'
|| $mode === 'wb+'
) {
- // don't overwrite encrypted files if encryption is not enabled
+ // if we update a encrypted file with a un-encrypted one we change the db flag
if ($targetIsEncrypted && $encryptionEnabled === false) {
- throw new GenericEncryptionException('Tried to access encrypted file but encryption is not enabled');
+ $cache = $this->storage->getCache();
+ if ($cache) {
+ $entry = $cache->get($path);
+ $cache->update($entry->getId(), ['encrypted' => 0]);
+ }
}
if ($encryptionEnabled) {
// if $encryptionModuleId is empty, the default module will be used
@@ -443,7 +445,7 @@ class Encryption extends Wrapper {
} catch (ModuleDoesNotExistsException $e) {
$this->logger->logException($e, [
'message' => 'Encryption module "' . $encryptionModuleId . '" not found, file will be stored unencrypted',
- 'level' => \OCP\Util::WARN,
+ 'level' => ILogger::WARN,
'app' => 'core',
]);
}
@@ -654,13 +656,14 @@ class Encryption extends Wrapper {
* @param string $sourceInternalPath
* @param string $targetInternalPath
* @param bool $isRename
+ * @param bool $keepEncryptionVersion
*/
- private function updateEncryptedVersion(Storage\IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath, $isRename) {
- $isEncrypted = $this->encryptionManager->isEnabled() && $this->shouldEncrypt($targetInternalPath) ? 1 : 0;
+ private function updateEncryptedVersion(Storage\IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath, $isRename, $keepEncryptionVersion) {
+ $isEncrypted = $this->encryptionManager->isEnabled() && $this->shouldEncrypt($targetInternalPath);
$cacheInformation = [
- 'encrypted' => (bool)$isEncrypted,
+ 'encrypted' => $isEncrypted,
];
- if($isEncrypted === 1) {
+ if($isEncrypted) {
$encryptedVersion = $sourceStorage->getCache()->get($sourceInternalPath)['encryptedVersion'];
// In case of a move operation from an unencrypted to an encrypted
@@ -668,7 +671,7 @@ class Encryption extends Wrapper {
// correct value would be "1". Thus we manually set the value to "1"
// for those cases.
// See also https://github.com/owncloud/core/issues/23078
- if($encryptedVersion === 0) {
+ if($encryptedVersion === 0 || !$keepEncryptionVersion) {
$encryptedVersion = 1;
}
@@ -716,7 +719,7 @@ class Encryption extends Wrapper {
$info['size']
);
}
- $this->updateEncryptedVersion($sourceStorage, $sourceInternalPath, $targetInternalPath, $isRename);
+ $this->updateEncryptedVersion($sourceStorage, $sourceInternalPath, $targetInternalPath, $isRename, true);
}
return $result;
}
@@ -759,7 +762,7 @@ class Encryption extends Wrapper {
if ($preserveMtime) {
$this->touch($targetInternalPath, $sourceStorage->filemtime($sourceInternalPath));
}
- $this->updateEncryptedVersion($sourceStorage, $sourceInternalPath, $targetInternalPath, $isRename);
+ $this->updateEncryptedVersion($sourceStorage, $sourceInternalPath, $targetInternalPath, $isRename, false);
} else {
// delete partially written target file
$this->unlink($targetInternalPath);
diff --git a/lib/private/Files/Storage/Wrapper/Quota.php b/lib/private/Files/Storage/Wrapper/Quota.php
index 22338f9c3cc..860fce57277 100644
--- a/lib/private/Files/Storage/Wrapper/Quota.php
+++ b/lib/private/Files/Storage/Wrapper/Quota.php
@@ -46,7 +46,7 @@ class Quota extends Wrapper {
* @param array $parameters
*/
public function __construct($parameters) {
- $this->storage = $parameters['storage'];
+ parent::__construct($parameters);
$this->quota = $parameters['quota'];
$this->sizeRoot = isset($parameters['root']) ? $parameters['root'] : '';
}
@@ -83,7 +83,7 @@ class Quota extends Wrapper {
* @return int
*/
public function free_space($path) {
- if ($this->quota < 0) {
+ if ($this->quota < 0 || strpos($path, 'cache') === 0) {
return $this->storage->free_space($path);
} else {
$used = $this->getSize($this->sizeRoot);
@@ -111,7 +111,7 @@ class Quota extends Wrapper {
* @return bool
*/
public function file_put_contents($path, $data) {
- $free = $this->free_space('');
+ $free = $this->free_space($path);
if ($free < 0 or strlen($data) < $free) {
return $this->storage->file_put_contents($path, $data);
} else {
@@ -127,7 +127,7 @@ class Quota extends Wrapper {
* @return bool
*/
public function copy($source, $target) {
- $free = $this->free_space('');
+ $free = $this->free_space($target);
if ($free < 0 or $this->getSize($source) < $free) {
return $this->storage->copy($source, $target);
} else {
@@ -147,7 +147,7 @@ class Quota extends Wrapper {
// don't apply quota for part files
if (!$this->isPartFile($path)) {
- $free = $this->free_space('');
+ $free = $this->free_space($path);
if ($source && $free >= 0 && $mode !== 'r' && $mode !== 'rb') {
// only apply quota for files, not metadata, trash or others
if (strpos(ltrim($path, '/'), 'files/') === 0) {
@@ -178,7 +178,7 @@ class Quota extends Wrapper {
* @return bool
*/
public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
- $free = $this->free_space('');
+ $free = $this->free_space($targetInternalPath);
if ($free < 0 or $this->getSize($sourceInternalPath, $sourceStorage) < $free) {
return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
} else {
@@ -193,11 +193,20 @@ class Quota extends Wrapper {
* @return bool
*/
public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
- $free = $this->free_space('');
+ $free = $this->free_space($targetInternalPath);
if ($free < 0 or $this->getSize($sourceInternalPath, $sourceStorage) < $free) {
return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
} else {
return false;
}
}
+
+ public function mkdir($path) {
+ $free = $this->free_space($path);
+ if ($free === 0.0) {
+ return false;
+ }
+
+ return parent::mkdir($path);
+ }
}
diff --git a/lib/private/Files/Stream/Encryption.php b/lib/private/Files/Stream/Encryption.php
index 05be5a5b286..65d379c0289 100644
--- a/lib/private/Files/Stream/Encryption.php
+++ b/lib/private/Files/Stream/Encryption.php
@@ -195,10 +195,10 @@ class Encryption extends Wrapper {
protected static function wrapSource($source, $context, $protocol, $class, $mode = 'r+') {
try {
stream_wrapper_register($protocol, $class);
- if (@rewinddir($source) === false) {
- $wrapped = fopen($protocol . '://', $mode, false, $context);
- } else {
+ if (self::isDirectoryHandle($source)) {
$wrapped = opendir($protocol . '://', $context);
+ } else {
+ $wrapped = fopen($protocol . '://', $mode, false, $context);
}
} catch (\BadMethodCallException $e) {
stream_wrapper_unregister($protocol);
diff --git a/lib/private/Files/Utils/Scanner.php b/lib/private/Files/Utils/Scanner.php
index dd20e11fb63..fe2bf4ccb58 100644
--- a/lib/private/Files/Utils/Scanner.php
+++ b/lib/private/Files/Utils/Scanner.php
@@ -182,15 +182,20 @@ class Scanner extends PublicEmitter {
/**
* @param string $dir
- * @throws \OC\ForbiddenException
- * @throws \OCP\Files\NotFoundException
+ * @param $recursive
+ * @param callable|null $mountFilter
+ * @throws ForbiddenException
+ * @throws NotFoundException
*/
- public function scan($dir = '') {
+ public function scan($dir = '', $recursive = \OC\Files\Cache\Scanner::SCAN_RECURSIVE, callable $mountFilter = null) {
if (!Filesystem::isValidPath($dir)) {
throw new \InvalidArgumentException('Invalid path to scan');
}
$mounts = $this->getMounts($dir);
foreach ($mounts as $mount) {
+ if ($mountFilter && !$mountFilter($mount)) {
+ continue;
+ }
$storage = $mount->getStorage();
if (is_null($storage)) {
continue;
@@ -242,7 +247,7 @@ class Scanner extends PublicEmitter {
try {
$propagator = $storage->getPropagator();
$propagator->beginBatch();
- $scanner->scan($relativePath, \OC\Files\Cache\Scanner::SCAN_RECURSIVE, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
+ $scanner->scan($relativePath, $recursive, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
$cache = $storage->getCache();
if ($cache instanceof Cache) {
// only re-calculate for the root folder we scanned, anything below that is taken care of by the scanner
diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php
index aaf14b4d7e0..c6429a89942 100644
--- a/lib/private/Files/View.php
+++ b/lib/private/Files/View.php
@@ -59,6 +59,7 @@ use OCP\Files\InvalidPathException;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\NotFoundException;
use OCP\Files\ReservedWordException;
+use OCP\ILogger;
use OCP\IUser;
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
@@ -631,7 +632,7 @@ class View {
/**
* @param string $path
- * @param mixed $data
+ * @param string|resource $data
* @return bool|mixed
* @throws \Exception
*/
@@ -975,7 +976,7 @@ class View {
$hooks[] = 'write';
break;
default:
- \OCP\Util::writeLog('core', 'invalid mode (' . $mode . ') for ' . $path, \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'invalid mode (' . $mode . ') for ' . $path, ILogger::ERROR);
}
if ($mode !== 'r' && $mode !== 'w') {
@@ -1315,15 +1316,13 @@ class View {
try {
// if the file is not in the cache or needs to be updated, trigger the scanner and reload the data
if (!$data || $data['size'] === -1) {
- $this->lockFile($relativePath, ILockingProvider::LOCK_SHARED);
if (!$storage->file_exists($internalPath)) {
- $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
return false;
}
+ // don't need to get a lock here since the scanner does it's own locking
$scanner = $storage->getScanner($internalPath);
$scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
$data = $cache->get($internalPath);
- $this->unlockFile($relativePath, ILockingProvider::LOCK_SHARED);
} else if (!Cache\Scanner::isPartialFile($internalPath) && $watcher->needsUpdate($internalPath, $data)) {
$this->lockFile($relativePath, ILockingProvider::LOCK_SHARED);
$watcher->update($internalPath, $data);
@@ -1360,6 +1359,7 @@ class View {
$mount = Filesystem::getMountManager()->find($path);
if (!$mount) {
+ \OC::$server->getLogger()->warning('Mountpoint not found for path: ' . $path);
return false;
}
$storage = $mount->getStorage();
@@ -1368,6 +1368,7 @@ class View {
$data = $this->getCacheEntry($storage, $internalPath, $relativePath);
if (!$data instanceof ICacheEntry) {
+ \OC::$server->getLogger()->debug('No cache entry found for ' . $path . ' (storage: ' . $storage->getId() . ', internalPath: ' . $internalPath . ')');
return false;
}
@@ -1391,6 +1392,8 @@ class View {
}
return $info;
+ } else {
+ \OC::$server->getLogger()->warning('Storage not valid for mountpoint: ' . $mount->getMountPoint());
}
return false;
@@ -1463,7 +1466,7 @@ class View {
// sometimes when the storage is not available it can be any exception
\OC::$server->getLogger()->logException($e, [
'message' => 'Exception while scanning storage "' . $subStorage->getId() . '"',
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'lib',
]);
continue;
@@ -1752,7 +1755,7 @@ class View {
if (!$targetStorage->instanceOfStorage('\OCP\Files\IHomeStorage')) {
\OCP\Util::writeLog('files',
'It is not allowed to move one mount point into another one',
- \OCP\Util::DEBUG);
+ ILogger::DEBUG);
return false;
}
@@ -1775,7 +1778,7 @@ class View {
if (count($shares) > 0) {
\OCP\Util::writeLog('files',
'It is not allowed to move one mount point into a shared folder',
- \OCP\Util::DEBUG);
+ ILogger::DEBUG);
return false;
}
diff --git a/lib/private/Group/Database.php b/lib/private/Group/Database.php
index a439a978cce..9bcb7eb3385 100644
--- a/lib/private/Group/Database.php
+++ b/lib/private/Group/Database.php
@@ -5,6 +5,7 @@
* @author Aaron Wood <aaronjwood@gmail.com>
* @author Loki3000 <github@labcms.ru>
* @author Roeland Jago Douma <roeland@famdouma.nl>
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0
*
@@ -40,23 +41,39 @@
namespace OC\Group;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\Group\Backend\ABackend;
+use OCP\Group\Backend\IAddToGroupBackend;
+use OCP\Group\Backend\ICountDisabledInGroup;
+use OCP\Group\Backend\ICountUsersBackend;
+use OCP\Group\Backend\ICreateGroupBackend;
+use OCP\Group\Backend\IDeleteGroupBackend;
+use OCP\Group\Backend\IRemoveFromGroupBackend;
+use OCP\IDBConnection;
+
/**
* Class for group management in a SQL Database (e.g. MySQL, SQLite)
*/
-class Database extends \OC\Group\Backend {
+class Database extends ABackend
+ implements IAddToGroupBackend,
+ ICountDisabledInGroup,
+ ICountUsersBackend,
+ ICreateGroupBackend,
+ IDeleteGroupBackend,
+ IRemoveFromGroupBackend {
/** @var string[] */
private $groupCache = [];
- /** @var \OCP\IDBConnection */
+ /** @var IDBConnection */
private $dbConn;
/**
* \OC\Group\Database constructor.
*
- * @param \OCP\IDBConnection|null $dbConn
+ * @param IDBConnection|null $dbConn
*/
- public function __construct(\OCP\IDBConnection $dbConn = null) {
+ public function __construct(IDBConnection $dbConn = null) {
$this->dbConn = $dbConn;
}
@@ -77,7 +94,7 @@ class Database extends \OC\Group\Backend {
* Tries to create a new group. If the group name already exists, false will
* be returned.
*/
- public function createGroup( $gid ) {
+ public function createGroup(string $gid): bool {
$this->fixDI();
// Add group
@@ -98,7 +115,7 @@ class Database extends \OC\Group\Backend {
*
* Deletes a group and removes it from the group_user-table
*/
- public function deleteGroup( $gid ) {
+ public function deleteGroup(string $gid): bool {
$this->fixDI();
// Delete the group
@@ -158,7 +175,7 @@ class Database extends \OC\Group\Backend {
*
* Adds a user to a group.
*/
- public function addToGroup( $uid, $gid ) {
+ public function addToGroup(string $uid, string $gid): bool {
$this->fixDI();
// No duplicate entries!
@@ -182,7 +199,7 @@ class Database extends \OC\Group\Backend {
*
* removes the user from a group.
*/
- public function removeFromGroup( $uid, $gid ) {
+ public function removeFromGroup(string $uid, string $gid): bool {
$this->fixDI();
$qb = $this->dbConn->getQueryBuilder();
@@ -219,7 +236,7 @@ class Database extends \OC\Group\Backend {
$groups = [];
while( $row = $cursor->fetch()) {
- $groups[] = $row["gid"];
+ $groups[] = $row['gid'];
$this->groupCache[$row['gid']] = $row['gid'];
}
$cursor->closeCursor();
@@ -237,19 +254,29 @@ class Database extends \OC\Group\Backend {
* Returns a list with all groups
*/
public function getGroups($search = '', $limit = null, $offset = null) {
- $parameters = [];
- $searchLike = '';
+ $this->fixDI();
+
+ $query = $this->dbConn->getQueryBuilder();
+ $query->select('gid')
+ ->from('groups')
+ ->orderBy('gid', 'ASC');
+
if ($search !== '') {
- $parameters[] = '%' . $search . '%';
- $searchLike = ' WHERE LOWER(`gid`) LIKE LOWER(?)';
+ $query->where($query->expr()->iLike('gid', $query->createNamedParameter(
+ '%' . $this->dbConn->escapeLikeParameter($search) . '%'
+ )));
}
- $stmt = \OC_DB::prepare('SELECT `gid` FROM `*PREFIX*groups`' . $searchLike . ' ORDER BY `gid` ASC', $limit, $offset);
- $result = $stmt->execute($parameters);
- $groups = array();
- while ($row = $result->fetchRow()) {
+ $query->setMaxResults($limit)
+ ->setFirstResult($offset);
+ $result = $query->execute();
+
+ $groups = [];
+ while ($row = $result->fetch()) {
$groups[] = $row['gid'];
}
+ $result->closeCursor();
+
return $groups;
}
@@ -290,21 +317,30 @@ class Database extends \OC\Group\Backend {
* @return array an array of user ids
*/
public function usersInGroup($gid, $search = '', $limit = null, $offset = null) {
- $parameters = [$gid];
- $searchLike = '';
+ $this->fixDI();
+
+ $query = $this->dbConn->getQueryBuilder();
+ $query->select('uid')
+ ->from('group_user')
+ ->where($query->expr()->eq('gid', $query->createNamedParameter($gid)))
+ ->orderBy('uid', 'ASC');
+
if ($search !== '') {
- $parameters[] = '%' . $this->dbConn->escapeLikeParameter($search) . '%';
- $searchLike = ' AND `uid` LIKE ?';
+ $query->andWhere($query->expr()->like('uid', $query->createNamedParameter(
+ '%' . $this->dbConn->escapeLikeParameter($search) . '%'
+ )));
}
- $stmt = \OC_DB::prepare('SELECT `uid` FROM `*PREFIX*group_user` WHERE `gid` = ?' . $searchLike . ' ORDER BY `uid` ASC',
- $limit,
- $offset);
- $result = $stmt->execute($parameters);
- $users = array();
- while ($row = $result->fetchRow()) {
+ $query->setMaxResults($limit)
+ ->setFirstResult($offset);
+ $result = $query->execute();
+
+ $users = [];
+ while ($row = $result->fetch()) {
$users[] = $row['uid'];
}
+ $result->closeCursor();
+
return $users;
}
@@ -312,23 +348,63 @@ class Database extends \OC\Group\Backend {
* get the number of all users matching the search string in a group
* @param string $gid
* @param string $search
- * @return int|false
- * @throws \OC\DatabaseException
+ * @return int
*/
- public function countUsersInGroup($gid, $search = '') {
- $parameters = [$gid];
- $searchLike = '';
+ public function countUsersInGroup(string $gid, string $search = ''): int {
+ $this->fixDI();
+
+ $query = $this->dbConn->getQueryBuilder();
+ $query->selectAlias($query->createFunction('COUNT(*)'), 'num_users')
+ ->from('group_user')
+ ->where($query->expr()->eq('gid', $query->createNamedParameter($gid)));
+
if ($search !== '') {
- $parameters[] = '%' . $this->dbConn->escapeLikeParameter($search) . '%';
- $searchLike = ' AND `uid` LIKE ?';
+ $query->andWhere($query->expr()->like('uid', $query->createNamedParameter(
+ '%' . $this->dbConn->escapeLikeParameter($search) . '%'
+ )));
+ }
+
+ $result = $query->execute();
+ $count = $result->fetchColumn();
+ $result->closeCursor();
+
+ if ($count !== false) {
+ $count = (int)$count;
+ } else {
+ $count = 0;
}
- $stmt = \OC_DB::prepare('SELECT COUNT(`uid`) AS `count` FROM `*PREFIX*group_user` WHERE `gid` = ?' . $searchLike);
- $result = $stmt->execute($parameters);
- $count = $result->fetchOne();
- if($count !== false) {
+ return $count;
+ }
+
+ /**
+ * get the number of disabled users in a group
+ *
+ * @param string $search
+ * @return int|bool
+ */
+ public function countDisabledInGroup(string $gid): int {
+ $this->fixDI();
+
+ $query = $this->dbConn->getQueryBuilder();
+ $query->select($query->createFunction('COUNT(Distinct uid)'))
+ ->from('preferences', 'p')
+ ->innerJoin('p', 'group_user', 'g', 'p.userid = g.uid')
+ ->where($query->expr()->eq('appid', $query->createNamedParameter('core')))
+ ->andWhere($query->expr()->eq('configkey', $query->createNamedParameter('enabled')))
+ ->andWhere($query->expr()->eq('configvalue', $query->createNamedParameter('false'), IQueryBuilder::PARAM_STR))
+ ->andWhere($query->expr()->eq('gid', $query->createNamedParameter($gid), IQueryBuilder::PARAM_STR));
+
+ $result = $query->execute();
+ $count = $result->fetchColumn();
+ $result->closeCursor();
+
+ if ($count !== false) {
$count = (int)$count;
+ } else {
+ $count = 0;
}
+
return $count;
}
diff --git a/lib/private/Group/Group.php b/lib/private/Group/Group.php
index 6795f0e2f53..0d54cf8e35a 100644
--- a/lib/private/Group/Group.php
+++ b/lib/private/Group/Group.php
@@ -10,6 +10,7 @@
* @author Robin McCorkell <robin@mccorkell.me.uk>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Vincent Petry <pvince81@owncloud.com>
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0
*
@@ -29,8 +30,10 @@
namespace OC\Group;
+use OCP\GroupInterface;
use OCP\IGroup;
use OCP\IUser;
+use OCP\Group\Backend\ICountDisabledInGroup;
class Group implements IGroup {
/** @var null|string */
@@ -209,10 +212,10 @@ class Group implements IGroup {
$userIds = $backend->usersInGroup($this->gid, $search, $limit, $offset);
$users += $this->getVerifiedUsers($userIds);
if (!is_null($limit) and $limit <= 0) {
- return array_values($users);
+ return $users;
}
}
- return array_values($users);
+ return $users;
}
/**
@@ -237,6 +240,26 @@ class Group implements IGroup {
}
/**
+ * returns the number of disabled users
+ *
+ * @return int|bool
+ */
+ public function countDisabled() {
+ $users = false;
+ foreach ($this->backends as $backend) {
+ if($backend instanceOf ICountDisabledInGroup) {
+ if($users === false) {
+ //we could directly add to a bool variable, but this would
+ //be ugly
+ $users = 0;
+ }
+ $users += $backend->countDisabledInGroup($this->gid);
+ }
+ }
+ return $users;
+ }
+
+ /**
* search for users in the group by displayname
*
* @param string $search
@@ -301,4 +324,30 @@ class Group implements IGroup {
}
return $users;
}
+
+ /**
+ * @return bool
+ * @since 14.0.0
+ */
+ public function canRemoveUser() {
+ foreach ($this->backends as $backend) {
+ if ($backend->implementsActions(GroupInterface::REMOVE_FROM_GOUP)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @return bool
+ * @since 14.0.0
+ */
+ public function canAddUser() {
+ foreach ($this->backends as $backend) {
+ if ($backend->implementsActions(GroupInterface::ADD_TO_GROUP)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/lib/private/Group/Manager.php b/lib/private/Group/Manager.php
index 2d40b447996..f1bb6357d0a 100644
--- a/lib/private/Group/Manager.php
+++ b/lib/private/Group/Manager.php
@@ -183,7 +183,7 @@ class Manager extends PublicEmitter implements IGroupManager {
foreach ($this->backends as $backend) {
if ($backend->implementsActions(\OC\Group\Backend::GROUP_DETAILS)) {
$groupData = $backend->getGroupDetails($gid);
- if (is_array($groupData)) {
+ if (is_array($groupData) && !empty($groupData)) {
// take the display name from the first backend that has a non-null one
if (is_null($displayName) && isset($groupData['displayName'])) {
$displayName = $groupData['displayName'];
@@ -330,6 +330,17 @@ class Manager extends PublicEmitter implements IGroupManager {
}
/**
+ * get an array of groupid and displayName for a user
+ * @param IUser $user
+ * @return array ['displayName' => displayname]
+ */
+ public function getUserGroupNames(IUser $user) {
+ return array_map(function($group) {
+ return array('displayName' => $group->getDisplayName());
+ }, $this->getUserGroups($user));
+ }
+
+ /**
* get a list of all display names in a group
* @param string $gid
* @param string $search
diff --git a/lib/private/Group/MetaData.php b/lib/private/Group/MetaData.php
index d5c8b581f8b..f4877237ec7 100644
--- a/lib/private/Group/MetaData.php
+++ b/lib/private/Group/MetaData.php
@@ -8,6 +8,7 @@
* @author Morris Jobke <hey@morrisjobke.de>
* @author Stephan Peijnik <speijnik@anexia-it.com>
* @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0
*
@@ -28,6 +29,7 @@
namespace OC\Group;
use OCP\IUserSession;
+use OCP\IGroupManager;
class MetaData {
const SORT_NONE = 0;
@@ -40,7 +42,7 @@ class MetaData {
protected $isAdmin;
/** @var array */
protected $metaData = array();
- /** @var \OCP\IGroupManager */
+ /** @var IGroupManager */
protected $groupManager;
/** @var bool */
protected $sorting = false;
@@ -50,13 +52,14 @@ class MetaData {
/**
* @param string $user the uid of the current user
* @param bool $isAdmin whether the current users is an admin
- * @param \OCP\IGroupManager $groupManager
+ * @param IGroupManager $groupManager
+ * @param IUserManager $userManager
* @param IUserSession $userSession
*/
public function __construct(
$user,
$isAdmin,
- \OCP\IGroupManager $groupManager,
+ IGroupManager $groupManager,
IUserSession $userSession
) {
$this->user = $user;
@@ -155,13 +158,16 @@ class MetaData {
* creates an array containing the group meta data
* @param \OCP\IGroup $group
* @param string $userSearch
- * @return array with the keys 'id', 'name' and 'usercount'
+ * @return array with the keys 'id', 'name', 'usercount' and 'disabled'
*/
private function generateGroupMetaData(\OCP\IGroup $group, $userSearch) {
return array(
'id' => $group->getGID(),
- 'name' => $group->getGID(),
+ 'name' => $group->getDisplayName(),
'usercount' => $this->sorting === self::SORT_USERCOUNT ? $group->count($userSearch) : 0,
+ 'disabled' => $group->countDisabled(),
+ 'canAdd' => $group->canAddUser(),
+ 'canRemove' => $group->canRemoveUser(),
);
}
@@ -184,7 +190,7 @@ class MetaData {
* @param string $search a search string
* @return \OCP\IGroup[]
*/
- protected function getGroups($search = '') {
+ public function getGroups($search = '') {
if($this->isAdmin) {
return $this->groupManager->search($search);
} else {
diff --git a/lib/private/HTTPHelper.php b/lib/private/HTTPHelper.php
deleted file mode 100644
index d58f81fbbdc..00000000000
--- a/lib/private/HTTPHelper.php
+++ /dev/null
@@ -1,120 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Björn Schießle <bjoern@schiessle.org>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @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;
-
-use OCP\Http\Client\IClientService;
-use OCP\IConfig;
-
-/**
- * Class HTTPHelper
- *
- * @package OC
- * @deprecated Use \OCP\Http\Client\IClientService
- */
-class HTTPHelper {
- const USER_AGENT = 'ownCloud Server Crawler';
-
- /** @var \OCP\IConfig */
- private $config;
- /** @var IClientService */
- private $clientService;
-
- /**
- * @param IConfig $config
- * @param IClientService $clientService
- */
- public function __construct(IConfig $config,
- IClientService $clientService) {
- $this->config = $config;
- $this->clientService = $clientService;
- }
-
- /**
- * Get URL content
- * @param string $url Url to get content
- * @throws \Exception If the URL does not start with http:// or https://
- * @return string of the response or false on error
- * This function get the content of a page via curl, if curl is enabled.
- * If not, file_get_contents is used.
- * @deprecated Use \OCP\Http\Client\IClientService
- */
- public function getUrlContent($url) {
- try {
- $client = $this->clientService->newClient();
- $response = $client->get($url);
- return $response->getBody();
- } catch (\Exception $e) {
- return false;
- }
- }
-
- /**
- * Returns the response headers of a HTTP URL without following redirects
- * @param string $location Needs to be a HTTPS or HTTP URL
- * @return array
- * @deprecated Use \OCP\Http\Client\IClientService
- */
- public function getHeaders($location) {
- $client = $this->clientService->newClient();
- $response = $client->get($location);
- return $response->getHeaders();
- }
-
- /**
- * Checks whether the supplied URL begins with HTTPS:// or HTTP:// (case insensitive)
- * @param string $url
- * @return bool
- */
- public function isHTTPURL($url) {
- return stripos($url, 'https://') === 0 || stripos($url, 'http://') === 0;
- }
-
- /**
- * send http post request
- *
- * @param string $url
- * @param array $fields data send by the request
- * @return array
- * @deprecated Use \OCP\Http\Client\IClientService
- */
- public function post($url, array $fields) {
- $client = $this->clientService->newClient();
-
- try {
- $response = $client->post(
- $url,
- [
- 'body' => $fields,
- 'connect_timeout' => 10,
- ]
- );
- } catch (\Exception $e) {
- return ['success' => false, 'result' => $e->getMessage()];
- }
-
- return ['success' => true, 'result' => $response->getBody()];
- }
-
-}
diff --git a/lib/private/Http/Client/Client.php b/lib/private/Http/Client/Client.php
index 4e6843d7b9f..03b09bf54b7 100644
--- a/lib/private/Http/Client/Client.php
+++ b/lib/private/Http/Client/Client.php
@@ -25,10 +25,13 @@ declare(strict_types=1);
namespace OC\Http\Client;
use GuzzleHttp\Client as GuzzleClient;
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Middleware;
use OCP\Http\Client\IClient;
use OCP\Http\Client\IResponse;
use OCP\ICertificateManager;
use OCP\IConfig;
+use Psr\Http\Message\RequestInterface;
/**
* Class Client
@@ -43,17 +46,23 @@ class Client implements IClient {
/** @var ICertificateManager */
private $certificateManager;
private $configured = false;
+ /** @var HandlerStack */
+ private $stack;
/**
* @param IConfig $config
* @param ICertificateManager $certificateManager
* @param GuzzleClient $client
*/
- public function __construct(IConfig $config,
- ICertificateManager $certificateManager,
- GuzzleClient $client) {
+ public function __construct(
+ IConfig $config,
+ ICertificateManager $certificateManager,
+ GuzzleClient $client,
+ HandlerStack $stack
+ ) {
$this->config = $config;
$this->client = $client;
+ $this->stack = $stack;
$this->certificateManager = $certificateManager;
}
@@ -65,25 +74,37 @@ class Client implements IClient {
return;
}
$this->configured = true;
- // Either use user bundle or the system bundle if nothing is specified
+
+ $this->stack->push(Middleware::mapRequest(function (RequestInterface $request) {
+ return $request
+ ->withHeader('User-Agent', 'Nextcloud Server Crawler');
+ }));
+ }
+
+ private function getRequestOptions() {
+ $options = [
+ 'verify' => $this->getCertBundle(),
+ ];
+ $proxyUri = $this->getProxyUri();
+ if ($proxyUri !== '') {
+ $options['proxy'] = $proxyUri;
+ }
+ return $options;
+ }
+
+ private function getCertBundle() {
if ($this->certificateManager->listCertificates() !== []) {
- $this->client->setDefaultOption('verify', $this->certificateManager->getAbsoluteBundlePath());
+ return $this->certificateManager->getAbsoluteBundlePath();
} else {
// If the instance is not yet setup we need to use the static path as
// $this->certificateManager->getAbsoluteBundlePath() tries to instantiiate
// a view
if ($this->config->getSystemValue('installed', false)) {
- $this->client->setDefaultOption('verify', $this->certificateManager->getAbsoluteBundlePath(null));
+ return $this->certificateManager->getAbsoluteBundlePath(null);
} else {
- $this->client->setDefaultOption('verify', \OC::$SERVERROOT . '/resources/config/ca-bundle.crt');
+ return \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
}
}
-
- $this->client->setDefaultOption('headers/User-Agent', 'Nextcloud Server Crawler');
- $proxyUri = $this->getProxyUri();
- if ($proxyUri !== '') {
- $this->client->setDefaultOption('proxy', $proxyUri);
- }
}
/**
@@ -137,7 +158,7 @@ class Client implements IClient {
*/
public function get(string $uri, array $options = []): IResponse {
$this->setDefaultOptions();
- $response = $this->client->get($uri, $options);
+ $response = $this->client->request('get', $uri, array_merge($this->getRequestOptions(), $options));
$isStream = isset($options['stream']) && $options['stream'];
return new Response($response, $isStream);
}
@@ -168,7 +189,7 @@ class Client implements IClient {
*/
public function head(string $uri, array $options = []): IResponse {
$this->setDefaultOptions();
- $response = $this->client->head($uri, $options);
+ $response = $this->client->request('head', $uri, array_merge($this->getRequestOptions(), $options));
return new Response($response);
}
@@ -203,7 +224,11 @@ class Client implements IClient {
*/
public function post(string $uri, array $options = []): IResponse {
$this->setDefaultOptions();
- $response = $this->client->post($uri, $options);
+ if (isset($options['body']) && is_array($options['body'])) {
+ $options['form_params'] = $options['body'];
+ unset($options['body']);
+ }
+ $response = $this->client->request('post', $uri, array_merge($this->getRequestOptions(), $options));
return new Response($response);
}
@@ -238,7 +263,7 @@ class Client implements IClient {
*/
public function put(string $uri, array $options = []): IResponse {
$this->setDefaultOptions();
- $response = $this->client->put($uri, $options);
+ $response = $this->client->request('put', $uri, array_merge($this->getRequestOptions(), $options));
return new Response($response);
}
@@ -273,7 +298,7 @@ class Client implements IClient {
*/
public function delete(string $uri, array $options = []): IResponse {
$this->setDefaultOptions();
- $response = $this->client->delete($uri, $options);
+ $response = $this->client->request('delete', $uri, array_merge($this->getRequestOptions(), $options));
return new Response($response);
}
@@ -309,7 +334,7 @@ class Client implements IClient {
*/
public function options(string $uri, array $options = []): IResponse {
$this->setDefaultOptions();
- $response = $this->client->options($uri, $options);
+ $response = $this->client->request('options', $uri, array_merge($this->getRequestOptions(), $options));
return new Response($response);
}
}
diff --git a/lib/private/Http/Client/ClientService.php b/lib/private/Http/Client/ClientService.php
index 1df54010a2d..fa8544f07a5 100644
--- a/lib/private/Http/Client/ClientService.php
+++ b/lib/private/Http/Client/ClientService.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace OC\Http\Client;
use GuzzleHttp\Client as GuzzleClient;
+use GuzzleHttp\HandlerStack;
use OCP\Http\Client\IClient;
use OCP\Http\Client\IClientService;
use OCP\ICertificateManager;
@@ -54,6 +55,6 @@ class ClientService implements IClientService {
* @return Client
*/
public function newClient(): IClient {
- return new Client($this->config, $this->certificateManager, new GuzzleClient());
+ return new Client($this->config, $this->certificateManager, new GuzzleClient(), HandlerStack::create());
}
}
diff --git a/lib/private/Http/Client/Response.php b/lib/private/Http/Client/Response.php
index 0ce6cc98e0d..73c14c2926d 100644
--- a/lib/private/Http/Client/Response.php
+++ b/lib/private/Http/Client/Response.php
@@ -25,7 +25,7 @@ declare(strict_types=1);
namespace OC\Http\Client;
use OCP\Http\Client\IResponse;
-use GuzzleHttp\Message\ResponseInterface as GuzzleResponse;
+use Psr\Http\Message\ResponseInterface;
/**
* Class Response
@@ -33,7 +33,7 @@ use GuzzleHttp\Message\ResponseInterface as GuzzleResponse;
* @package OC\Http
*/
class Response implements IResponse {
- /** @var GuzzleResponse */
+ /** @var ResponseInterface */
private $response;
/**
@@ -42,10 +42,10 @@ class Response implements IResponse {
private $stream;
/**
- * @param GuzzleResponse $response
+ * @param ResponseInterface $response
* @param bool $stream
*/
- public function __construct(GuzzleResponse $response, $stream = false) {
+ public function __construct(ResponseInterface $response, $stream = false) {
$this->response = $response;
$this->stream = $stream;
}
@@ -71,7 +71,7 @@ class Response implements IResponse {
* @return string
*/
public function getHeader(string $key): string {
- return $this->response->getHeader($key);
+ return $this->response->getHeader($key)[0];
}
/**
diff --git a/lib/private/Installer.php b/lib/private/Installer.php
index ad2dcb60f20..b6586eceabe 100644
--- a/lib/private/Installer.php
+++ b/lib/private/Installer.php
@@ -36,17 +36,12 @@
namespace OC;
use Doctrine\DBAL\Exception\TableExistsException;
-use OC\App\AppManager;
use OC\App\AppStore\Bundles\Bundle;
use OC\App\AppStore\Fetcher\AppFetcher;
-use OC\App\CodeChecker\CodeChecker;
-use OC\App\CodeChecker\EmptyCheck;
-use OC\App\CodeChecker\PrivateCheck;
use OC\Archive\TAR;
use OC_App;
use OC_DB;
use OC_Helper;
-use OCP\App\IAppManager;
use OCP\Http\Client\IClientService;
use OCP\IConfig;
use OCP\ILogger;
@@ -112,12 +107,12 @@ class Installer {
if(!is_array($info)) {
throw new \Exception(
$l->t('App "%s" cannot be installed because appinfo file cannot be read.',
- [$info['name']]
+ [$appId]
)
);
}
- $version = \OCP\Util::getVersion();
+ $version = implode('.', \OCP\Util::getVersion());
if (!\OC_App::isAppCompatible($version, $info)) {
throw new \Exception(
// TODO $l
@@ -146,9 +141,7 @@ class Installer {
\OC_App::setupBackgroundJobs($info['background-jobs']);
//run appinfo/install.php
- if(!isset($data['noinstall']) or $data['noinstall']==false) {
- self::includeAppScript($basedir . '/appinfo/install.php');
- }
+ self::includeAppScript($basedir . '/appinfo/install.php');
$appData = OC_App::getAppInfo($appId);
OC_App::executeRepairSteps($appId, $appData['repair-steps']['install']);
@@ -171,17 +164,6 @@ class Installer {
}
/**
- * @brief checks whether or not an app is installed
- * @param string $app app
- * @returns bool
- *
- * Checks whether or not an app is installed, i.e. registered in apps table.
- */
- public static function isInstalled( $app ) {
- return (\OC::$server->getConfig()->getAppValue($app, "installed_version", null) !== null);
- }
-
- /**
* Updates the specified app from the appstore
*
* @param string $appId
@@ -193,7 +175,7 @@ class Installer {
$this->downloadApp($appId);
} catch (\Exception $e) {
$this->logger->logException($e, [
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return false;
@@ -478,7 +460,7 @@ class Installer {
OC_Helper::rmdirr($appDir);
return true;
}else{
- \OCP\Util::writeLog('core', 'can\'t remove app '.$appId.'. It is not installed.', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'can\'t remove app '.$appId.'. It is not installed.', ILogger::ERROR);
return false;
}
@@ -515,17 +497,19 @@ class Installer {
* @return array Array of error messages (appid => Exception)
*/
public static function installShippedApps($softErrors = false) {
+ $appManager = \OC::$server->getAppManager();
+ $config = \OC::$server->getConfig();
$errors = [];
foreach(\OC::$APPSROOTS as $app_dir) {
if($dir = opendir( $app_dir['path'] )) {
while( false !== ( $filename = readdir( $dir ))) {
if( $filename[0] !== '.' and is_dir($app_dir['path']."/$filename") ) {
if( file_exists( $app_dir['path']."/$filename/appinfo/info.xml" )) {
- if(!Installer::isInstalled($filename)) {
+ if($config->getAppValue($filename, "installed_version", null) === null) {
$info=OC_App::getAppInfo($filename);
$enabled = isset($info['default_enable']);
- if (($enabled || in_array($filename, \OC::$server->getAppManager()->getAlwaysEnabledApps()))
- && \OC::$server->getConfig()->getAppValue($filename, 'enabled') !== 'no') {
+ if (($enabled || in_array($filename, $appManager->getAlwaysEnabledApps()))
+ && $config->getAppValue($filename, 'enabled') !== 'no') {
if ($softErrors) {
try {
Installer::installShippedApp($filename);
@@ -539,7 +523,7 @@ class Installer {
} else {
Installer::installShippedApp($filename);
}
- \OC::$server->getConfig()->setAppValue($filename, 'enabled', 'yes');
+ $config->setAppValue($filename, 'enabled', 'yes');
}
}
}
diff --git a/lib/private/IntegrityCheck/Checker.php b/lib/private/IntegrityCheck/Checker.php
index 771ac891ab4..44544b6770e 100644
--- a/lib/private/IntegrityCheck/Checker.php
+++ b/lib/private/IntegrityCheck/Checker.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -97,9 +98,9 @@ class Checker {
*
* @return bool
*/
- public function isCodeCheckEnforced() {
+ public function isCodeCheckEnforced(): bool {
$notSignedChannels = [ '', 'git'];
- if (in_array($this->environmentHelper->getChannel(), $notSignedChannels, true)) {
+ if (\in_array($this->environmentHelper->getChannel(), $notSignedChannels, true)) {
return false;
}
@@ -108,10 +109,9 @@ class Checker {
* applicable for very specific scenarios and we should not advertise it
* too prominent. So please do not add it to config.sample.php.
*/
+ $isIntegrityCheckDisabled = false;
if ($this->config !== null) {
$isIntegrityCheckDisabled = $this->config->getSystemValue('integrity.check.disabled', false);
- } else {
- $isIntegrityCheckDisabled = false;
}
if ($isIntegrityCheckDisabled === true) {
return false;
@@ -128,7 +128,7 @@ class Checker {
* @return \RecursiveIteratorIterator
* @throws \Exception
*/
- private function getFolderIterator($folderToIterate, $root = '') {
+ private function getFolderIterator(string $folderToIterate, string $root = ''): \RecursiveIteratorIterator {
$dirItr = new \RecursiveDirectoryIterator(
$folderToIterate,
\RecursiveDirectoryIterator::SKIP_DOTS
@@ -156,12 +156,12 @@ class Checker {
* @return array Array of hashes.
*/
private function generateHashes(\RecursiveIteratorIterator $iterator,
- $path) {
+ string $path): array {
$hashes = [];
$copiedWebserverSettingFiles = false;
$tmpFolder = '';
- $baseDirectoryLength = strlen($path);
+ $baseDirectoryLength = \strlen($path);
foreach($iterator as $filename => $data) {
/** @var \DirectoryIterator $data */
if($data->isDir()) {
@@ -220,7 +220,7 @@ class Checker {
if($filename === $this->environmentHelper->getServerRoot() . '/.htaccess') {
$fileContent = file_get_contents($tmpFolder . '/.htaccess');
$explodedArray = explode('#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####', $fileContent);
- if(count($explodedArray) === 2) {
+ if(\count($explodedArray) === 2) {
$hashes[$relativeFileName] = hash('sha512', $explodedArray[0]);
continue;
}
@@ -238,11 +238,11 @@ class Checker {
* @param array $hashes
* @param X509 $certificate
* @param RSA $privateKey
- * @return string
+ * @return array
*/
private function createSignatureData(array $hashes,
X509 $certificate,
- RSA $privateKey) {
+ RSA $privateKey): array {
ksort($hashes);
$privateKey->setSignatureMode(RSA::SIGNATURE_PSS);
@@ -328,13 +328,18 @@ class Checker {
* @throws InvalidSignatureException
* @throws \Exception
*/
- private function verify($signaturePath, $basePath, $certificateCN) {
+ private function verify(string $signaturePath, string $basePath, string $certificateCN): array {
if(!$this->isCodeCheckEnforced()) {
return [];
}
- $signatureData = json_decode($this->fileAccessHelper->file_get_contents($signaturePath), true);
- if(!is_array($signatureData)) {
+ $content = $this->fileAccessHelper->file_get_contents($signaturePath);
+ $signatureData = null;
+
+ if (\is_string($content)) {
+ $signatureData = json_decode($content, true);
+ }
+ if(!\is_array($signatureData)) {
throw new InvalidSignatureException('Signature data not found.');
}
@@ -422,7 +427,7 @@ class Checker {
*
* @return bool
*/
- public function hasPassedCheck() {
+ public function hasPassedCheck(): bool {
$results = $this->getResults();
if(empty($results)) {
return true;
@@ -434,9 +439,9 @@ class Checker {
/**
* @return array
*/
- public function getResults() {
+ public function getResults(): array {
$cachedResults = $this->cache->get(self::CACHE_KEY);
- if(!is_null($cachedResults)) {
+ if(!\is_null($cachedResults)) {
return json_decode($cachedResults, true);
}
@@ -452,7 +457,7 @@ class Checker {
* @param string $scope
* @param array $result
*/
- private function storeResults($scope, array $result) {
+ private function storeResults(string $scope, array $result) {
$resultArray = $this->getResults();
unset($resultArray[$scope]);
if(!empty($result)) {
@@ -505,7 +510,7 @@ class Checker {
* @param string $path Optional path. If none is given it will be guessed.
* @return array
*/
- public function verifyAppSignature($appId, $path = '') {
+ public function verifyAppSignature(string $appId, string $path = ''): array {
try {
if($path === '') {
$path = $this->appLocator->getAppPath($appId);
@@ -518,7 +523,7 @@ class Checker {
} catch (\Exception $e) {
$result = [
'EXCEPTION' => [
- 'class' => get_class($e),
+ 'class' => \get_class($e),
'message' => $e->getMessage(),
],
];
@@ -558,7 +563,7 @@ class Checker {
*
* @return array
*/
- public function verifyCoreSignature() {
+ public function verifyCoreSignature(): array {
try {
$result = $this->verify(
$this->environmentHelper->getServerRoot() . '/core/signature.json',
@@ -568,7 +573,7 @@ class Checker {
} catch (\Exception $e) {
$result = [
'EXCEPTION' => [
- 'class' => get_class($e),
+ 'class' => \get_class($e),
'message' => $e->getMessage(),
],
];
diff --git a/lib/private/IntegrityCheck/Helpers/AppLocator.php b/lib/private/IntegrityCheck/Helpers/AppLocator.php
index c8d4e1b9b27..9ec5361d9d5 100644
--- a/lib/private/IntegrityCheck/Helpers/AppLocator.php
+++ b/lib/private/IntegrityCheck/Helpers/AppLocator.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -37,7 +38,7 @@ class AppLocator {
* @return string
* @throws \Exception If the app cannot be found
*/
- public function getAppPath($appId) {
+ public function getAppPath(string $appId): string {
$path = \OC_App::getAppPath($appId);
if($path === false) {
@@ -51,7 +52,7 @@ class AppLocator {
*
* @return array
*/
- public function getAllApps() {
+ public function getAllApps(): array {
return \OC_App::getAllApps();
}
}
diff --git a/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php b/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php
index c5e91997130..b69af591bc2 100644
--- a/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php
+++ b/lib/private/IntegrityCheck/Helpers/EnvironmentHelper.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -34,7 +35,7 @@ class EnvironmentHelper {
*
* @return string
*/
- public function getServerRoot() {
+ public function getServerRoot(): string {
return rtrim(\OC::$SERVERROOT, '/');
}
@@ -43,7 +44,7 @@ class EnvironmentHelper {
*
* @return string
*/
- public function getChannel() {
+ public function getChannel(): string {
return \OC_Util::getChannel();
}
}
diff --git a/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php b/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php
index ef8e8b41b3f..e73b84b73c4 100644
--- a/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php
+++ b/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -36,7 +37,7 @@ class FileAccessHelper {
* @param string $filename
* @return string|false
*/
- public function file_get_contents($filename) {
+ public function file_get_contents(string $filename) {
return file_get_contents($filename);
}
@@ -46,7 +47,7 @@ class FileAccessHelper {
* @param string $filename
* @return bool
*/
- public function file_exists($filename) {
+ public function file_exists(string $filename): bool {
return file_exists($filename);
}
@@ -58,9 +59,9 @@ class FileAccessHelper {
* @return int
* @throws \Exception
*/
- public function file_put_contents($filename, $data) {
+ public function file_put_contents(string $filename, string $data): int {
$bytesWritten = @file_put_contents($filename, $data);
- if ($bytesWritten === false || $bytesWritten !== strlen($data)){
+ if ($bytesWritten === false || $bytesWritten !== \strlen($data)){
throw new \Exception('Failed to write into ' . $filename);
}
return $bytesWritten;
@@ -70,7 +71,7 @@ class FileAccessHelper {
* @param string $path
* @return bool
*/
- public function is_writable($path) {
+ public function is_writable(string $path): bool {
return is_writable($path);
}
@@ -78,7 +79,7 @@ class FileAccessHelper {
* @param string $path
* @throws \Exception
*/
- public function assertDirectoryExists($path) {
+ public function assertDirectoryExists(string $path) {
if (!is_dir($path)) {
throw new \Exception('Directory ' . $path . ' does not exist.');
}
diff --git a/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php b/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php
index 4801d7bb748..e0ad6a550e5 100644
--- a/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php
+++ b/lib/private/IntegrityCheck/Iterator/ExcludeFileByNameFilterIterator.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -52,7 +53,7 @@ class ExcludeFileByNameFilterIterator extends \RecursiveFilterIterator {
return true;
}
- return !in_array(
+ return !\in_array(
$this->current()->getFilename(),
$this->excludedFilenames,
true
diff --git a/lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php b/lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php
index 31dd05ef312..56524abe6a0 100644
--- a/lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php
+++ b/lib/private/IntegrityCheck/Iterator/ExcludeFoldersByPathFilterIterator.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -24,7 +25,7 @@
namespace OC\IntegrityCheck\Iterator;
class ExcludeFoldersByPathFilterIterator extends \RecursiveFilterIterator {
- private $excludedFolders = [];
+ private $excludedFolders;
public function __construct(\RecursiveIterator $iterator, $root = '') {
parent::__construct($iterator);
@@ -59,7 +60,7 @@ class ExcludeFoldersByPathFilterIterator extends \RecursiveFilterIterator {
* @return bool
*/
public function accept() {
- return !in_array(
+ return !\in_array(
$this->current()->getPathName(),
$this->excludedFolders,
true
diff --git a/lib/private/L10N/Factory.php b/lib/private/L10N/Factory.php
index a7ffb401b7b..cc2de174509 100644
--- a/lib/private/L10N/Factory.php
+++ b/lib/private/L10N/Factory.php
@@ -32,8 +32,10 @@ namespace OC\L10N;
use OCP\IConfig;
use OCP\IRequest;
+use OCP\IUser;
use OCP\IUserSession;
use OCP\L10N\IFactory;
+use OCP\L10N\ILanguageIterator;
/**
* A factory that generates language instances
@@ -55,10 +57,20 @@ class Factory implements IFactory {
protected $availableLanguages = [];
/**
+ * @var array
+ */
+ protected $availableLocales = [];
+
+ /**
* @var array Structure: string => callable
*/
protected $pluralFunctions = [];
+ const COMMON_LANGUAGE_CODES = [
+ 'en', 'es', 'fr', 'de', 'de_DE', 'ja', 'ar', 'ru', 'nl', 'it',
+ 'pt_BR', 'pt_PT', 'da', 'fi_FI', 'nb_NO', 'sv', 'tr', 'zh_CN', 'ko'
+ ];
+
/** @var IConfig */
protected $config;
@@ -92,9 +104,10 @@ class Factory implements IFactory {
*
* @param string $app
* @param string|null $lang
+ * @param string|null $locale
* @return \OCP\IL10N
*/
- public function get($app, $lang = null) {
+ public function get($app, $lang = null, $locale = null) {
$app = \OC_App::cleanAppId($app);
if ($lang !== null) {
$lang = str_replace(array('\0', '/', '\\', '..'), '', (string) $lang);
@@ -105,13 +118,22 @@ class Factory implements IFactory {
$lang = $forceLang;
}
+ $forceLocale = $this->config->getSystemValue('force_locale', false);
+ if (is_string($forceLocale)) {
+ $locale = $forceLocale;
+ }
+
if ($lang === null || !$this->languageExists($app, $lang)) {
$lang = $this->findLanguage($app);
}
+ if ($locale === null || !$this->localeExists($locale)) {
+ $locale = $this->findLocale($lang);
+ }
+
if (!isset($this->instances[$lang][$app])) {
$this->instances[$lang][$app] = new L10N(
- $this, $app, $lang,
+ $this, $app, $lang, $locale,
$this->getL10nFilesForApp($app, $lang)
);
}
@@ -126,6 +148,11 @@ class Factory implements IFactory {
* @return string language If nothing works it returns 'en'
*/
public function findLanguage($app = null) {
+ $forceLang = $this->config->getSystemValue('force_language', false);
+ if (is_string($forceLang)) {
+ $this->requestLanguage = $forceLang;
+ }
+
if ($this->requestLanguage !== '' && $this->languageExists($app, $this->requestLanguage)) {
return $this->requestLanguage;
}
@@ -137,9 +164,9 @@ class Factory implements IFactory {
*
* @link https://github.com/owncloud/core/issues/21955
*/
- if($this->config->getSystemValue('installed', false)) {
+ if ($this->config->getSystemValue('installed', false)) {
$userId = !is_null($this->userSession->getUser()) ? $this->userSession->getUser()->getUID() : null;
- if(!is_null($userId)) {
+ if (!is_null($userId)) {
$userLang = $this->config->getUserValue($userId, 'core', 'lang', null);
} else {
$userLang = null;
@@ -176,6 +203,48 @@ class Factory implements IFactory {
}
/**
+ * find the best locale
+ *
+ * @param string $lang
+ * @return null|string
+ */
+ public function findLocale($lang = null) {
+ $forceLocale = $this->config->getSystemValue('force_locale', false);
+ if (is_string($forceLocale) && $this->localeExists($forceLocale)) {
+ return $forceLocale;
+ }
+
+ if ($this->config->getSystemValue('installed', false)) {
+ $userId = null !== $this->userSession->getUser() ? $this->userSession->getUser()->getUID() : null;
+ $userLocale = null;
+ if (null !== $userId) {
+ $userLocale = $this->config->getUserValue($userId, 'core', 'locale', null);
+ }
+ } else {
+ $userId = null;
+ $userLocale = null;
+ }
+
+ if ($userLocale && $this->localeExists($userLocale)) {
+ return $userLocale;
+ }
+
+ // Default : use system default locale
+ $defaultLocale = $this->config->getSystemValue('default_locale', false);
+ if ($defaultLocale !== false && $this->localeExists($defaultLocale)) {
+ return $defaultLocale;
+ }
+
+ // If no user locale set, use lang as locale
+ if (null !== $lang && $this->localeExists($lang)) {
+ return $lang;
+ }
+
+ // At last, return USA
+ return 'en_US';
+ }
+
+ /**
* Find all available languages for an app
*
* @param string|null $app App id or null for core
@@ -227,6 +296,20 @@ class Factory implements IFactory {
}
/**
+ * @return array|mixed
+ */
+ public function findAvailableLocales() {
+ if (!empty($this->availableLocales)) {
+ return $this->availableLocales;
+ }
+
+ $localeData = file_get_contents(\OC::$SERVERROOT . '/resources/locales.json');
+ $this->availableLocales = \json_decode($localeData, true);
+
+ return $this->availableLocales;
+ }
+
+ /**
* @param string|null $app App id or null for core
* @param string $lang
* @return bool
@@ -240,6 +323,31 @@ class Factory implements IFactory {
return array_search($lang, $languages) !== false;
}
+ public function getLanguageIterator(IUser $user = null): ILanguageIterator {
+ $user = $user ?? $this->userSession->getUser();
+ if($user === null) {
+ throw new \RuntimeException('Failed to get an IUser instance');
+ }
+ return new LanguageIterator($user, $this->config);
+ }
+
+ /**
+ * @param string $locale
+ * @return bool
+ */
+ public function localeExists($locale) {
+ if ($locale === 'en') { //english is always available
+ return true;
+ }
+
+ $locales = $this->findAvailableLocales();
+ $userLocale = array_filter($locales, function($value) use ($locale) {
+ return $locale === $value['code'];
+ });
+
+ return !empty($userLocale);
+ }
+
/**
* @param string|null $app
* @return string
@@ -310,7 +418,7 @@ class Factory implements IFactory {
*/
private function isSubDirectory($sub, $parent) {
// Check whether $sub contains no ".."
- if(strpos($sub, '..') !== false) {
+ if (strpos($sub, '..') !== false) {
return false;
}
@@ -441,4 +549,74 @@ class Factory implements IFactory {
return $function;
}
}
+
+ /**
+ * returns the common language and other languages in an
+ * associative array
+ *
+ * @return array
+ */
+ public function getLanguages() {
+ $forceLanguage = $this->config->getSystemValue('force_language', false);
+ if ($forceLanguage !== false) {
+ return [];
+ }
+
+ $languageCodes = $this->findAvailableLanguages();
+
+ $commonLanguages = [];
+ $languages = [];
+
+ foreach($languageCodes as $lang) {
+ $l = $this->get('lib', $lang);
+ // TRANSLATORS this is the language name for the language switcher in the personal settings and should be the localized version
+ $potentialName = (string) $l->t('__language_name__');
+ if ($l->getLanguageCode() === $lang && $potentialName[0] !== '_') {//first check if the language name is in the translation file
+ $ln = array(
+ 'code' => $lang,
+ 'name' => $potentialName
+ );
+ } else if ($lang === 'en') {
+ $ln = array(
+ 'code' => $lang,
+ 'name' => 'English (US)'
+ );
+ } else {//fallback to language code
+ $ln = array(
+ 'code' => $lang,
+ 'name' => $lang
+ );
+ }
+
+ // put appropriate languages into appropriate arrays, to print them sorted
+ // common languages -> divider -> other languages
+ if (in_array($lang, self::COMMON_LANGUAGE_CODES)) {
+ $commonLanguages[array_search($lang, self::COMMON_LANGUAGE_CODES)] = $ln;
+ } else {
+ $languages[] = $ln;
+ }
+ }
+
+ ksort($commonLanguages);
+
+ // sort now by displayed language not the iso-code
+ usort( $languages, function ($a, $b) {
+ if ($a['code'] === $a['name'] && $b['code'] !== $b['name']) {
+ // If a doesn't have a name, but b does, list b before a
+ return 1;
+ }
+ if ($a['code'] !== $a['name'] && $b['code'] === $b['name']) {
+ // If a does have a name, but b doesn't, list a before b
+ return -1;
+ }
+ // Otherwise compare the names
+ return strcmp($a['name'], $b['name']);
+ });
+
+ return [
+ // reset indexes
+ 'commonlanguages' => array_values($commonLanguages),
+ 'languages' => $languages
+ ];
+ }
}
diff --git a/lib/private/L10N/L10N.php b/lib/private/L10N/L10N.php
index e9e720a3766..a12375c4214 100644
--- a/lib/private/L10N/L10N.php
+++ b/lib/private/L10N/L10N.php
@@ -1,9 +1,11 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Georg Ehrke <oc.list@georgehrke.com>
* @author Joas Schilling <coding@schilljs.com>
+ * @author Thomas Citharel <tcit@tcit.fr>
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
* @license AGPL-3.0
@@ -40,6 +42,9 @@ class L10N implements IL10N {
/** @var string Language of this object */
protected $lang;
+ /** @var string Locale of this object */
+ protected $locale;
+
/** @var string Plural forms (string) */
private $pluralFormString = 'nplurals=2; plural=(n != 1);';
@@ -53,14 +58,15 @@ class L10N implements IL10N {
* @param IFactory $factory
* @param string $app
* @param string $lang
+ * @param string $locale
* @param array $files
*/
- public function __construct(IFactory $factory, $app, $lang, array $files) {
+ public function __construct(IFactory $factory, $app, $lang, $locale, array $files) {
$this->factory = $factory;
$this->app = $app;
$this->lang = $lang;
+ $this->locale = $locale;
- $this->translations = [];
foreach ($files as $languageFile) {
$this->load($languageFile);
}
@@ -71,20 +77,33 @@ class L10N implements IL10N {
*
* @return string language
*/
- public function getLanguageCode() {
+ public function getLanguageCode(): string {
return $this->lang;
}
/**
+ * The code (en_US, fr_CA, ...) of the locale that is used for this instance
+ *
+ * @return string locale
+ */
+ public function getLocaleCode(): string {
+ return $this->locale;
+ }
+
+ /**
* Translating
* @param string $text The text we need a translation for
- * @param array $parameters default:array() Parameters for sprintf
+ * @param array|string $parameters default:array() Parameters for sprintf
* @return string Translation or the same text
*
* Returns the translation. If no translation is found, $text will be
* returned.
*/
- public function t($text, $parameters = array()) {
+ public function t(string $text, $parameters = []): string {
+ if (!\is_array($parameters)) {
+ $parameters = [$parameters];
+ }
+
return (string) new L10NString($this, $text, $parameters);
}
@@ -103,17 +122,17 @@ class L10N implements IL10N {
* provided by the po file.
*
*/
- public function n($text_singular, $text_plural, $count, $parameters = array()) {
+ public function n(string $text_singular, string $text_plural, int $count, array $parameters = []): string {
$identifier = "_${text_singular}_::_${text_plural}_";
if (isset($this->translations[$identifier])) {
return (string) new L10NString($this, $identifier, $parameters, $count);
- } else {
- if ($count === 1) {
- return (string) new L10NString($this, $text_singular, $parameters, $count);
- } else {
- return (string) new L10NString($this, $text_plural, $parameters, $count);
- }
}
+
+ if ($count === 1) {
+ return (string) new L10NString($this, $text_singular, $parameters, $count);
+ }
+
+ return (string) new L10NString($this, $text_plural, $parameters, $count);
}
/**
@@ -138,41 +157,44 @@ class L10N implements IL10N {
* - firstday: Returns the first day of the week (0 sunday - 6 saturday)
* - jsdate: Returns the short JS date format
*/
- public function l($type, $data = null, $options = array()) {
- // Use the language of the instance
- $locale = $this->getLanguageCode();
- if ($locale === 'sr@latin') {
- $locale = 'sr_latn';
+ public function l(string $type, $data = null, array $options = []) {
+ if (null === $this->locale) {
+ // Use the language of the instance
+ $this->locale = $this->getLanguageCode();
+ }
+ if ($this->locale === 'sr@latin') {
+ $this->locale = 'sr_latn';
}
if ($type === 'firstday') {
- return (int) Calendar::getFirstWeekday($locale);
+ return (int) Calendar::getFirstWeekday($this->locale);
}
if ($type === 'jsdate') {
- return (string) Calendar::getDateFormat('short', $locale);
+ return (string) Calendar::getDateFormat('short', $this->locale);
}
$value = new \DateTime();
if ($data instanceof \DateTime) {
$value = $data;
- } else if (is_string($data) && !is_numeric($data)) {
+ } else if (\is_string($data) && !is_numeric($data)) {
$data = strtotime($data);
$value->setTimestamp($data);
} else if ($data !== null) {
+ $data = (int)$data;
$value->setTimestamp($data);
}
- $options = array_merge(array('width' => 'long'), $options);
+ $options = array_merge(['width' => 'long'], $options);
$width = $options['width'];
switch ($type) {
case 'date':
- return (string) Calendar::formatDate($value, $width, $locale);
+ return (string) Calendar::formatDate($value, $width, $this->locale);
case 'datetime':
- return (string) Calendar::formatDatetime($value, $width, $locale);
+ return (string) Calendar::formatDatetime($value, $width, $this->locale);
case 'time':
- return (string) Calendar::formatTime($value, $width, $locale);
+ return (string) Calendar::formatTime($value, $width, $this->locale);
case 'weekdayName':
- return (string) Calendar::getWeekdayName($value, $width, $locale);
+ return (string) Calendar::getWeekdayName($value, $width, $this->locale);
default:
return false;
}
@@ -184,7 +206,7 @@ class L10N implements IL10N {
* Called by \OC_L10N_String
* @return array
*/
- public function getTranslations() {
+ public function getTranslations(): array {
return $this->translations;
}
@@ -192,10 +214,10 @@ class L10N implements IL10N {
* Returnsed function accepts the argument $n
*
* Called by \OC_L10N_String
- * @return string the plural form function
+ * @return \Closure the plural form function
*/
- public function getPluralFormFunction() {
- if (is_null($this->pluralFormFunction)) {
+ public function getPluralFormFunction(): \Closure {
+ if (\is_null($this->pluralFormFunction)) {
$lang = $this->getLanguageCode();
$this->pluralFormFunction = function($n) use ($lang) {
return PluralizationRules::get($n, $lang);
@@ -206,12 +228,12 @@ class L10N implements IL10N {
}
/**
- * @param $translationFile
+ * @param string $translationFile
* @return bool
*/
- protected function load($translationFile) {
+ protected function load(string $translationFile): bool {
$json = json_decode(file_get_contents($translationFile), true);
- if (!is_array($json)) {
+ if (!\is_array($json)) {
$jsonError = json_last_error();
\OC::$server->getLogger()->warning("Failed to load $translationFile - json error code: $jsonError", ['app' => 'l10n']);
return false;
diff --git a/lib/private/L10N/LanguageIterator.php b/lib/private/L10N/LanguageIterator.php
new file mode 100644
index 00000000000..ba8f942c912
--- /dev/null
+++ b/lib/private/L10N/LanguageIterator.php
@@ -0,0 +1,137 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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\L10N;
+
+use OCP\IConfig;
+use OCP\IUser;
+use OCP\L10N\ILanguageIterator;
+
+class LanguageIterator implements ILanguageIterator {
+ private $i = 0;
+ /** @var IConfig */
+ private $config;
+ /** @var IUser */
+ private $user;
+
+ public function __construct(IUser $user, IConfig $config) {
+ $this->config = $config;
+ $this->user = $user;
+ }
+
+ /**
+ * Rewind the Iterator to the first element
+ */
+ public function rewind() {
+ $this->i = 0;
+ }
+
+ /**
+ * Return the current element
+ *
+ * @since 14.0.0
+ */
+ public function current(): string {
+ switch($this->i) {
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 0:
+ $forcedLang = $this->config->getSystemValue('force_language', false);
+ if(is_string($forcedLang)) {
+ return $forcedLang;
+ }
+ $this->next();
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 1:
+ $forcedLang = $this->config->getSystemValue('force_language', false);
+ if(is_string($forcedLang)
+ && ($truncated = $this->getTruncatedLanguage($forcedLang)) !== $forcedLang
+ ) {
+ return $truncated;
+ }
+ $this->next();
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 2:
+ $userLang = $this->config->getUserValue($this->user->getUID(), 'core', 'lang', null);
+ if(is_string($userLang)) {
+ return $userLang;
+ }
+ $this->next();
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 3:
+ $userLang = $this->config->getUserValue($this->user->getUID(), 'core', 'lang', null);
+ if(is_string($userLang)
+ && ($truncated = $this->getTruncatedLanguage($userLang)) !== $userLang
+ ) {
+ return $truncated;
+ }
+ $this->next();
+ case 4:
+ return $this->config->getSystemValue('default_language', 'en');
+ /** @noinspection PhpMissingBreakStatementInspection */
+ case 5:
+ $defaultLang = $this->config->getSystemValue('default_language', 'en');
+ if(($truncated = $this->getTruncatedLanguage($defaultLang)) !== $defaultLang) {
+ return $truncated;
+ }
+ $this->next();
+ default:
+ return 'en';
+ }
+ }
+
+ /**
+ * Move forward to next element
+ *
+ * @since 14.0.0
+ */
+ public function next() {
+ ++$this->i;
+ }
+
+ /**
+ * Return the key of the current element
+ *
+ * @since 14.0.0
+ */
+ public function key(): int {
+ return $this->i;
+ }
+
+ /**
+ * Checks if current position is valid
+ *
+ * @since 14.0.0
+ */
+ public function valid(): bool {
+ return $this->i <= 6;
+ }
+
+ protected function getTruncatedLanguage(string $lang):string {
+ $pos = strpos($lang, '_');
+ if($pos !== false) {
+ $lang = substr($lang, 0, $pos);
+ }
+ return $lang;
+ }
+}
diff --git a/lib/private/LargeFileHelper.php b/lib/private/LargeFileHelper.php
index ea848f83622..d6dcbeedb48 100644..100755
--- a/lib/private/LargeFileHelper.php
+++ b/lib/private/LargeFileHelper.php
@@ -117,7 +117,7 @@ class LargeFileHelper {
public function getFileSizeViaCurl($fileName) {
if (\OC::$server->getIniWrapper()->getString('open_basedir') === '') {
$encodedFileName = rawurlencode($fileName);
- $ch = curl_init("file://$encodedFileName");
+ $ch = curl_init("file:///$encodedFileName");
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
@@ -185,14 +185,22 @@ class LargeFileHelper {
* @return int
*/
public function getFileMtime($fullPath) {
- if (\OC_Helper::is_function_enabled('exec')) {
- $os = strtolower(php_uname('s'));
- if (strpos($os, 'linux') !== false) {
- return $this->exec('stat -c %Y ' . escapeshellarg($fullPath));
+ try {
+ $result = filemtime($fullPath);
+ } catch (\Exception $e) {
+ $result =- 1;
+ }
+ if ($result < 0) {
+ if (\OC_Helper::is_function_enabled('exec')) {
+ $os = strtolower(php_uname('s'));
+ if (strpos($os, 'linux') !== false) {
+ return $this->exec('stat -c %Y ' . escapeshellarg($fullPath));
+ }
}
}
+ return $result;
+
- return filemtime($fullPath);
}
protected function exec($cmd) {
diff --git a/lib/private/Lock/DBLockingProvider.php b/lib/private/Lock/DBLockingProvider.php
index 016be64c097..6adb7488217 100644
--- a/lib/private/Lock/DBLockingProvider.php
+++ b/lib/private/Lock/DBLockingProvider.php
@@ -56,6 +56,11 @@ class DBLockingProvider extends AbstractLockingProvider {
private $sharedLocks = [];
/**
+ * @var bool
+ */
+ private $cacheSharedLocks;
+
+ /**
* Check if we have an open shared lock for a path
*
* @param string $path
@@ -73,8 +78,10 @@ class DBLockingProvider extends AbstractLockingProvider {
*/
protected function markAcquire(string $path, int $type) {
parent::markAcquire($path, $type);
- if ($type === self::LOCK_SHARED) {
- $this->sharedLocks[$path] = true;
+ if ($this->cacheSharedLocks) {
+ if ($type === self::LOCK_SHARED) {
+ $this->sharedLocks[$path] = true;
+ }
}
}
@@ -86,10 +93,12 @@ class DBLockingProvider extends AbstractLockingProvider {
*/
protected function markChange(string $path, int $targetType) {
parent::markChange($path, $targetType);
- if ($targetType === self::LOCK_SHARED) {
- $this->sharedLocks[$path] = true;
- } else if ($targetType === self::LOCK_EXCLUSIVE) {
- $this->sharedLocks[$path] = false;
+ if ($this->cacheSharedLocks) {
+ if ($targetType === self::LOCK_SHARED) {
+ $this->sharedLocks[$path] = true;
+ } else if ($targetType === self::LOCK_EXCLUSIVE) {
+ $this->sharedLocks[$path] = false;
+ }
}
}
@@ -98,12 +107,20 @@ class DBLockingProvider extends AbstractLockingProvider {
* @param \OCP\ILogger $logger
* @param \OCP\AppFramework\Utility\ITimeFactory $timeFactory
* @param int $ttl
+ * @param bool $cacheSharedLocks
*/
- public function __construct(IDBConnection $connection, ILogger $logger, ITimeFactory $timeFactory, int $ttl = 3600) {
+ public function __construct(
+ IDBConnection $connection,
+ ILogger $logger,
+ ITimeFactory $timeFactory,
+ int $ttl = 3600,
+ $cacheSharedLocks = true
+ ) {
$this->connection = $connection;
$this->logger = $logger;
$this->timeFactory = $timeFactory;
$this->ttl = $ttl;
+ $this->cacheSharedLocks = $cacheSharedLocks;
}
/**
@@ -193,6 +210,8 @@ class DBLockingProvider extends AbstractLockingProvider {
/**
* @param string $path
* @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
+ *
+ * @suppress SqlInjectionChecker
*/
public function releaseLock(string $path, int $type) {
$this->markRelease($path, $type);
@@ -203,6 +222,13 @@ class DBLockingProvider extends AbstractLockingProvider {
'UPDATE `*PREFIX*file_locks` SET `lock` = 0 WHERE `key` = ? AND `lock` = -1',
[$path]
);
+ } else if (!$this->cacheSharedLocks) {
+ $query = $this->connection->getQueryBuilder();
+ $query->update('file_locks')
+ ->set('lock', $query->func()->subtract('lock', $query->createNamedParameter(1)))
+ ->where($query->expr()->eq('key', $query->createNamedParameter($path)))
+ ->andWhere($query->expr()->gt('lock', $query->createNamedParameter(0)));
+ $query->execute();
}
}
@@ -256,11 +282,15 @@ class DBLockingProvider extends AbstractLockingProvider {
/**
* release all lock acquired by this instance which were marked using the mark* methods
+ *
* @suppress SqlInjectionChecker
*/
public function releaseAll() {
parent::releaseAll();
+ if (!$this->cacheSharedLocks) {
+ return;
+ }
// since we keep shared locks we need to manually clean those
$lockedPaths = array_keys($this->sharedLocks);
$lockedPaths = array_filter($lockedPaths, function ($path) {
diff --git a/lib/private/Lock/MemcacheLockingProvider.php b/lib/private/Lock/MemcacheLockingProvider.php
index 70ad972b46d..4d1b3dc0bca 100644
--- a/lib/private/Lock/MemcacheLockingProvider.php
+++ b/lib/private/Lock/MemcacheLockingProvider.php
@@ -72,12 +72,12 @@ class MemcacheLockingProvider extends AbstractLockingProvider {
public function acquireLock(string $path, int $type) {
if ($type === self::LOCK_SHARED) {
if (!$this->memcache->inc($path)) {
- throw new LockedException($path);
+ throw new LockedException($path, null, $this->getExistingLockForException($path));
}
} else {
$this->memcache->add($path, 0);
if (!$this->memcache->cas($path, 0, 'exclusive')) {
- throw new LockedException($path);
+ throw new LockedException($path, null, $this->getExistingLockForException($path));
}
}
$this->setTTL($path);
@@ -90,14 +90,20 @@ class MemcacheLockingProvider extends AbstractLockingProvider {
*/
public function releaseLock(string $path, int $type) {
if ($type === self::LOCK_SHARED) {
+ $newValue = 0;
if ($this->getOwnSharedLockCount($path) === 1) {
$removed = $this->memcache->cad($path, 1); // if we're the only one having a shared lock we can remove it in one go
if (!$removed) { //someone else also has a shared lock, decrease only
- $this->memcache->dec($path);
+ $newValue = $this->memcache->dec($path);
}
} else {
// if we own more than one lock ourselves just decrease
- $this->memcache->dec($path);
+ $newValue = $this->memcache->dec($path);
+ }
+
+ // if we somehow release more locks then exists, reset the lock
+ if ($newValue < 0) {
+ $this->memcache->cad($path, $newValue);
}
} else if ($type === self::LOCK_EXCLUSIVE) {
$this->memcache->cad($path, 'exclusive');
@@ -115,15 +121,26 @@ class MemcacheLockingProvider extends AbstractLockingProvider {
public function changeLock(string $path, int $targetType) {
if ($targetType === self::LOCK_SHARED) {
if (!$this->memcache->cas($path, 'exclusive', 1)) {
- throw new LockedException($path);
+ throw new LockedException($path, null, $this->getExistingLockForException($path));
}
} else if ($targetType === self::LOCK_EXCLUSIVE) {
// we can only change a shared lock to an exclusive if there's only a single owner of the shared lock
if (!$this->memcache->cas($path, 1, 'exclusive')) {
- throw new LockedException($path);
+ throw new LockedException($path, null, $this->getExistingLockForException($path));
}
}
$this->setTTL($path);
$this->markChange($path, $targetType);
}
+
+ private function getExistingLockForException($path) {
+ $existing = $this->memcache->get($path);
+ if (!$existing) {
+ return 'none';
+ } else if ($existing === 'exclusive') {
+ return $existing;
+ } else {
+ return $existing . ' shared locks';
+ }
+ }
}
diff --git a/lib/private/Log.php b/lib/private/Log.php
index bed0321bef3..4170acbb69a 100644
--- a/lib/private/Log.php
+++ b/lib/private/Log.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -36,6 +37,9 @@ namespace OC;
use InterfaSys\LogNormalizer\Normalizer;
+use OC\Log\ExceptionSerializer;
+use OCP\Log\IFileBased;
+use OCP\Log\IWriter;
use OCP\ILogger;
use OCP\Support\CrashReport\IRegistry;
use OCP\Util;
@@ -49,10 +53,9 @@ use OCP\Util;
*
* MonoLog is an example implementing this interface.
*/
-
class Log implements ILogger {
- /** @var string */
+ /** @var IWriter */
private $logger;
/** @var SystemConfig */
@@ -67,72 +70,20 @@ class Log implements ILogger {
/** @var IRegistry */
private $crashReporters;
- protected $methodsWithSensitiveParameters = [
- // Session/User
- 'completeLogin',
- 'login',
- 'checkPassword',
- 'checkPasswordNoLogging',
- 'loginWithPassword',
- 'updatePrivateKeyPassword',
- 'validateUserPass',
- 'loginWithToken',
- '\{closure\}',
-
- // TokenProvider
- 'getToken',
- 'isTokenPassword',
- 'getPassword',
- 'decryptPassword',
- 'logClientIn',
- 'generateToken',
- 'validateToken',
-
- // TwoFactorAuth
- 'solveChallenge',
- 'verifyChallenge',
-
- // ICrypto
- 'calculateHMAC',
- 'encrypt',
- 'decrypt',
-
- // LoginController
- 'tryLogin',
- 'confirmPassword',
-
- // LDAP
- 'bind',
- 'areCredentialsValid',
- 'invokeLDAPMethod',
-
- // Encryption
- 'storeKeyPair',
- 'setupUser',
- ];
-
/**
- * @param string $logger The logger that should be used
+ * @param IWriter $logger The logger that should be used
* @param SystemConfig $config the system config object
* @param Normalizer|null $normalizer
* @param IRegistry|null $registry
*/
- public function __construct($logger = null, SystemConfig $config = null, $normalizer = null, IRegistry $registry = null) {
+ public function __construct(IWriter $logger, SystemConfig $config = null, $normalizer = null, IRegistry $registry = null) {
// FIXME: Add this for backwards compatibility, should be fixed at some point probably
- if($config === null) {
+ if ($config === null) {
$config = \OC::$server->getSystemConfig();
}
$this->config = $config;
-
- // FIXME: Add this for backwards compatibility, should be fixed at some point probably
- if($logger === null) {
- $logType = $this->config->getValue('log_type', 'file');
- $this->logger = static::getLogClass($logType);
- call_user_func(array($this->logger, 'init'));
- } else {
- $this->logger = $logger;
- }
+ $this->logger = $logger;
if ($normalizer === null) {
$this->normalizer = new Normalizer();
} else {
@@ -148,8 +99,8 @@ class Log implements ILogger {
* @param array $context
* @return void
*/
- public function emergency($message, array $context = array()) {
- $this->log(Util::FATAL, $message, $context);
+ public function emergency(string $message, array $context = []) {
+ $this->log(ILogger::FATAL, $message, $context);
}
/**
@@ -162,8 +113,8 @@ class Log implements ILogger {
* @param array $context
* @return void
*/
- public function alert($message, array $context = array()) {
- $this->log(Util::ERROR, $message, $context);
+ public function alert(string $message, array $context = []) {
+ $this->log(ILogger::ERROR, $message, $context);
}
/**
@@ -175,8 +126,8 @@ class Log implements ILogger {
* @param array $context
* @return void
*/
- public function critical($message, array $context = array()) {
- $this->log(Util::ERROR, $message, $context);
+ public function critical(string $message, array $context = []) {
+ $this->log(ILogger::ERROR, $message, $context);
}
/**
@@ -187,8 +138,8 @@ class Log implements ILogger {
* @param array $context
* @return void
*/
- public function error($message, array $context = array()) {
- $this->log(Util::ERROR, $message, $context);
+ public function error(string $message, array $context = []) {
+ $this->log(ILogger::ERROR, $message, $context);
}
/**
@@ -201,8 +152,8 @@ class Log implements ILogger {
* @param array $context
* @return void
*/
- public function warning($message, array $context = array()) {
- $this->log(Util::WARN, $message, $context);
+ public function warning(string $message, array $context = []) {
+ $this->log(ILogger::WARN, $message, $context);
}
/**
@@ -212,8 +163,8 @@ class Log implements ILogger {
* @param array $context
* @return void
*/
- public function notice($message, array $context = array()) {
- $this->log(Util::INFO, $message, $context);
+ public function notice(string $message, array $context = []) {
+ $this->log(ILogger::INFO, $message, $context);
}
/**
@@ -225,8 +176,8 @@ class Log implements ILogger {
* @param array $context
* @return void
*/
- public function info($message, array $context = array()) {
- $this->log(Util::INFO, $message, $context);
+ public function info(string $message, array $context = []) {
+ $this->log(ILogger::INFO, $message, $context);
}
/**
@@ -236,75 +187,72 @@ class Log implements ILogger {
* @param array $context
* @return void
*/
- public function debug($message, array $context = array()) {
- $this->log(Util::DEBUG, $message, $context);
+ public function debug(string $message, array $context = []) {
+ $this->log(ILogger::DEBUG, $message, $context);
}
/**
* Logs with an arbitrary level.
*
- * @param mixed $level
+ * @param int $level
* @param string $message
* @param array $context
* @return void
*/
- public function log($level, $message, array $context = array()) {
- $minLevel = min($this->config->getValue('loglevel', Util::WARN), Util::FATAL);
- $logCondition = $this->config->getValue('log.condition', []);
+ public function log(int $level, string $message, array $context = []) {
+ $minLevel = $this->getLogLevel($context);
array_walk($context, [$this->normalizer, 'format']);
- if (isset($context['app'])) {
- $app = $context['app'];
-
- /**
- * check log condition based on the context of each log message
- * once this is met -> change the required log level to debug
- */
- if(!empty($logCondition)
- && isset($logCondition['apps'])
- && in_array($app, $logCondition['apps'], true)) {
- $minLevel = Util::DEBUG;
- }
+ $app = $context['app'] ?? 'no app in context';
- } else {
- $app = 'no app in context';
- }
// interpolate $message as defined in PSR-3
- $replace = array();
+ $replace = [];
foreach ($context as $key => $val) {
$replace['{' . $key . '}'] = $val;
}
-
- // interpolate replacement values into the message and return
$message = strtr($message, $replace);
+ if ($level >= $minLevel) {
+ $this->writeLog($app, $message, $level);
+ }
+ }
+
+ private function getLogLevel($context) {
/**
* check for a special log condition - this enables an increased log on
* a per request/user base
*/
- if($this->logConditionSatisfied === null) {
+ if ($this->logConditionSatisfied === null) {
// default to false to just process this once per request
$this->logConditionSatisfied = false;
- if(!empty($logCondition)) {
+ if (!empty($logCondition)) {
// check for secret token in the request
- if(isset($logCondition['shared_secret'])) {
+ if (isset($logCondition['shared_secret'])) {
$request = \OC::$server->getRequest();
+ if ($request->getMethod() === 'PUT' &&
+ strpos($request->getHeader('Content-Type'), 'application/x-www-form-urlencoded') === false &&
+ strpos($request->getHeader('Content-Type'), 'application/json') === false) {
+ $logSecretRequest = '';
+ } else {
+ $logSecretRequest = $request->getParam('log_secret', '');
+ }
+
// if token is found in the request change set the log condition to satisfied
- if($request && hash_equals($logCondition['shared_secret'], $request->getParam('log_secret', ''))) {
+ if ($request && hash_equals($logCondition['shared_secret'], $logSecretRequest)) {
$this->logConditionSatisfied = true;
}
}
// check for user
- if(isset($logCondition['users'])) {
+ if (isset($logCondition['users'])) {
$user = \OC::$server->getUserSession()->getUser();
// if the user matches set the log condition to satisfied
- if($user !== null && in_array($user->getUID(), $logCondition['users'], true)) {
+ if ($user !== null && in_array($user->getUID(), $logCondition['users'], true)) {
$this->logConditionSatisfied = true;
}
}
@@ -312,14 +260,26 @@ class Log implements ILogger {
}
// if log condition is satisfied change the required log level to DEBUG
- if($this->logConditionSatisfied) {
- $minLevel = Util::DEBUG;
+ if ($this->logConditionSatisfied) {
+ return ILogger::DEBUG;
}
- if ($level >= $minLevel) {
- $logger = $this->logger;
- call_user_func(array($logger, 'write'), $app, $message, $level);
+ if (isset($context['app'])) {
+ $logCondition = $this->config->getValue('log.condition', []);
+ $app = $context['app'];
+
+ /**
+ * check log condition based on the context of each log message
+ * once this is met -> change the required log level to debug
+ */
+ if (!empty($logCondition)
+ && isset($logCondition['apps'])
+ && in_array($app, $logCondition['apps'], true)) {
+ return ILogger::DEBUG;
+ }
}
+
+ return min($this->config->getValue('loglevel', ILogger::WARN), ILogger::FATAL);
}
/**
@@ -330,27 +290,25 @@ class Log implements ILogger {
* @return void
* @since 8.2.0
*/
- public function logException($exception, array $context = array()) {
- $level = Util::ERROR;
- if (isset($context['level'])) {
- $level = $context['level'];
- unset($context['level']);
- }
- $data = array(
- 'Exception' => get_class($exception),
- 'Message' => $exception->getMessage(),
- 'Code' => $exception->getCode(),
- 'Trace' => $exception->getTraceAsString(),
- 'File' => $exception->getFile(),
- 'Line' => $exception->getLine(),
- );
- $data['Trace'] = preg_replace('!(' . implode('|', $this->methodsWithSensitiveParameters) . ')\(.*\)!', '$1(*** sensitive parameters replaced ***)', $data['Trace']);
- if ($exception instanceof HintException) {
- $data['Hint'] = $exception->getHint();
+ public function logException(\Throwable $exception, array $context = []) {
+ $app = $context['app'] ?? 'no app in context';
+ $level = $context['level'] ?? ILogger::ERROR;
+
+ $serializer = new ExceptionSerializer();
+ $data = $serializer->serializeException($exception);
+ $data['CustomMessage'] = $context['message'] ?? '--';
+
+ $minLevel = $this->getLogLevel($context);
+
+ array_walk($context, [$this->normalizer, 'format']);
+
+ if ($level >= $minLevel) {
+ if (!$this->logger instanceof IFileBased) {
+ $data = json_encode($data, JSON_PARTIAL_OUTPUT_ON_ERROR);
+ }
+ $this->writeLog($app, $data, $level);
}
- $msg = isset($context['message']) ? $context['message'] : 'Exception';
- $msg .= ': ' . json_encode($data);
- $this->log($level, $msg, $context);
+
$context['level'] = $level;
if (!is_null($this->crashReporters)) {
$this->crashReporters->delegateReport($exception, $context);
@@ -358,24 +316,18 @@ class Log implements ILogger {
}
/**
- * @param string $logType
- * @return string
- * @internal
+ * @param string $app
+ * @param string|array $entry
+ * @param int $level
*/
- public static function getLogClass($logType) {
- switch (strtolower($logType)) {
- case 'errorlog':
- return \OC\Log\Errorlog::class;
- case 'syslog':
- return \OC\Log\Syslog::class;
- case 'file':
- return \OC\Log\File::class;
-
- // Backwards compatibility for old and fallback for unknown log types
- case 'owncloud':
- case 'nextcloud':
- default:
- return \OC\Log\File::class;
+ protected function writeLog(string $app, $entry, int $level) {
+ $this->logger->write($app, $entry, $level);
+ }
+
+ public function getLogPath():string {
+ if($this->logger instanceof IFileBased) {
+ return $this->logger->getLogFilePath();
}
+ throw new \RuntimeException('Log implementation has no path');
}
}
diff --git a/lib/private/Log/Errorlog.php b/lib/private/Log/Errorlog.php
index 37498c36aba..9dc8b2cc49c 100644
--- a/lib/private/Log/Errorlog.php
+++ b/lib/private/Log/Errorlog.php
@@ -25,14 +25,9 @@
namespace OC\Log;
-class Errorlog {
+use OCP\Log\IWriter;
-
- /**
- * Init class data
- */
- public static function init() {
- }
+class Errorlog implements IWriter {
/**
* write a message in the log
@@ -40,7 +35,7 @@ class Errorlog {
* @param string $message
* @param int $level
*/
- public static function write($app, $message, $level) {
+ public function write(string $app, $message, int $level) {
error_log('[owncloud]['.$app.']['.$level.'] '.$message);
}
}
diff --git a/lib/private/Log/ExceptionSerializer.php b/lib/private/Log/ExceptionSerializer.php
new file mode 100644
index 00000000000..768c6484963
--- /dev/null
+++ b/lib/private/Log/ExceptionSerializer.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Log;
+
+use OC\HintException;
+
+class ExceptionSerializer {
+ const methodsWithSensitiveParameters = [
+ // Session/User
+ 'completeLogin',
+ 'login',
+ 'checkPassword',
+ 'checkPasswordNoLogging',
+ 'loginWithPassword',
+ 'updatePrivateKeyPassword',
+ 'validateUserPass',
+ 'loginWithToken',
+ '{closure}',
+ 'createSessionToken',
+
+ // TokenProvider
+ 'getToken',
+ 'isTokenPassword',
+ 'getPassword',
+ 'decryptPassword',
+ 'logClientIn',
+ 'generateToken',
+ 'validateToken',
+
+ // TwoFactorAuth
+ 'solveChallenge',
+ 'verifyChallenge',
+
+ // ICrypto
+ 'calculateHMAC',
+ 'encrypt',
+ 'decrypt',
+
+ // LoginController
+ 'tryLogin',
+ 'confirmPassword',
+
+ // LDAP
+ 'bind',
+ 'areCredentialsValid',
+ 'invokeLDAPMethod',
+
+ // Encryption
+ 'storeKeyPair',
+ 'setupUser',
+ ];
+
+ private function filterTrace(array $trace) {
+ $sensitiveValues = [];
+ $trace = array_map(function (array $traceLine) use (&$sensitiveValues) {
+ foreach (self::methodsWithSensitiveParameters as $sensitiveMethod) {
+ if (strpos($traceLine['function'], $sensitiveMethod) !== false) {
+ $sensitiveValues = array_merge($sensitiveValues, $traceLine['args']);
+ $traceLine['args'] = ['*** sensitive parameters replaced ***'];
+ return $traceLine;
+ }
+ }
+ return $traceLine;
+ }, $trace);
+ return array_map(function (array $traceLine) use ($sensitiveValues) {
+ if (isset($traceLine['args'])) {
+ $traceLine['args'] = $this->removeValuesFromArgs($traceLine['args'], $sensitiveValues);
+ }
+ return $traceLine;
+ }, $trace);
+ }
+
+ private function removeValuesFromArgs($args, $values) {
+ foreach ($args as &$arg) {
+ if (in_array($arg, $values, true)) {
+ $arg = '*** sensitive parameter replaced ***';
+ } else if (is_array($arg)) {
+ $arg = $this->removeValuesFromArgs($arg, $values);
+ }
+ }
+ return $args;
+ }
+
+ private function encodeTrace($trace) {
+ $filteredTrace = $this->filterTrace($trace);
+ return array_map(function (array $line) {
+ if (isset($line['args'])) {
+ $line['args'] = array_map([$this, 'encodeArg'], $line['args']);
+ }
+ return $line;
+ }, $filteredTrace);
+ }
+
+ private function encodeArg($arg) {
+ if (is_object($arg)) {
+ $data = get_object_vars($arg);
+ $data['__class__'] = get_class($arg);
+ return array_map([$this, 'encodeArg'], $data);
+ } else if (is_array($arg)) {
+ return array_map([$this, 'encodeArg'], $arg);
+ } else {
+ return $arg;
+ }
+ }
+
+ public function serializeException(\Throwable $exception) {
+ $data = [
+ 'Exception' => get_class($exception),
+ 'Message' => $exception->getMessage(),
+ 'Code' => $exception->getCode(),
+ 'Trace' => $this->encodeTrace($exception->getTrace()),
+ 'File' => $exception->getFile(),
+ 'Line' => $exception->getLine(),
+ ];
+
+ if ($exception instanceof HintException) {
+ $data['Hint'] = $exception->getHint();
+ }
+
+ if ($exception->getPrevious()) {
+ $data['Previous'] = $this->serializeException($exception->getPrevious());
+ }
+
+ return $data;
+ }
+}
diff --git a/lib/private/Log/File.php b/lib/private/Log/File.php
index ba5027251d7..597cb54e402 100644
--- a/lib/private/Log/File.php
+++ b/lib/private/Log/File.php
@@ -36,6 +36,10 @@
*/
namespace OC\Log;
+use OC\SystemConfig;
+use OCP\Log\IFileBased;
+use OCP\Log\IWriter;
+use OCP\ILogger;
/**
* logging utilities
@@ -43,44 +47,38 @@ namespace OC\Log;
* Log is saved at data/nextcloud.log (on default)
*/
-class File {
- static protected $logFile;
+class File implements IWriter, IFileBased {
+ /** @var string */
+ protected $logFile;
+ /** @var SystemConfig */
+ private $config;
- /**
- * Init class data
- */
- public static function init() {
- $systemConfig = \OC::$server->getSystemConfig();
- $defaultLogFile = $systemConfig->getValue("datadirectory", \OC::$SERVERROOT.'/data').'/nextcloud.log';
- self::$logFile = $systemConfig->getValue("logfile", $defaultLogFile);
-
- /**
- * Fall back to default log file if specified logfile does not exist
- * and can not be created.
- */
- if (!file_exists(self::$logFile)) {
- if(!is_writable(dirname(self::$logFile))) {
- self::$logFile = $defaultLogFile;
- } else {
- if(!touch(self::$logFile)) {
- self::$logFile = $defaultLogFile;
- }
+ public function __construct(string $path, string $fallbackPath = '', SystemConfig $config) {
+ $this->logFile = $path;
+ if (!file_exists($this->logFile)) {
+ if(
+ (
+ !is_writable(dirname($this->logFile))
+ || !touch($this->logFile)
+ )
+ && $fallbackPath !== ''
+ ) {
+ $this->logFile = $fallbackPath;
}
}
+ $this->config = $config;
}
/**
* write a message in the log
* @param string $app
- * @param string $message
+ * @param string|array $message
* @param int $level
*/
- public static function write($app, $message, $level) {
- $config = \OC::$server->getSystemConfig();
-
+ public function write(string $app, $message, int $level) {
// default to ISO8601
- $format = $config->getValue('logdateformat', \DateTime::ATOM);
- $logTimeZone = $config->getValue('logtimezone', 'UTC');
+ $format = $this->config->getValue('logdateformat', \DateTime::ATOM);
+ $logTimeZone = $this->config->getValue('logtimezone', 'UTC');
try {
$timezone = new \DateTimeZone($logTimeZone);
} catch (\Exception $e) {
@@ -100,7 +98,7 @@ class File {
$time = $time->format($format);
$url = ($request->getRequestUri() !== '') ? $request->getRequestUri() : '--';
$method = is_string($request->getMethod()) ? $request->getMethod() : '--';
- if($config->getValue('installed', false)) {
+ if($this->config->getValue('installed', false)) {
$user = \OC_User::getUser() ? \OC_User::getUser() : '--';
} else {
$user = '--';
@@ -109,7 +107,7 @@ class File {
if ($userAgent === '') {
$userAgent = '--';
}
- $version = $config->getValue('version', '');
+ $version = $this->config->getValue('version', '');
$entry = compact(
'reqId',
'level',
@@ -135,9 +133,9 @@ class File {
}
}
$entry = json_encode($entry, JSON_PARTIAL_OUTPUT_ON_ERROR);
- $handle = @fopen(self::$logFile, 'a');
- if ((fileperms(self::$logFile) & 0777) != 0640) {
- @chmod(self::$logFile, 0640);
+ $handle = @fopen($this->logFile, 'a');
+ if ((fileperms($this->logFile) & 0777) != 0640) {
+ @chmod($this->logFile, 0640);
}
if ($handle) {
fwrite($handle, $entry."\n");
@@ -157,11 +155,10 @@ class File {
* @param int $offset
* @return array
*/
- public static function getEntries($limit=50, $offset=0) {
- self::init();
- $minLevel = \OC::$server->getSystemConfig()->getValue("loglevel", \OCP\Util::WARN);
+ public function getEntries(int $limit=50, int $offset=0):array {
+ $minLevel = $this->config->getValue("loglevel", ILogger::WARN);
$entries = array();
- $handle = @fopen(self::$logFile, 'rb');
+ $handle = @fopen($this->logFile, 'rb');
if ($handle) {
fseek($handle, 0, SEEK_END);
$pos = ftell($handle);
@@ -203,7 +200,7 @@ class File {
/**
* @return string
*/
- public static function getLogFilePath() {
- return self::$logFile;
+ public function getLogFilePath():string {
+ return $this->logFile;
}
}
diff --git a/lib/private/Log/LogFactory.php b/lib/private/Log/LogFactory.php
new file mode 100644
index 00000000000..5bb803cbaf2
--- /dev/null
+++ b/lib/private/Log/LogFactory.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ * @author Johannes Ernst <jernst@indiecomputing.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Log;
+
+use OC\Log;
+use OC\SystemConfig;
+use OCP\ILogger;
+use OCP\IServerContainer;
+use OCP\Log\ILogFactory;
+use OCP\Log\IWriter;
+
+class LogFactory implements ILogFactory {
+ /** @var IServerContainer */
+ private $c;
+ /** @var SystemConfig */
+ private $systemConfig;
+
+ public function __construct(IServerContainer $c, SystemConfig $systemConfig) {
+ $this->c = $c;
+ $this->systemConfig = $systemConfig;
+ }
+
+ /**
+ * @throws \OCP\AppFramework\QueryException
+ */
+ public function get(string $type):IWriter {
+ switch (strtolower($type)) {
+ case 'errorlog':
+ return new Errorlog();
+ case 'syslog':
+ return $this->c->resolve(Syslog::class);
+ case 'systemd':
+ return $this->c->resolve(Systemdlog::class);
+ case 'file':
+ return $this->buildLogFile();
+
+ // Backwards compatibility for old and fallback for unknown log types
+ case 'owncloud':
+ case 'nextcloud':
+ default:
+ return $this->buildLogFile();
+ }
+ }
+
+ public function getCustomLogger(string $path):ILogger {
+ $log = $this->buildLogFile($path);
+ return new Log($log, $this->systemConfig);
+ }
+
+ protected function buildLogFile(string $logFile = ''):File {
+ $defaultLogFile = $this->systemConfig->getValue('datadirectory', \OC::$SERVERROOT.'/data').'/nextcloud.log';
+ if($logFile === '') {
+ $logFile = $this->systemConfig->getValue('logfile', $defaultLogFile);
+ }
+ $fallback = $defaultLogFile !== $logFile ? $defaultLogFile : '';
+
+ return new File($logFile, $fallback, $this->systemConfig);
+ }
+}
diff --git a/lib/private/Log/Rotate.php b/lib/private/Log/Rotate.php
index d7c554374fd..cc41c804ad3 100644
--- a/lib/private/Log/Rotate.php
+++ b/lib/private/Log/Rotate.php
@@ -24,6 +24,7 @@
*/
namespace OC\Log;
+use OCP\Log\RotationTrait;
/**
* This rotates the current logfile to a new name, this way the total log usage
@@ -32,23 +33,17 @@ namespace OC\Log;
* location and manage that with your own tools.
*/
class Rotate extends \OC\BackgroundJob\Job {
- private $max_log_size;
+ use RotationTrait;
+
public function run($dummy) {
$systemConfig = \OC::$server->getSystemConfig();
- $logFile = $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', \OC::$SERVERROOT . '/data') . '/nextcloud.log');
- $this->max_log_size = \OC::$server->getConfig()->getSystemValue('log_rotate_size', false);
- if ($this->max_log_size) {
- $filesize = @filesize($logFile);
- if ($filesize >= $this->max_log_size) {
- $this->rotate($logFile);
- }
- }
- }
+ $this->filePath = $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', \OC::$SERVERROOT . '/data') . '/nextcloud.log');
- protected function rotate($logfile) {
- $rotatedLogfile = $logfile.'.1';
- rename($logfile, $rotatedLogfile);
- $msg = 'Log file "'.$logfile.'" was over '.$this->max_log_size.' bytes, moved to "'.$rotatedLogfile.'"';
- \OCP\Util::writeLog(Rotate::class, $msg, \OCP\Util::WARN);
+ $this->maxSize = \OC::$server->getConfig()->getSystemValue('log_rotate_size', 100 * 1024 * 1024);
+ if($this->shouldRotateBySize()) {
+ $rotatedFile = $this->rotate();
+ $msg = 'Log file "'.$this->filePath.'" was over '.$this->maxSize.' bytes, moved to "'.$rotatedFile.'"';
+ \OC::$server->getLogger()->warning($msg, ['app' => Rotate::class]);
+ }
}
}
diff --git a/lib/private/Log/Syslog.php b/lib/private/Log/Syslog.php
index c6ea0a40350..b652eb4343d 100644
--- a/lib/private/Log/Syslog.php
+++ b/lib/private/Log/Syslog.php
@@ -25,22 +25,25 @@
namespace OC\Log;
-class Syslog {
- static protected $levels = array(
- \OCP\Util::DEBUG => LOG_DEBUG,
- \OCP\Util::INFO => LOG_INFO,
- \OCP\Util::WARN => LOG_WARNING,
- \OCP\Util::ERROR => LOG_ERR,
- \OCP\Util::FATAL => LOG_CRIT,
- );
+use OCP\ILogger;
+use OCP\IConfig;
+use OCP\Log\IWriter;
- /**
- * Init class data
- */
- public static function init() {
- openlog(\OC::$server->getSystemConfig()->getValue("syslog_tag", "ownCloud"), LOG_PID | LOG_CONS, LOG_USER);
- // Close at shutdown
- register_shutdown_function('closelog');
+class Syslog implements IWriter {
+ protected $levels = [
+ ILogger::DEBUG => LOG_DEBUG,
+ ILogger::INFO => LOG_INFO,
+ ILogger::WARN => LOG_WARNING,
+ ILogger::ERROR => LOG_ERR,
+ ILogger::FATAL => LOG_CRIT,
+ ];
+
+ public function __construct(IConfig $config) {
+ openlog($config->getSystemValue('syslog_tag', 'Nextcloud'), LOG_PID | LOG_CONS, LOG_USER);
+ }
+
+ public function __destruct() {
+ closelog();
}
/**
@@ -49,8 +52,8 @@ class Syslog {
* @param string $message
* @param int $level
*/
- public static function write($app, $message, $level) {
- $syslog_level = self::$levels[$level];
+ public function write(string $app, $message, int $level) {
+ $syslog_level = $this->levels[$level];
syslog($syslog_level, '{'.$app.'} '.$message);
}
}
diff --git a/lib/private/Log/Systemdlog.php b/lib/private/Log/Systemdlog.php
new file mode 100644
index 00000000000..40e9c12386e
--- /dev/null
+++ b/lib/private/Log/Systemdlog.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018, Johannes Ernst
+ *
+ * @author Johannes Ernst <jernst@indiecomputing.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * 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\Log;
+
+use OC\HintException;
+use OCP\ILogger;
+use OCP\IConfig;
+use OCP\Log\IWriter;
+
+// The following fields are understood by systemd/journald, see
+// man systemd.journal-fields. All are optional:
+// MESSAGE=
+// The human-readable message string for this entry.
+// MESSAGE_ID=
+// A 128-bit message identifier ID
+// PRIORITY=
+// A priority value between 0 ("emerg") and 7 ("debug")
+// CODE_FILE=, CODE_LINE=, CODE_FUNC=
+// The code location generating this message, if known
+// ERRNO=
+// The low-level Unix error number causing this entry, if any.
+// SYSLOG_FACILITY=, SYSLOG_IDENTIFIER=, SYSLOG_PID=
+// Syslog compatibility fields
+
+class Systemdlog implements IWriter {
+ protected $levels = [
+ ILogger::DEBUG => 7,
+ ILogger::INFO => 6,
+ ILogger::WARN => 4,
+ ILogger::ERROR => 3,
+ ILogger::FATAL => 2,
+ ];
+
+ protected $syslogId;
+
+ public function __construct(IConfig $config) {
+ if(!function_exists('sd_journal_send')) {
+ throw new HintException(
+ 'PHP extension php-systemd is not available.',
+ 'Please install and enable PHP extension systemd if you wish to log to the Systemd journal.');
+
+ }
+ $this->syslogId = $config->getSystemValue('syslog_tag', 'Nextcloud');
+ }
+
+ /**
+ * Write a message to the log.
+ * @param string $app
+ * @param string $message
+ * @param int $level
+ */
+ public function write(string $app, $message, int $level) {
+ $journal_level = $this->levels[$level];
+ sd_journal_send('PRIORITY='.$journal_level,
+ 'SYSLOG_IDENTIFIER='.$this->syslogId,
+ 'MESSAGE={'.$app.'} '.$message);
+ }
+}
diff --git a/lib/private/Mail/Attachment.php b/lib/private/Mail/Attachment.php
index 822fca5a24e..b696451e41c 100644
--- a/lib/private/Mail/Attachment.php
+++ b/lib/private/Mail/Attachment.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
*
@@ -45,7 +46,7 @@ class Attachment implements IAttachment {
* @return $this
* @since 13.0.0
*/
- public function setFilename($filename) {
+ public function setFilename(string $filename): IAttachment {
$this->swiftAttachment->setFilename($filename);
return $this;
}
@@ -55,7 +56,7 @@ class Attachment implements IAttachment {
* @return $this
* @since 13.0.0
*/
- public function setContentType($contentType) {
+ public function setContentType(string $contentType): IAttachment {
$this->swiftAttachment->setContentType($contentType);
return $this;
}
@@ -65,7 +66,7 @@ class Attachment implements IAttachment {
* @return $this
* @since 13.0.0
*/
- public function setBody($body) {
+ public function setBody(string $body): IAttachment {
$this->swiftAttachment->setBody($body);
return $this;
}
@@ -73,7 +74,7 @@ class Attachment implements IAttachment {
/**
* @return \Swift_Mime_Attachment
*/
- public function getSwiftAttachment() {
+ public function getSwiftAttachment(): \Swift_Mime_Attachment {
return $this->swiftAttachment;
}
diff --git a/lib/private/Mail/EMailTemplate.php b/lib/private/Mail/EMailTemplate.php
index 0535dabc13e..4c56a316042 100644
--- a/lib/private/Mail/EMailTemplate.php
+++ b/lib/private/Mail/EMailTemplate.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright 2017, Morris Jobke <hey@morrisjobke.de>
* @copyright 2017, Lukas Reschke <lukas@statuscode.ch>
@@ -228,13 +229,13 @@ EOF;
<tr style="padding:0;text-align:left;vertical-align:top">
<th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left">
<center data-parsed="" style="min-width:490px;width:100%%">
- <table class="button btn default primary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;margin-right:15px;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto">
+ <table class="button btn default primary float-center" style="Margin:0 0 30px 0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0 0 30px 0;margin-right:15px;max-height:40px;max-width:200px;padding:0;text-align:center;vertical-align:top;width:auto;background:%1\$s;background-color:%1\$s;color:#fefefe;">
<tr style="padding:0;text-align:left;vertical-align:top">
<td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
<table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%%">
<tr style="padding:0;text-align:left;vertical-align:top">
- <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:%s;border:0 solid %s;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
- <a href="%s" style="Margin:0;border:0 solid %s;border-radius:2px;color:%s;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;outline:1px solid %s;text-decoration:none">%s</a>
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border:0 solid %2\$s;border-collapse:collapse!important;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <a href="%3\$s" style="Margin:0;border:0 solid %4\$s;border-radius:2px;color:%5\$s;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;outline:1px solid %6\$s;text-decoration:none">%7\$s</a>
</td>
</tr>
</table>
@@ -247,7 +248,7 @@ EOF;
<table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%%">
<tr style="padding:0;text-align:left;vertical-align:top">
<td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:#777;border:0 solid #777;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
- <a href="%s" style="Margin:0;background-color:#fff;border:0 solid #777;border-radius:2px;color:#6C6C6C!important;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;outline:1px solid #CBCBCB;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">%s</a>
+ <a href="%8\$s" style="Margin:0;background-color:#fff;border:0 solid #777;border-radius:2px;color:#6C6C6C!important;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;outline:1px solid #CBCBCB;padding:10px 25px 10px 25px;text-align:left;text-decoration:none">%9\$s</a>
</td>
</tr>
</table>
@@ -281,13 +282,13 @@ EOF;
<tr style="padding:0;text-align:left;vertical-align:top">
<th style="Margin:0;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;line-height:1.3;margin:0;padding:0;text-align:left">
<center data-parsed="" style="min-width:490px;width:100%%">
- <table class="button btn default primary float-center" style="Margin:0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0;max-height:40px;padding:0;text-align:center;vertical-align:top;width:auto">
+ <table class="button btn default primary float-center" style="Margin:0;border-collapse:collapse;border-spacing:0;display:inline-block;float:none;margin:0;max-height:40px;padding:0;text-align:center;vertical-align:top;width:auto;background:%1\$s;color:#fefefe;background-color:%1\$s;">
<tr style="padding:0;text-align:left;vertical-align:top">
<td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border-collapse:collapse!important;color:#0a0a0a;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
<table style="border-collapse:collapse;border-spacing:0;padding:0;text-align:left;vertical-align:top;width:100%%">
<tr style="padding:0;text-align:left;vertical-align:top">
- <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;background:%s;border:0 solid %s;border-collapse:collapse!important;color:#fefefe;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
- <a href="%s" style="Margin:0;border:0 solid %s;border-radius:2px;color:%s;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;outline:1px solid %s;text-decoration:none">%s</a>
+ <td style="-moz-hyphens:auto;-webkit-hyphens:auto;Margin:0;border:0 solid %2\$;border-collapse:collapse!important;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:400;hyphens:auto;line-height:1.3;margin:0;padding:0;text-align:left;vertical-align:top;word-wrap:break-word">
+ <a href="%3\$s" style="Margin:0;border:0 solid %4\$s;border-radius:2px;color:%5\$s;display:inline-block;font-family:Lucida Grande,Geneva,Verdana,sans-serif;font-size:16px;font-weight:regular;line-height:1.3;margin:0;padding:10px 25px 10px 25px;text-align:left;outline:1px solid %5\$s;text-decoration:none">%7\$s</a>
</td>
</tr>
</table>
@@ -367,7 +368,7 @@ EOF;
*
* @param string $subject
*/
- public function setSubject($subject) {
+ public function setSubject(string $subject) {
$this->subject = $subject;
}
@@ -391,7 +392,7 @@ EOF;
* @param string|bool $plainTitle Title that is used in the plain text email
* if empty the $title is used, if false none will be used
*/
- public function addHeading($title, $plainTitle = '') {
+ public function addHeading(string $title, $plainTitle = '') {
if ($this->footerAdded) {
return;
}
@@ -420,21 +421,22 @@ EOF;
/**
* Adds a paragraph to the body of the email
*
- * @param string $text
+ * @param string $text Note: When $plainText falls back to this, HTML is automatically escaped in the HTML email
* @param string|bool $plainText Text that is used in the plain text email
* if empty the $text is used, if false none will be used
*/
- public function addBodyText($text, $plainText = '') {
+ public function addBodyText(string $text, $plainText = '') {
if ($this->footerAdded) {
return;
}
if ($plainText === '') {
$plainText = $text;
+ $text = htmlspecialchars($text);
}
$this->ensureBodyIsOpened();
- $this->htmlBody .= vsprintf($this->bodyText, [htmlspecialchars($text)]);
+ $this->htmlBody .= vsprintf($this->bodyText, [$text]);
if ($plainText !== false) {
$this->plainBody .= $plainText . PHP_EOL . PHP_EOL;
}
@@ -443,28 +445,30 @@ EOF;
/**
* Adds a list item to the body of the email
*
- * @param string $text
- * @param string $metaInfo
+ * @param string $text Note: When $plainText falls back to this, HTML is automatically escaped in the HTML email
+ * @param string $metaInfo Note: When $plainMetaInfo falls back to this, HTML is automatically escaped in the HTML email
* @param string $icon Absolute path, must be 16*16 pixels
- * @param string $plainText Text that is used in the plain text email
+ * @param string|bool $plainText Text that is used in the plain text email
* if empty the $text is used, if false none will be used
- * @param string $plainMetaInfo Meta info that is used in the plain text email
+ * @param string|bool $plainMetaInfo Meta info that is used in the plain text email
* if empty the $metaInfo is used, if false none will be used
* @since 12.0.0
*/
- public function addBodyListItem($text, $metaInfo = '', $icon = '', $plainText = '', $plainMetaInfo = '') {
+ public function addBodyListItem(string $text, string $metaInfo = '', string $icon = '', $plainText = '', $plainMetaInfo = '') {
$this->ensureBodyListOpened();
if ($plainText === '') {
$plainText = $text;
+ $text = htmlspecialchars($text);
}
if ($plainMetaInfo === '') {
$plainMetaInfo = $metaInfo;
+ $metaInfo = htmlspecialchars($metaInfo);
}
- $htmlText = htmlspecialchars($text);
+ $htmlText = $text;
if ($metaInfo) {
- $htmlText = '<em style="color:#777;">' . htmlspecialchars($metaInfo) . '</em><br>' . $htmlText;
+ $htmlText = '<em style="color:#777;">' . $metaInfo . '</em><br>' . $htmlText;
}
if ($icon !== '') {
$icon = '<img src="' . htmlspecialchars($icon) . '" alt="&bull;">';
@@ -503,28 +507,30 @@ EOF;
/**
* Adds a button group of two buttons to the body of the email
*
- * @param string $textLeft Text of left button
+ * @param string $textLeft Text of left button; Note: When $plainTextLeft falls back to this, HTML is automatically escaped in the HTML email
* @param string $urlLeft URL of left button
- * @param string $textRight Text of right button
+ * @param string $textRight Text of right button; Note: When $plainTextRight falls back to this, HTML is automatically escaped in the HTML email
* @param string $urlRight URL of right button
* @param string $plainTextLeft Text of left button that is used in the plain text version - if unset the $textLeft is used
* @param string $plainTextRight Text of right button that is used in the plain text version - if unset the $textRight is used
*/
- public function addBodyButtonGroup($textLeft,
- $urlLeft,
- $textRight,
- $urlRight,
- $plainTextLeft = '',
- $plainTextRight = '') {
+ public function addBodyButtonGroup(string $textLeft,
+ string $urlLeft,
+ string $textRight,
+ string $urlRight,
+ string $plainTextLeft = '',
+ string $plainTextRight = '') {
if ($this->footerAdded) {
return;
}
if ($plainTextLeft === '') {
$plainTextLeft = $textLeft;
+ $textLeft = htmlspecialchars($textLeft);
}
if ($plainTextRight === '') {
$plainTextRight = $textRight;
+ $textRight = htmlspecialchars($textRight);
}
$this->ensureBodyIsOpened();
@@ -533,7 +539,7 @@ EOF;
$color = $this->themingDefaults->getColorPrimary();
$textColor = $this->themingDefaults->getTextColorPrimary();
- $this->htmlBody .= vsprintf($this->buttonGroup, [$color, $color, $urlLeft, $color, $textColor, $textColor, htmlspecialchars($textLeft), $urlRight, htmlspecialchars($textRight)]);
+ $this->htmlBody .= vsprintf($this->buttonGroup, [$color, $color, $urlLeft, $color, $textColor, $textColor, $textLeft, $urlRight, $textRight]);
$this->plainBody .= $plainTextLeft . ': ' . $urlLeft . PHP_EOL;
$this->plainBody .= $plainTextRight . ': ' . $urlRight . PHP_EOL . PHP_EOL;
@@ -542,14 +548,14 @@ EOF;
/**
* Adds a button to the body of the email
*
- * @param string $text Text of button
+ * @param string $text Text of button; Note: When $plainText falls back to this, HTML is automatically escaped in the HTML email
* @param string $url URL of button
* @param string $plainText Text of button in plain text version
* if empty the $text is used, if false none will be used
*
* @since 12.0.0
*/
- public function addBodyButton($text, $url, $plainText = '') {
+ public function addBodyButton(string $text, string $url, $plainText = '') {
if ($this->footerAdded) {
return;
}
@@ -559,11 +565,12 @@ EOF;
if ($plainText === '') {
$plainText = $text;
+ $text = htmlspecialchars($text);
}
$color = $this->themingDefaults->getColorPrimary();
$textColor = $this->themingDefaults->getTextColorPrimary();
- $this->htmlBody .= vsprintf($this->button, [$color, $color, $url, $color, $textColor, $textColor, htmlspecialchars($text)]);
+ $this->htmlBody .= vsprintf($this->button, [$color, $color, $url, $color, $textColor, $textColor, $text]);
if ($plainText !== false) {
$this->plainBody .= $plainText . ': ';
@@ -592,7 +599,7 @@ EOF;
*
* @param string $text If the text is empty the default "Name - Slogan<br>This is an automatically sent email" will be used
*/
- public function addFooter($text = '') {
+ public function addFooter(string $text = '') {
if($text === '') {
$text = $this->themingDefaults->getName() . ' - ' . $this->themingDefaults->getSlogan() . '<br>' . $this->l10n->t('This is an automatically sent email, please do not reply.');
}
@@ -615,7 +622,7 @@ EOF;
*
* @return string
*/
- public function renderSubject() {
+ public function renderSubject(): string {
return $this->subject;
}
@@ -624,7 +631,7 @@ EOF;
*
* @return string
*/
- public function renderHtml() {
+ public function renderHtml(): string {
if (!$this->footerAdded) {
$this->footerAdded = true;
$this->ensureBodyIsClosed();
@@ -638,7 +645,7 @@ EOF;
*
* @return string
*/
- public function renderText() {
+ public function renderText(): string {
if (!$this->footerAdded) {
$this->footerAdded = true;
$this->ensureBodyIsClosed();
diff --git a/lib/private/Mail/Mailer.php b/lib/private/Mail/Mailer.php
index 3637bb1e27d..6f148bc0c6e 100644
--- a/lib/private/Mail/Mailer.php
+++ b/lib/private/Mail/Mailer.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -25,6 +26,8 @@
namespace OC\Mail;
+use Egulias\EmailValidator\EmailValidator;
+use Egulias\EmailValidator\Validation\RFCValidation;
use OCP\Defaults;
use OCP\IConfig;
use OCP\IL10N;
@@ -54,7 +57,7 @@ use OCP\Mail\IMessage;
* @package OC\Mail
*/
class Mailer implements IMailer {
- /** @var \Swift_SmtpTransport|\Swift_SendmailTransport|\Swift_MailTransport Cached transport */
+ /** @var \Swift_Mailer Cached mailer */
private $instance = null;
/** @var IConfig */
private $config;
@@ -91,8 +94,9 @@ class Mailer implements IMailer {
*
* @return IMessage
*/
- public function createMessage() {
- return new Message(new \Swift_Message());
+ public function createMessage(): IMessage {
+ $plainTextOnly = $this->config->getSystemValue('mail_send_plaintext_only', false);
+ return new Message(new \Swift_Message(), $plainTextOnly);
}
/**
@@ -102,8 +106,8 @@ class Mailer implements IMailer {
* @return IAttachment
* @since 13.0.0
*/
- public function createAttachment($data = null, $filename = null, $contentType = null) {
- return new Attachment(\Swift_Attachment::newInstance($data, $filename, $contentType));
+ public function createAttachment($data = null, $filename = null, $contentType = null): IAttachment {
+ return new Attachment(new \Swift_Attachment($data, $filename, $contentType));
}
/**
@@ -112,7 +116,7 @@ class Mailer implements IMailer {
* @return IAttachment
* @since 13.0.0
*/
- public function createAttachmentFromPath($path, $contentType = null) {
+ public function createAttachmentFromPath(string $path, $contentType = null): IAttachment {
return new Attachment(\Swift_Attachment::fromPath($path, $contentType));
}
@@ -124,7 +128,7 @@ class Mailer implements IMailer {
* @return IEMailTemplate
* @since 12.0.0
*/
- public function createEMailTemplate($emailId, array $data = []) {
+ public function createEMailTemplate(string $emailId, array $data = []): IEMailTemplate {
$class = $this->config->getSystemValue('mail_template_class', '');
if ($class !== '' && class_exists($class) && is_a($class, EMailTemplate::class, true)) {
@@ -156,7 +160,7 @@ class Mailer implements IMailer {
* @throws \Exception In case it was not possible to send the message. (for example if an invalid mail address
* has been supplied.)
*/
- public function send(IMessage $message) {
+ public function send(IMessage $message): array {
$debugMode = $this->config->getSystemValue('mail_smtpdebug', false);
if (empty($message->getFrom())) {
@@ -191,8 +195,11 @@ class Mailer implements IMailer {
* @param string $email Email address to be validated
* @return bool True if the mail address is valid, false otherwise
*/
- public function validateMailAddress($email) {
- return \Swift_Validate::email($this->convertEmail($email));
+ public function validateMailAddress(string $email): bool {
+ $validator = new EmailValidator();
+ $validation = new RFCValidation();
+
+ return $validator->isValid($this->convertEmail($email), $validation);
}
/**
@@ -203,8 +210,8 @@ class Mailer implements IMailer {
* @param string $email
* @return string Converted mail address if `idn_to_ascii` exists
*/
- protected function convertEmail($email) {
- if (!function_exists('idn_to_ascii') || strpos($email, '@') === false) {
+ protected function convertEmail(string $email): string {
+ if (!function_exists('idn_to_ascii') || !defined('INTL_IDNA_VARIANT_UTS46') || strpos($email, '@') === false) {
return $email;
}
@@ -213,32 +220,24 @@ class Mailer implements IMailer {
return $name.'@'.$domain;
}
- /**
- * Returns whatever transport is configured within the config
- *
- * @return \Swift_SmtpTransport|\Swift_SendmailTransport|\Swift_MailTransport
- */
- protected function getInstance() {
+ protected function getInstance(): \Swift_Mailer {
if (!is_null($this->instance)) {
return $this->instance;
}
- switch ($this->config->getSystemValue('mail_smtpmode', 'php')) {
- case 'smtp':
- $this->instance = $this->getSmtpInstance();
- break;
+ $transport = null;
+
+ switch ($this->config->getSystemValue('mail_smtpmode', 'smtp')) {
case 'sendmail':
- // FIXME: Move into the return statement but requires proper testing
- // for SMTP and mail as well. Thus not really doable for a
- // minor release.
- $this->instance = \Swift_Mailer::newInstance($this->getSendMailInstance());
+ $transport = $this->getSendMailInstance();
break;
+ case 'smtp':
default:
- $this->instance = $this->getMailInstance();
+ $transport = $this->getSmtpInstance();
break;
}
- return $this->instance;
+ return new \Swift_Mailer($transport);
}
/**
@@ -246,8 +245,8 @@ class Mailer implements IMailer {
*
* @return \Swift_SmtpTransport
*/
- protected function getSmtpInstance() {
- $transport = \Swift_SmtpTransport::newInstance();
+ protected function getSmtpInstance(): \Swift_SmtpTransport {
+ $transport = new \Swift_SmtpTransport();
$transport->setTimeout($this->config->getSystemValue('mail_smtptimeout', 10));
$transport->setHost($this->config->getSystemValue('mail_smtphost', '127.0.0.1'));
$transport->setPort($this->config->getSystemValue('mail_smtpport', 25));
@@ -260,7 +259,7 @@ class Mailer implements IMailer {
if (!empty($smtpSecurity)) {
$transport->setEncryption($smtpSecurity);
}
- $transport->start();
+
return $transport;
}
@@ -269,8 +268,8 @@ class Mailer implements IMailer {
*
* @return \Swift_SendmailTransport
*/
- protected function getSendMailInstance() {
- switch ($this->config->getSystemValue('mail_smtpmode', 'php')) {
+ protected function getSendMailInstance(): \Swift_SendmailTransport {
+ switch ($this->config->getSystemValue('mail_smtpmode', 'smtp')) {
case 'qmail':
$binaryPath = '/var/qmail/bin/sendmail';
break;
@@ -279,16 +278,6 @@ class Mailer implements IMailer {
break;
}
- return \Swift_SendmailTransport::newInstance($binaryPath . ' -bs');
+ return new \Swift_SendmailTransport($binaryPath . ' -bs');
}
-
- /**
- * Returns the mail transport
- *
- * @return \Swift_MailTransport
- */
- protected function getMailInstance() {
- return \Swift_MailTransport::newInstance();
- }
-
}
diff --git a/lib/private/Mail/Message.php b/lib/private/Mail/Message.php
index c695f0f4fb1..8a13e2c108c 100644
--- a/lib/private/Mail/Message.php
+++ b/lib/private/Mail/Message.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -38,12 +39,12 @@ use Swift_Message;
class Message implements IMessage {
/** @var Swift_Message */
private $swiftMessage;
+ /** @var bool */
+ private $plainTextOnly;
- /**
- * @param Swift_Message $swiftMessage
- */
- public function __construct(Swift_Message $swiftMessage) {
+ public function __construct(Swift_Message $swiftMessage, bool $plainTextOnly) {
$this->swiftMessage = $swiftMessage;
+ $this->plainTextOnly = $plainTextOnly;
}
/**
@@ -51,7 +52,7 @@ class Message implements IMessage {
* @return $this
* @since 13.0.0
*/
- public function attach(IAttachment $attachment) {
+ public function attach(IAttachment $attachment): IMessage {
/** @var Attachment $attachment */
$this->swiftMessage->attach($attachment->getSwiftAttachment());
return $this;
@@ -64,12 +65,12 @@ class Message implements IMessage {
* @param array $addresses Array of mail addresses, key will get converted
* @return array Converted addresses if `idn_to_ascii` exists
*/
- protected function convertAddresses($addresses) {
- if (!function_exists('idn_to_ascii')) {
+ protected function convertAddresses(array $addresses): array {
+ if (!function_exists('idn_to_ascii') || !defined('INTL_IDNA_VARIANT_UTS46')) {
return $addresses;
}
- $convertedAddresses = array();
+ $convertedAddresses = [];
foreach($addresses as $email => $readableName) {
if(!is_numeric($email)) {
@@ -94,7 +95,7 @@ class Message implements IMessage {
* @param array $addresses Example: array('sender@domain.org', 'other@domain.org' => 'A name')
* @return $this
*/
- public function setFrom(array $addresses) {
+ public function setFrom(array $addresses): IMessage {
$addresses = $this->convertAddresses($addresses);
$this->swiftMessage->setFrom($addresses);
@@ -106,7 +107,7 @@ class Message implements IMessage {
*
* @return array
*/
- public function getFrom() {
+ public function getFrom(): array {
return $this->swiftMessage->getFrom();
}
@@ -116,7 +117,7 @@ class Message implements IMessage {
* @param array $addresses
* @return $this
*/
- public function setReplyTo(array $addresses) {
+ public function setReplyTo(array $addresses): IMessage {
$addresses = $this->convertAddresses($addresses);
$this->swiftMessage->setReplyTo($addresses);
@@ -126,9 +127,9 @@ class Message implements IMessage {
/**
* Returns the Reply-To address of this message
*
- * @return array
+ * @return string
*/
- public function getReplyTo() {
+ public function getReplyTo(): string {
return $this->swiftMessage->getReplyTo();
}
@@ -138,7 +139,7 @@ class Message implements IMessage {
* @param array $recipients Example: array('recipient@domain.org', 'other@domain.org' => 'A name')
* @return $this
*/
- public function setTo(array $recipients) {
+ public function setTo(array $recipients): IMessage {
$recipients = $this->convertAddresses($recipients);
$this->swiftMessage->setTo($recipients);
@@ -150,7 +151,7 @@ class Message implements IMessage {
*
* @return array
*/
- public function getTo() {
+ public function getTo(): array {
return $this->swiftMessage->getTo();
}
@@ -160,7 +161,7 @@ class Message implements IMessage {
* @param array $recipients Example: array('recipient@domain.org', 'other@domain.org' => 'A name')
* @return $this
*/
- public function setCc(array $recipients) {
+ public function setCc(array $recipients): IMessage {
$recipients = $this->convertAddresses($recipients);
$this->swiftMessage->setCc($recipients);
@@ -172,7 +173,7 @@ class Message implements IMessage {
*
* @return array
*/
- public function getCc() {
+ public function getCc(): array {
return $this->swiftMessage->getCc();
}
@@ -182,7 +183,7 @@ class Message implements IMessage {
* @param array $recipients Example: array('recipient@domain.org', 'other@domain.org' => 'A name')
* @return $this
*/
- public function setBcc(array $recipients) {
+ public function setBcc(array $recipients): IMessage {
$recipients = $this->convertAddresses($recipients);
$this->swiftMessage->setBcc($recipients);
@@ -194,17 +195,17 @@ class Message implements IMessage {
*
* @return array
*/
- public function getBcc() {
+ public function getBcc(): array {
return $this->swiftMessage->getBcc();
}
/**
* Set the subject of this message.
*
- * @param $subject
- * @return $this
+ * @param string $subject
+ * @return IMessage
*/
- public function setSubject($subject) {
+ public function setSubject(string $subject): IMessage {
$this->swiftMessage->setSubject($subject);
return $this;
}
@@ -214,7 +215,7 @@ class Message implements IMessage {
*
* @return string
*/
- public function getSubject() {
+ public function getSubject(): string {
return $this->swiftMessage->getSubject();
}
@@ -224,7 +225,7 @@ class Message implements IMessage {
* @param string $body
* @return $this
*/
- public function setPlainBody($body) {
+ public function setPlainBody(string $body): IMessage {
$this->swiftMessage->setBody($body);
return $this;
}
@@ -234,7 +235,7 @@ class Message implements IMessage {
*
* @return string
*/
- public function getPlainBody() {
+ public function getPlainBody(): string {
return $this->swiftMessage->getBody();
}
@@ -245,7 +246,9 @@ class Message implements IMessage {
* @return $this
*/
public function setHtmlBody($body) {
- $this->swiftMessage->addPart($body, 'text/html');
+ if (!$this->plainTextOnly) {
+ $this->swiftMessage->addPart($body, 'text/html');
+ }
return $this;
}
@@ -253,7 +256,7 @@ class Message implements IMessage {
* Get's the underlying SwiftMessage
* @return Swift_Message
*/
- public function getSwiftMessage() {
+ public function getSwiftMessage(): Swift_Message {
return $this->swiftMessage;
}
@@ -263,7 +266,9 @@ class Message implements IMessage {
* @return $this
*/
public function setBody($body, $contentType) {
- $this->swiftMessage->setBody($body, $contentType);
+ if (!$this->plainTextOnly || $contentType !== 'text/html') {
+ $this->swiftMessage->setBody($body, $contentType);
+ }
return $this;
}
@@ -271,10 +276,12 @@ class Message implements IMessage {
* @param IEMailTemplate $emailTemplate
* @return $this
*/
- public function useTemplate(IEMailTemplate $emailTemplate) {
+ public function useTemplate(IEMailTemplate $emailTemplate): IMessage {
$this->setSubject($emailTemplate->renderSubject());
$this->setPlainBody($emailTemplate->renderText());
- $this->setHtmlBody($emailTemplate->renderHtml());
+ if (!$this->plainTextOnly) {
+ $this->setHtmlBody($emailTemplate->renderHtml());
+ }
return $this;
}
}
diff --git a/lib/private/Memcache/Factory.php b/lib/private/Memcache/Factory.php
index cb2cd8aabe2..8678c1b7999 100644
--- a/lib/private/Memcache/Factory.php
+++ b/lib/private/Memcache/Factory.php
@@ -185,11 +185,11 @@ class Factory implements ICacheFactory {
}
/**
- * check local memcache availability
+ * Check if a local memory cache backend is available
*
* @return bool
*/
- public function isAvailableLowLatency(): bool {
+ public function isLocalCacheAvailable(): bool {
return ($this->localCacheClass !== self::NULL_CACHE);
}
}
diff --git a/lib/private/NaturalSort.php b/lib/private/NaturalSort.php
index 636e5cd0219..470e720c54c 100644
--- a/lib/private/NaturalSort.php
+++ b/lib/private/NaturalSort.php
@@ -27,6 +27,8 @@
namespace OC;
+use OCP\ILogger;
+
class NaturalSort {
private static $instance;
private $collator;
@@ -41,7 +43,7 @@ class NaturalSort {
// or inject an instance of \OC\NaturalSort_DefaultCollator to force using Owncloud's default collator
if (isset($injectedCollator)) {
$this->collator = $injectedCollator;
- \OCP\Util::writeLog('core', 'forced use of '.get_class($injectedCollator), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', 'forced use of '.get_class($injectedCollator), ILogger::DEBUG);
}
}
diff --git a/lib/private/NavigationManager.php b/lib/private/NavigationManager.php
index 31d147a3b80..1874cd0e4ff 100644
--- a/lib/private/NavigationManager.php
+++ b/lib/private/NavigationManager.php
@@ -100,30 +100,65 @@ class NavigationManager implements INavigationManager {
if(!isset($entry['type'])) {
$entry['type'] = 'link';
}
- $this->entries[] = $entry;
+ $this->entries[$entry['id']] = $entry;
}
/**
- * returns all the added Menu entries
- * @param string $type
- * @return array an array of the added entries
+ * Get a list of navigation entries
+ *
+ * @param string $type type of the navigation entries
+ * @return array
*/
- public function getAll($type = 'link') {
+ public function getAll(string $type = 'link'): array {
$this->init();
foreach ($this->closureEntries as $c) {
$this->add($c());
}
$this->closureEntries = array();
- if ($type === 'all') {
- return $this->entries;
+ $result = $this->entries;
+ if ($type !== 'all') {
+ $result = array_filter($this->entries, function($entry) use ($type) {
+ return $entry['type'] === $type;
+ });
}
- return array_filter($this->entries, function($entry) use ($type) {
- return $entry['type'] === $type;
+ return $this->proceedNavigation($result);
+ }
+
+ /**
+ * Sort navigation entries by order, name and set active flag
+ *
+ * @param array $list
+ * @return array
+ */
+ private function proceedNavigation(array $list): array {
+ uasort($list, function($a, $b) {
+ if (isset($a['order']) && isset($b['order'])) {
+ return ($a['order'] < $b['order']) ? -1 : 1;
+ } else if (isset($a['order']) || isset($b['order'])) {
+ return isset($a['order']) ? -1 : 1;
+ } else {
+ return ($a['name'] < $b['name']) ? -1 : 1;
+ }
});
+
+ $activeApp = $this->getActiveEntry();
+ if ($activeApp !== null) {
+ foreach ($list as $index => &$navEntry) {
+ if ($navEntry['id'] == $activeApp) {
+ $navEntry['active'] = true;
+ } else {
+ $navEntry['active'] = false;
+ }
+ }
+ unset($navEntry);
+ }
+
+ return $list;
}
+
/**
* removes all the entries
*/
@@ -212,7 +247,7 @@ class NavigationManager implements INavigationManager {
'type' => 'settings',
'id' => 'core_users',
'order' => 4,
- 'href' => $this->urlGenerator->linkToRoute('settings_users'),
+ 'href' => $this->urlGenerator->linkToRoute('settings.Users.usersList'),
'name' => $l->t('Users'),
'icon' => $this->urlGenerator->imagePath('settings', 'users.svg'),
]);
@@ -254,7 +289,7 @@ class NavigationManager implements INavigationManager {
$id = isset($nav['id']) ? $nav['id'] : $app;
$order = isset($nav['order']) ? $nav['order'] : 100;
$type = isset($nav['type']) ? $nav['type'] : 'link';
- $route = $this->urlGenerator->linkToRoute($nav['route']);
+ $route = $nav['route'] !== '' ? $this->urlGenerator->linkToRoute($nav['route']) : '';
$icon = isset($nav['icon']) ? $nav['icon'] : 'app.svg';
foreach ([$icon, "$app.svg"] as $i) {
try {
diff --git a/lib/private/OCS/DiscoveryService.php b/lib/private/OCS/DiscoveryService.php
index 016331e908f..6662263fb76 100644
--- a/lib/private/OCS/DiscoveryService.php
+++ b/lib/private/OCS/DiscoveryService.php
@@ -59,15 +59,18 @@ class DiscoveryService implements IDiscoveryService {
*
* @param string $remote
* @param string $service the service you want to discover
+ * @param bool $skipCache We won't check if the data is in the cache. This is usefull if a background job is updating the status
* @return array
*/
- public function discover(string $remote, string $service): array {
+ public function discover(string $remote, string $service, bool $skipCache = false): array {
// Check the cache first
- $cacheData = $this->cache->get($remote . '#' . $service);
- if($cacheData) {
- $data = json_decode($cacheData, true);
- if (\is_array($data)) {
- return $data;
+ if ($skipCache === false) {
+ $cacheData = $this->cache->get($remote . '#' . $service);
+ if ($cacheData) {
+ $data = json_decode($cacheData, true);
+ if (\is_array($data)) {
+ return $data;
+ }
}
}
diff --git a/lib/private/Preview/BackgroundCleanupJob.php b/lib/private/Preview/BackgroundCleanupJob.php
new file mode 100644
index 00000000000..25bf354e28b
--- /dev/null
+++ b/lib/private/Preview/BackgroundCleanupJob.php
@@ -0,0 +1,91 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @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\Preview;
+
+use OC\BackgroundJob\TimedJob;
+use OC\Files\AppData\Factory;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+use OCP\IDBConnection;
+
+class BackgroundCleanupJob extends TimedJob {
+
+ /** @var IDBConnection */
+ private $connection;
+
+ /** @var Factory */
+ private $appDataFactory;
+
+ /** @var bool */
+ private $isCLI;
+
+ public function __construct(IDBConnection $connection,
+ Factory $appDataFactory,
+ bool $isCLI) {
+ // Run at most once an hour
+ $this->setInterval(3600);
+
+ $this->connection = $connection;
+ $this->appDataFactory = $appDataFactory;
+ $this->isCLI = $isCLI;
+ }
+
+ public function run($argument) {
+ $previews = $this->appDataFactory->get('preview');
+
+ $previewFodlerId = $previews->getId();
+
+ $qb = $this->connection->getQueryBuilder();
+ $qb->select('a.name')
+ ->from('filecache', 'a')
+ ->leftJoin('a', 'filecache', 'b', $qb->expr()->eq(
+ $qb->expr()->castColumn('a.name', IQueryBuilder::PARAM_INT), 'b.fileid'
+ ))
+ ->where(
+ $qb->expr()->isNull('b.fileid')
+ )->andWhere(
+ $qb->expr()->eq('a.parent', $qb->createNamedParameter($previewFodlerId))
+ );
+
+ if (!$this->isCLI) {
+ $qb->setMaxResults(10);
+ }
+
+ $cursor = $qb->execute();
+
+ while ($row = $cursor->fetch()) {
+ try {
+ $preview = $previews->getFolder($row['name']);
+ $preview->delete();
+ } catch (NotFoundException $e) {
+ // continue
+ } catch (NotPermittedException $e) {
+ // continue
+ }
+ }
+
+ $cursor->closeCursor();
+ }
+}
diff --git a/lib/private/Preview/Bitmap.php b/lib/private/Preview/Bitmap.php
index ff6093fcf81..1fd42a0ea97 100644
--- a/lib/private/Preview/Bitmap.php
+++ b/lib/private/Preview/Bitmap.php
@@ -26,6 +26,7 @@
namespace OC\Preview;
use Imagick;
+use OCP\ILogger;
/**
* Creates a PNG preview using ImageMagick via the PECL extension
@@ -49,8 +50,8 @@ abstract class Bitmap extends Provider {
$bp = $this->getResizedPreview($tmpPath, $maxX, $maxY);
} catch (\Exception $e) {
\OC::$server->getLogger()->logException($e, [
- 'message' => 'Imagick says:',
- 'level' => \OCP\Util::ERROR,
+ 'message' => 'File: ' . $fileview->getAbsolutePath($path) . ' Imagick says:',
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return false;
diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php
index 08f6b604eca..3e81004c8aa 100644
--- a/lib/private/Preview/Generator.php
+++ b/lib/private/Preview/Generator.php
@@ -89,6 +89,12 @@ class Generator {
* @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid)
*/
public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) {
+ //Make sure that we can read the file
+ if (!$file->isReadable()) {
+ throw new NotFoundException('Cannot read file');
+ }
+
+
$this->eventDispatcher->dispatch(
IPreview::EVENT,
new GenericEvent($file,[
diff --git a/lib/private/Preview/Office.php b/lib/private/Preview/Office.php
index 6403cf5dd8d..4a2aa7f4953 100644
--- a/lib/private/Preview/Office.php
+++ b/lib/private/Preview/Office.php
@@ -25,6 +25,8 @@
*/
namespace OC\Preview;
+use OCP\ILogger;
+
abstract class Office extends Provider {
private $cmd;
@@ -41,36 +43,36 @@ abstract class Office extends Provider {
$tmpDir = \OC::$server->getTempManager()->getTempBaseDir();
- $defaultParameters = ' -env:UserInstallation=file://' . escapeshellarg($tmpDir . '/owncloud-' . \OC_Util::getInstanceId() . '/') . ' --headless --nologo --nofirststartwizard --invisible --norestore --convert-to pdf --outdir ';
+ $defaultParameters = ' -env:UserInstallation=file://' . escapeshellarg($tmpDir . '/owncloud-' . \OC_Util::getInstanceId() . '/') . ' --headless --nologo --nofirststartwizard --invisible --norestore --convert-to png --outdir ';
$clParameters = \OC::$server->getConfig()->getSystemValue('preview_office_cl_parameters', $defaultParameters);
$exec = $this->cmd . $clParameters . escapeshellarg($tmpDir) . ' ' . escapeshellarg($absPath);
shell_exec($exec);
- //create imagick object from pdf
- $pdfPreview = null;
+ //create imagick object from png
+ $pngPreview = null;
try {
list($dirname, , , $filename) = array_values(pathinfo($absPath));
- $pdfPreview = $dirname . '/' . $filename . '.pdf';
+ $pngPreview = $dirname . '/' . $filename . '.png';
- $pdf = new \imagick($pdfPreview . '[0]');
- $pdf->setImageFormat('jpg');
+ $png = new \imagick($pngPreview . '[0]');
+ $png->setImageFormat('jpg');
} catch (\Exception $e) {
unlink($absPath);
- unlink($pdfPreview);
+ unlink($pngPreview);
\OC::$server->getLogger()->logException($e, [
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return false;
}
$image = new \OC_Image();
- $image->loadFromData($pdf);
+ $image->loadFromData($png);
unlink($absPath);
- unlink($pdfPreview);
+ unlink($pngPreview);
if ($image->valid()) {
$image->scaleDownToFit($maxX, $maxY);
diff --git a/lib/private/Preview/SVG.php b/lib/private/Preview/SVG.php
index e0abf04d931..e283175c2e2 100644
--- a/lib/private/Preview/SVG.php
+++ b/lib/private/Preview/SVG.php
@@ -24,6 +24,8 @@
*/
namespace OC\Preview;
+use OCP\ILogger;
+
class SVG extends Provider {
/**
* {@inheritDoc}
@@ -54,7 +56,7 @@ class SVG extends Provider {
$svg->setImageFormat('png32');
} catch (\Exception $e) {
\OC::$server->getLogger()->logException($e, [
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return false;
diff --git a/lib/private/Preview/Watcher.php b/lib/private/Preview/Watcher.php
index 8d091b84b0e..0c0531dff94 100644
--- a/lib/private/Preview/Watcher.php
+++ b/lib/private/Preview/Watcher.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
*
@@ -22,7 +23,6 @@
*/
namespace OC\Preview;
-use OCP\Files\File;
use OCP\Files\Node;
use OCP\Files\Folder;
use OCP\Files\IAppData;
@@ -39,9 +39,6 @@ class Watcher {
/** @var IAppData */
private $appData;
- /** @var int[] */
- private $toDelete = [];
-
/**
* Watcher constructor.
*
@@ -52,53 +49,26 @@ class Watcher {
}
public function postWrite(Node $node) {
+ $this->deleteNode($node);
+ }
+
+ protected function deleteNode(Node $node) {
// We only handle files
if ($node instanceof Folder) {
return;
}
try {
- $folder = $this->appData->getFolder($node->getId());
+ $folder = $this->appData->getFolder((string)$node->getId());
$folder->delete();
} catch (NotFoundException $e) {
//Nothing to do
}
}
- public function preDelete(Node $node) {
- // To avoid cycles
- if ($this->toDelete !== []) {
- return;
- }
-
- if ($node instanceof File) {
- $this->toDelete[] = $node->getId();
- return;
- }
-
- /** @var Folder $node */
- $this->deleteFolder($node);
- }
-
- private function deleteFolder(Folder $folder) {
- $nodes = $folder->getDirectoryListing();
- foreach ($nodes as $node) {
- if ($node instanceof File) {
- $this->toDelete[] = $node->getId();
- } else if ($node instanceof Folder) {
- $this->deleteFolder($node);
- }
- }
- }
-
- public function postDelete(Node $node) {
- foreach ($this->toDelete as $fid) {
- try {
- $folder = $this->appData->getFolder($fid);
- $folder->delete();
- } catch (NotFoundException $e) {
- // continue
- }
+ public function versionRollback(array $data) {
+ if (isset($data['node'])) {
+ $this->deleteNode($data['node']);
}
}
}
diff --git a/lib/private/Preview/WatcherConnector.php b/lib/private/Preview/WatcherConnector.php
index 4e6e786cec7..f374b909d8f 100644
--- a/lib/private/Preview/WatcherConnector.php
+++ b/lib/private/Preview/WatcherConnector.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
*
@@ -49,7 +50,7 @@ class WatcherConnector {
/**
* @return Watcher
*/
- private function getWatcher() {
+ private function getWatcher(): Watcher {
return \OC::$server->query(Watcher::class);
}
@@ -60,13 +61,7 @@ class WatcherConnector {
$this->getWatcher()->postWrite($node);
});
- $this->root->listen('\OC\Files', 'preDelete', function (Node $node) {
- $this->getWatcher()->preDelete($node);
- });
-
- $this->root->listen('\OC\Files', 'postDelete', function (Node $node) {
- $this->getWatcher()->postDelete($node);
- });
+ \OC_Hook::connect('\OCP\Versions', 'rollback', $this->getWatcher(), 'versionRollback');
}
}
}
diff --git a/lib/private/Repair.php b/lib/private/Repair.php
index d787a1c802b..ad9662ca1d7 100644
--- a/lib/private/Repair.php
+++ b/lib/private/Repair.php
@@ -30,14 +30,15 @@
namespace OC;
-use OC\App\AppStore\Bundles\BundleFetcher;
-use OC\Files\AppData\Factory;
+use OC\Repair\AddCleanupUpdaterBackupsJob;
use OC\Repair\CleanTags;
use OC\Repair\ClearFrontendCaches;
use OC\Repair\Collation;
use OC\Repair\MoveUpdaterStepFile;
use OC\Repair\NC11\FixMountStorages;
use OC\Repair\NC13\AddLogRotateJob;
+use OC\Repair\NC14\AddPreviewBackgroundCleanupJob;
+use OC\Repair\NC14\RepairPendingCronJobs;
use OC\Repair\OldGroupMembershipShares;
use OC\Repair\Owncloud\DropAccountTermsTable;
use OC\Repair\Owncloud\SaveAccountsTableData;
@@ -134,7 +135,10 @@ class Repair implements IOutput{
new FixMountStorages(\OC::$server->getDatabaseConnection()),
new RepairInvalidPaths(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()),
new AddLogRotateJob(\OC::$server->getJobList()),
- new ClearFrontendCaches(\OC::$server->getMemCacheFactory(), \OC::$server->query(SCSSCacher::class), \OC::$server->query(JSCombiner::class))
+ new ClearFrontendCaches(\OC::$server->getMemCacheFactory(), \OC::$server->query(SCSSCacher::class), \OC::$server->query(JSCombiner::class)),
+ new AddPreviewBackgroundCleanupJob(\OC::$server->getJobList()),
+ new AddCleanupUpdaterBackupsJob(\OC::$server->getJobList()),
+ new RepairPendingCronJobs(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()),
];
}
@@ -146,7 +150,7 @@ class Repair implements IOutput{
*/
public static function getExpensiveRepairSteps() {
return [
- new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager())
+ new OldGroupMembershipShares(\OC::$server->getDatabaseConnection(), \OC::$server->getGroupManager()),
];
}
diff --git a/lib/private/Repair/AddCleanupUpdaterBackupsJob.php b/lib/private/Repair/AddCleanupUpdaterBackupsJob.php
new file mode 100644
index 00000000000..1574e665fb6
--- /dev/null
+++ b/lib/private/Repair/AddCleanupUpdaterBackupsJob.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Morris Jobke <hey@morrisjobke.de>
+ *
+ * @author Morris Jobke <hey@morrisjobke.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\Repair;
+
+use OC\Core\BackgroundJobs\BackgroundCleanupUpdaterBackupsJob;
+use OCP\BackgroundJob\IJobList;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+
+class AddCleanupUpdaterBackupsJob implements IRepairStep {
+
+ /** @var IJobList */
+ protected $jobList;
+
+ public function __construct(IJobList $jobList) {
+ $this->jobList = $jobList;
+ }
+
+ public function getName() {
+ return 'Queue a one-time job to cleanup old backups of the updater';
+ }
+
+ public function run(IOutput $output) {
+ $this->jobList->add(BackgroundCleanupUpdaterBackupsJob::class);
+ }
+}
+
diff --git a/lib/private/Repair/Collation.php b/lib/private/Repair/Collation.php
index 2642985371b..f2cc9373176 100644
--- a/lib/private/Repair/Collation.php
+++ b/lib/private/Repair/Collation.php
@@ -6,6 +6,7 @@
* @author Morris Jobke <hey@morrisjobke.de>
* @author Robin Appelman <robin@icewind.nl>
* @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author Robin Müller <robin.mueller@1und1.de>
*
* @license AGPL-3.0
*
@@ -124,7 +125,7 @@ class Collation implements IRepairStep {
" FROM INFORMATION_SCHEMA . COLUMNS" .
" WHERE TABLE_SCHEMA = ?" .
" AND (COLLATION_NAME <> '" . $characterSet . "_bin' OR CHARACTER_SET_NAME <> '" . $characterSet . "')" .
- " AND TABLE_NAME LIKE \"*PREFIX*%\"",
+ " AND TABLE_NAME LIKE '*PREFIX*%'",
array($dbName)
);
$rows = $statement->fetchAll();
@@ -139,7 +140,7 @@ class Collation implements IRepairStep {
" FROM INFORMATION_SCHEMA . TABLES" .
" WHERE TABLE_SCHEMA = ?" .
" AND TABLE_COLLATION <> '" . $characterSet . "_bin'" .
- " AND TABLE_NAME LIKE \"*PREFIX*%\"",
+ " AND TABLE_NAME LIKE '*PREFIX*%'",
[$dbName]
);
$rows = $statement->fetchAll();
diff --git a/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php b/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php
new file mode 100644
index 00000000000..b58fabcba50
--- /dev/null
+++ b/lib/private/Repair/NC14/AddPreviewBackgroundCleanupJob.php
@@ -0,0 +1,48 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright 2018, 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\Repair\NC14;
+
+use OC\Preview\BackgroundCleanupJob;
+use OCP\BackgroundJob\IJobList;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+
+class AddPreviewBackgroundCleanupJob implements IRepairStep {
+
+ /** @var IJobList */
+ private $jobList;
+
+ public function __construct(IJobList $jobList) {
+ $this->jobList = $jobList;
+ }
+
+ public function getName(): string {
+ return 'Add preview background cleanup job';
+ }
+
+ public function run(IOutput $output) {
+ $this->jobList->add(BackgroundCleanupJob::class);
+ }
+
+}
diff --git a/lib/private/Repair/NC14/RepairPendingCronJobs.php b/lib/private/Repair/NC14/RepairPendingCronJobs.php
new file mode 100644
index 00000000000..a8ca2c75e89
--- /dev/null
+++ b/lib/private/Repair/NC14/RepairPendingCronJobs.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Morris Jobke <hey@morrisjobke.de>
+ *
+ * @author Morris Jobke <hey@morrisjobke.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\Repair\NC14;
+
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\Migration\IOutput;
+use OCP\Migration\IRepairStep;
+
+class RepairPendingCronJobs implements IRepairStep {
+ const MAX_ROWS = 1000;
+
+ /** @var IDBConnection */
+ private $connection;
+ /** @var IConfig */
+ private $config;
+
+ public function __construct(IDBConnection $connection, IConfig $config) {
+ $this->connection = $connection;
+ $this->config = $config;
+ }
+
+
+ public function getName() {
+ return 'Repair pending cron jobs';
+ }
+
+ private function shouldRun() {
+ $versionFromBeforeUpdate = $this->config->getSystemValue('version', '0.0.0');
+
+ return version_compare($versionFromBeforeUpdate, '14.0.0.9', '<');
+ }
+
+ /**
+ * @suppress SqlInjectionChecker
+ */
+ private function repair() {
+ $reset = $this->connection->getQueryBuilder();
+ $reset->update('jobs')
+ ->set('reserved_at', $reset->expr()->literal(0, IQueryBuilder::PARAM_INT))
+ ->where($reset->expr()->neq('reserved_at', $reset->expr()->literal(0, IQueryBuilder::PARAM_INT)));
+
+ return $reset->execute();
+ }
+
+ public function run(IOutput $output) {
+ if ($this->shouldRun()) {
+ $count = $this->repair();
+
+ $output->info('Repaired ' . $count . ' pending cron job(s).');
+ } else {
+ $output->info('No need to repair pending cron jobs.');
+ }
+ }
+}
diff --git a/lib/private/Repair/RepairMimeTypes.php b/lib/private/Repair/RepairMimeTypes.php
index 2b259175623..9df11231e7a 100644
--- a/lib/private/Repair/RepairMimeTypes.php
+++ b/lib/private/Repair/RepairMimeTypes.php
@@ -162,6 +162,32 @@ class RepairMimeTypes implements IRepairStep {
return $this->updateMimetypes($updatedMimetypes);
}
+ private function introduceVisioTypes() {
+ $updatedMimetypes = [
+ 'vsdm' => 'application/vnd.visio',
+ 'vsdx' => 'application/vnd.visio',
+ 'vssm' => 'application/vnd.visio',
+ 'vssx' => 'application/vnd.visio',
+ 'vstm' => 'application/vnd.visio',
+ 'vstx' => 'application/vnd.visio',
+ ];
+
+ return $this->updateMimetypes($updatedMimetypes);
+ }
+
+ private function introduceComicbookTypes() {
+ $updatedMimetypes = [
+ 'cb7' => 'application/comicbook+7z',
+ 'cba' => 'application/comicbook+ace',
+ 'cbr' => 'application/comicbook+rar',
+ 'cbt' => 'application/comicbook+tar',
+ 'cbtc' => 'application/comicbook+truecrypt',
+ 'cbz' => 'application/comicbook+zip',
+ ];
+
+ return $this->updateMimetypes($updatedMimetypes);
+ }
+
/**
* Fix mime types
*/
@@ -191,5 +217,13 @@ class RepairMimeTypes implements IRepairStep {
if (version_compare($ocVersionFromBeforeUpdate, '13.0.0.6', '<') && $this->introduceStreamingTypes()) {
$out->info('Fixed streaming mime types');
}
+
+ if (version_compare($ocVersionFromBeforeUpdate, '14.0.0.8', '<') && $this->introduceVisioTypes()) {
+ $out->info('Fixed visio mime types');
+ }
+
+ if (version_compare($ocVersionFromBeforeUpdate, '14.0.0.10', '<') && $this->introduceComicbookTypes()) {
+ $out->info('Fixed comicbook mime types');
+ }
}
}
diff --git a/lib/private/Security/Bruteforce/Throttler.php b/lib/private/Security/Bruteforce/Throttler.php
index f08b721d143..3282121d967 100644
--- a/lib/private/Security/Bruteforce/Throttler.php
+++ b/lib/private/Security/Bruteforce/Throttler.php
@@ -228,7 +228,7 @@ class Throttler {
return 0;
}
- $maxDelay = 30;
+ $maxDelay = 25;
$firstDelay = 0.1;
if ($attempts > (8 * PHP_INT_SIZE - 1)) {
// Don't ever overflow. Just assume the maxDelay time:s
diff --git a/lib/private/Security/CSP/ContentSecurityPolicy.php b/lib/private/Security/CSP/ContentSecurityPolicy.php
index 2adc3d3d12c..77e20dedf44 100644
--- a/lib/private/Security/CSP/ContentSecurityPolicy.php
+++ b/lib/private/Security/CSP/ContentSecurityPolicy.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -33,147 +34,147 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy
/**
* @return boolean
*/
- public function isInlineScriptAllowed() {
+ public function isInlineScriptAllowed(): bool {
return $this->inlineScriptAllowed;
}
/**
* @param boolean $inlineScriptAllowed
*/
- public function setInlineScriptAllowed($inlineScriptAllowed) {
+ public function setInlineScriptAllowed(bool $inlineScriptAllowed) {
$this->inlineScriptAllowed = $inlineScriptAllowed;
}
/**
* @return boolean
*/
- public function isEvalScriptAllowed() {
+ public function isEvalScriptAllowed(): bool {
return $this->evalScriptAllowed;
}
/**
* @param boolean $evalScriptAllowed
*/
- public function setEvalScriptAllowed($evalScriptAllowed) {
+ public function setEvalScriptAllowed(bool $evalScriptAllowed) {
$this->evalScriptAllowed = $evalScriptAllowed;
}
/**
* @return array
*/
- public function getAllowedScriptDomains() {
+ public function getAllowedScriptDomains(): array {
return $this->allowedScriptDomains;
}
/**
* @param array $allowedScriptDomains
*/
- public function setAllowedScriptDomains($allowedScriptDomains) {
+ public function setAllowedScriptDomains(array $allowedScriptDomains) {
$this->allowedScriptDomains = $allowedScriptDomains;
}
/**
* @return boolean
*/
- public function isInlineStyleAllowed() {
+ public function isInlineStyleAllowed(): bool {
return $this->inlineStyleAllowed;
}
/**
* @param boolean $inlineStyleAllowed
*/
- public function setInlineStyleAllowed($inlineStyleAllowed) {
+ public function setInlineStyleAllowed(bool $inlineStyleAllowed) {
$this->inlineStyleAllowed = $inlineStyleAllowed;
}
/**
* @return array
*/
- public function getAllowedStyleDomains() {
+ public function getAllowedStyleDomains(): array {
return $this->allowedStyleDomains;
}
/**
* @param array $allowedStyleDomains
*/
- public function setAllowedStyleDomains($allowedStyleDomains) {
+ public function setAllowedStyleDomains(array $allowedStyleDomains) {
$this->allowedStyleDomains = $allowedStyleDomains;
}
/**
* @return array
*/
- public function getAllowedImageDomains() {
+ public function getAllowedImageDomains(): array {
return $this->allowedImageDomains;
}
/**
* @param array $allowedImageDomains
*/
- public function setAllowedImageDomains($allowedImageDomains) {
+ public function setAllowedImageDomains(array $allowedImageDomains) {
$this->allowedImageDomains = $allowedImageDomains;
}
/**
* @return array
*/
- public function getAllowedConnectDomains() {
+ public function getAllowedConnectDomains(): array {
return $this->allowedConnectDomains;
}
/**
* @param array $allowedConnectDomains
*/
- public function setAllowedConnectDomains($allowedConnectDomains) {
+ public function setAllowedConnectDomains(array $allowedConnectDomains) {
$this->allowedConnectDomains = $allowedConnectDomains;
}
/**
* @return array
*/
- public function getAllowedMediaDomains() {
+ public function getAllowedMediaDomains(): array {
return $this->allowedMediaDomains;
}
/**
* @param array $allowedMediaDomains
*/
- public function setAllowedMediaDomains($allowedMediaDomains) {
+ public function setAllowedMediaDomains(array $allowedMediaDomains) {
$this->allowedMediaDomains = $allowedMediaDomains;
}
/**
* @return array
*/
- public function getAllowedObjectDomains() {
+ public function getAllowedObjectDomains(): array {
return $this->allowedObjectDomains;
}
/**
* @param array $allowedObjectDomains
*/
- public function setAllowedObjectDomains($allowedObjectDomains) {
+ public function setAllowedObjectDomains(array $allowedObjectDomains) {
$this->allowedObjectDomains = $allowedObjectDomains;
}
/**
* @return array
*/
- public function getAllowedFrameDomains() {
+ public function getAllowedFrameDomains(): array {
return $this->allowedFrameDomains;
}
/**
* @param array $allowedFrameDomains
*/
- public function setAllowedFrameDomains($allowedFrameDomains) {
+ public function setAllowedFrameDomains(array $allowedFrameDomains) {
$this->allowedFrameDomains = $allowedFrameDomains;
}
/**
* @return array
*/
- public function getAllowedFontDomains() {
+ public function getAllowedFontDomains(): array {
return $this->allowedFontDomains;
}
@@ -187,7 +188,7 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy
/**
* @return array
*/
- public function getAllowedChildSrcDomains() {
+ public function getAllowedChildSrcDomains(): array {
return $this->allowedChildSrcDomains;
}
@@ -201,7 +202,7 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy
/**
* @return array
*/
- public function getAllowedFrameAncestors() {
+ public function getAllowedFrameAncestors(): array {
return $this->allowedFrameAncestors;
}
diff --git a/lib/private/Security/CSP/ContentSecurityPolicyManager.php b/lib/private/Security/CSP/ContentSecurityPolicyManager.php
index 0e6f0ac6152..27a0524d3f3 100644
--- a/lib/private/Security/CSP/ContentSecurityPolicyManager.php
+++ b/lib/private/Security/CSP/ContentSecurityPolicyManager.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -41,7 +42,7 @@ class ContentSecurityPolicyManager implements IContentSecurityPolicyManager {
*
* @return ContentSecurityPolicy
*/
- public function getDefaultPolicy() {
+ public function getDefaultPolicy(): ContentSecurityPolicy {
$defaultPolicy = new \OC\Security\CSP\ContentSecurityPolicy();
foreach($this->policies as $policy) {
$defaultPolicy = $this->mergePolicies($defaultPolicy, $policy);
@@ -57,14 +58,14 @@ class ContentSecurityPolicyManager implements IContentSecurityPolicyManager {
* @return ContentSecurityPolicy
*/
public function mergePolicies(ContentSecurityPolicy $defaultPolicy,
- EmptyContentSecurityPolicy $originalPolicy) {
+ EmptyContentSecurityPolicy $originalPolicy): ContentSecurityPolicy {
foreach((object)(array)$originalPolicy as $name => $value) {
$setter = 'set'.ucfirst($name);
- if(is_array($value)) {
+ if(\is_array($value)) {
$getter = 'get'.ucfirst($name);
- $currentValues = is_array($defaultPolicy->$getter()) ? $defaultPolicy->$getter() : [];
+ $currentValues = \is_array($defaultPolicy->$getter()) ? $defaultPolicy->$getter() : [];
$defaultPolicy->$setter(array_values(array_unique(array_merge($currentValues, $value))));
- } elseif (is_bool($value)) {
+ } elseif (\is_bool($value)) {
$defaultPolicy->$setter($value);
}
}
diff --git a/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php b/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php
index 266e5809c24..088fb2d859d 100644
--- a/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php
+++ b/lib/private/Security/CSP/ContentSecurityPolicyNonceManager.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
*
@@ -55,7 +56,7 @@ class ContentSecurityPolicyNonceManager {
*
* @return string
*/
- public function getNonce() {
+ public function getNonce(): string {
if($this->nonce === '') {
$this->nonce = base64_encode($this->csrfTokenManager->getToken()->getEncryptedValue());
}
@@ -68,7 +69,7 @@ class ContentSecurityPolicyNonceManager {
*
* @return bool
*/
- public function browserSupportsCspV3() {
+ public function browserSupportsCspV3(): bool {
$browserWhitelist = [
Request::USER_AGENT_CHROME,
// Firefox 45+
diff --git a/lib/private/Security/CSRF/CsrfToken.php b/lib/private/Security/CSRF/CsrfToken.php
index d9e27ff80e3..643e58e1d53 100644
--- a/lib/private/Security/CSRF/CsrfToken.php
+++ b/lib/private/Security/CSRF/CsrfToken.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -40,7 +41,7 @@ class CsrfToken {
/**
* @param string $value Value of the token. Can be encrypted or not encrypted.
*/
- public function __construct($value) {
+ public function __construct(string $value) {
$this->value = $value;
}
@@ -50,9 +51,9 @@ class CsrfToken {
*
* @return string
*/
- public function getEncryptedValue() {
+ public function getEncryptedValue(): string {
if($this->encryptedValue === '') {
- $sharedSecret = random_bytes(strlen($this->value));
+ $sharedSecret = random_bytes(\strlen($this->value));
$this->encryptedValue = base64_encode($this->value ^ $sharedSecret) . ':' . base64_encode($sharedSecret);
}
@@ -65,9 +66,9 @@ class CsrfToken {
*
* @return string
*/
- public function getDecryptedValue() {
+ public function getDecryptedValue(): string {
$token = explode(':', $this->value);
- if (count($token) !== 2) {
+ if (\count($token) !== 2) {
return '';
}
$obfuscatedToken = $token[0];
diff --git a/lib/private/Security/CSRF/CsrfTokenGenerator.php b/lib/private/Security/CSRF/CsrfTokenGenerator.php
index 85207956e1a..be628ea176c 100644
--- a/lib/private/Security/CSRF/CsrfTokenGenerator.php
+++ b/lib/private/Security/CSRF/CsrfTokenGenerator.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -47,7 +48,7 @@ class CsrfTokenGenerator {
* @param int $length Length of the token in characters.
* @return string
*/
- public function generateToken($length = 32) {
+ public function generateToken(int $length = 32): string {
return $this->random->generate($length);
}
}
diff --git a/lib/private/Security/CSRF/CsrfTokenManager.php b/lib/private/Security/CSRF/CsrfTokenManager.php
index b43ca3d3679..deacd1f512c 100644
--- a/lib/private/Security/CSRF/CsrfTokenManager.php
+++ b/lib/private/Security/CSRF/CsrfTokenManager.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -52,8 +53,8 @@ class CsrfTokenManager {
*
* @return CsrfToken
*/
- public function getToken() {
- if(!is_null($this->csrfToken)) {
+ public function getToken(): CsrfToken {
+ if(!\is_null($this->csrfToken)) {
return $this->csrfToken;
}
@@ -73,7 +74,7 @@ class CsrfTokenManager {
*
* @return CsrfToken
*/
- public function refreshToken() {
+ public function refreshToken(): CsrfToken {
$value = $this->tokenGenerator->generateToken();
$this->sessionStorage->setToken($value);
$this->csrfToken = new CsrfToken($value);
@@ -94,7 +95,7 @@ class CsrfTokenManager {
* @param CsrfToken $token
* @return bool
*/
- public function isTokenValid(CsrfToken $token) {
+ public function isTokenValid(CsrfToken $token): bool {
if(!$this->sessionStorage->hasToken()) {
return false;
}
diff --git a/lib/private/Security/CSRF/TokenStorage/SessionStorage.php b/lib/private/Security/CSRF/TokenStorage/SessionStorage.php
index 946330b0c8c..b35e148c7ce 100644
--- a/lib/private/Security/CSRF/TokenStorage/SessionStorage.php
+++ b/lib/private/Security/CSRF/TokenStorage/SessionStorage.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -54,7 +55,7 @@ class SessionStorage {
* @return string
* @throws \Exception
*/
- public function getToken() {
+ public function getToken(): string {
$token = $this->session->get('requesttoken');
if(empty($token)) {
throw new \Exception('Session does not contain a requesttoken');
@@ -68,7 +69,7 @@ class SessionStorage {
*
* @param string $value
*/
- public function setToken($value) {
+ public function setToken(string $value) {
$this->session->set('requesttoken', $value);
}
@@ -83,7 +84,7 @@ class SessionStorage {
*
* @return bool
*/
- public function hasToken() {
+ public function hasToken(): bool {
return $this->session->exists('requesttoken');
}
}
diff --git a/lib/private/Security/Hasher.php b/lib/private/Security/Hasher.php
index c6c9109b336..e20de729f4f 100644
--- a/lib/private/Security/Hasher.php
+++ b/lib/private/Security/Hasher.php
@@ -51,11 +51,9 @@ class Hasher implements IHasher {
/** @var IConfig */
private $config;
/** @var array Options passed to password_hash and password_needs_rehash */
- private $options = array();
+ private $options = [];
/** @var string Salt used for legacy passwords */
private $legacySalt = null;
- /** @var int Current version of the generated hash */
- private $currentVersion = 1;
/**
* @param IConfig $config
@@ -78,7 +76,11 @@ class Hasher implements IHasher {
* @return string Hash of the message with appended version parameter
*/
public function hash(string $message): string {
- return $this->currentVersion . '|' . password_hash($message, PASSWORD_DEFAULT, $this->options);
+ if (\defined('PASSWORD_ARGON2I')) {
+ return 2 . '|' . password_hash($message, PASSWORD_ARGON2I, $this->options);
+ } else {
+ return 1 . '|' . password_hash($message, PASSWORD_BCRYPT, $this->options);
+ }
}
/**
@@ -90,7 +92,7 @@ class Hasher implements IHasher {
$explodedString = explode('|', $prefixedHash, 2);
if(\count($explodedString) === 2) {
if((int)$explodedString[0] > 0) {
- return array('version' => (int)$explodedString[0], 'hash' => $explodedString[1]);
+ return ['version' => (int)$explodedString[0], 'hash' => $explodedString[1]];
}
}
@@ -111,8 +113,8 @@ class Hasher implements IHasher {
// Verify whether it matches a legacy PHPass or SHA1 string
$hashLength = \strlen($hash);
- if($hashLength === 60 && password_verify($message.$this->legacySalt, $hash) ||
- $hashLength === 40 && hash_equals($hash, sha1($message))) {
+ if(($hashLength === 60 && password_verify($message.$this->legacySalt, $hash)) ||
+ ($hashLength === 40 && hash_equals($hash, sha1($message)))) {
$newHash = $this->hash($message);
return true;
}
@@ -121,7 +123,7 @@ class Hasher implements IHasher {
}
/**
- * Verify V1 hashes
+ * Verify V1 (blowfish) hashes
* @param string $message Message to verify
* @param string $hash Assumed hash of the message
* @param null|string &$newHash Reference will contain the updated hash if necessary. Update the existing hash with this one.
@@ -129,7 +131,30 @@ class Hasher implements IHasher {
*/
protected function verifyHashV1(string $message, string $hash, &$newHash = null): bool {
if(password_verify($message, $hash)) {
- if(password_needs_rehash($hash, PASSWORD_DEFAULT, $this->options)) {
+ $algo = PASSWORD_BCRYPT;
+ if (\defined('PASSWORD_ARGON2I')) {
+ $algo = PASSWORD_ARGON2I;
+ }
+
+ if(password_needs_rehash($hash, $algo, $this->options)) {
+ $newHash = $this->hash($message);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Verify V2 (argon2i) hashes
+ * @param string $message Message to verify
+ * @param string $hash Assumed hash of the message
+ * @param null|string &$newHash Reference will contain the updated hash if necessary. Update the existing hash with this one.
+ * @return bool Whether $hash is a valid hash of $message
+ */
+ protected function verifyHashV2(string $message, string $hash, &$newHash = null) : bool {
+ if(password_verify($message, $hash)) {
+ if(password_needs_rehash($hash, PASSWORD_ARGON2I, $this->options)) {
$newHash = $this->hash($message);
}
return true;
@@ -149,6 +174,8 @@ class Hasher implements IHasher {
if(isset($splittedHash['version'])) {
switch ($splittedHash['version']) {
+ case 2:
+ return $this->verifyHashV2($message, $splittedHash['hash'], $newHash);
case 1:
return $this->verifyHashV1($message, $splittedHash['hash'], $newHash);
}
diff --git a/lib/private/Security/IdentityProof/Key.php b/lib/private/Security/IdentityProof/Key.php
index b01a5c66bb8..4f79dee15db 100644
--- a/lib/private/Security/IdentityProof/Key.php
+++ b/lib/private/Security/IdentityProof/Key.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
*
@@ -33,16 +34,16 @@ class Key {
* @param string $publicKey
* @param string $privateKey
*/
- public function __construct($publicKey, $privateKey) {
+ public function __construct(string $publicKey, string $privateKey) {
$this->publicKey = $publicKey;
$this->privateKey = $privateKey;
}
- public function getPrivate() {
+ public function getPrivate(): string {
return $this->privateKey;
}
- public function getPublic() {
+ public function getPublic(): string {
return $this->publicKey;
}
}
diff --git a/lib/private/Security/IdentityProof/Manager.php b/lib/private/Security/IdentityProof/Manager.php
index 7bfc139b94c..fb27f04d873 100644
--- a/lib/private/Security/IdentityProof/Manager.php
+++ b/lib/private/Security/IdentityProof/Manager.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
*
@@ -59,7 +60,7 @@ class Manager {
*
* @return array [$publicKey, $privateKey]
*/
- protected function generateKeyPair() {
+ protected function generateKeyPair(): array {
$config = [
'digest_alg' => 'sha512',
'private_key_bits' => 2048,
@@ -83,7 +84,7 @@ class Manager {
* @param string $id key id
* @return Key
*/
- protected function generateKey($id) {
+ protected function generateKey(string $id): Key {
list($publicKey, $privateKey) = $this->generateKeyPair();
// Write the private and public key to the disk
@@ -105,7 +106,7 @@ class Manager {
* @param string $id
* @return Key
*/
- protected function retrieveKey($id) {
+ protected function retrieveKey(string $id): Key {
try {
$folder = $this->appData->getFolder($id);
$privateKey = $this->crypto->decrypt(
@@ -124,7 +125,7 @@ class Manager {
* @param IUser $user
* @return Key
*/
- public function getKey(IUser $user) {
+ public function getKey(IUser $user): Key {
$uid = $user->getUID();
return $this->retrieveKey('user-' . $uid);
}
@@ -135,7 +136,7 @@ class Manager {
* @return Key
* @throws \RuntimeException
*/
- public function getSystemKey() {
+ public function getSystemKey(): Key {
$instanceId = $this->config->getSystemValue('instanceid', null);
if ($instanceId === null) {
throw new \RuntimeException('no instance id!');
diff --git a/lib/private/Security/IdentityProof/Signer.php b/lib/private/Security/IdentityProof/Signer.php
index ed2a38f99b8..95546876bdc 100644
--- a/lib/private/Security/IdentityProof/Signer.php
+++ b/lib/private/Security/IdentityProof/Signer.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
*
@@ -57,7 +58,7 @@ class Signer {
* @param IUser $user
* @return array ['message', 'signature']
*/
- public function sign($type, array $data, IUser $user) {
+ public function sign(string $type, array $data, IUser $user): array {
$privateKey = $this->keyManager->getKey($user)->getPrivate();
$data = [
'data' => $data,
@@ -79,7 +80,7 @@ class Signer {
* @param array $data
* @return bool
*/
- public function verify(array $data) {
+ public function verify(array $data): bool {
if(isset($data['message'])
&& isset($data['signature'])
&& isset($data['message']['signer'])
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 228f0ab5f97..0f406ebe9b7 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -60,6 +60,7 @@ use OC\Authentication\LoginCredentials\Store;
use OC\Authentication\Token\IProvider;
use OC\Collaboration\Collaborators\GroupPlugin;
use OC\Collaboration\Collaborators\MailPlugin;
+use OC\Collaboration\Collaborators\RemoteGroupPlugin;
use OC\Collaboration\Collaborators\RemotePlugin;
use OC\Collaboration\Collaborators\UserPlugin;
use OC\Command\CronBus;
@@ -68,6 +69,8 @@ use OC\Contacts\ContactsMenu\ActionFactory;
use OC\Contacts\ContactsMenu\ContactsStore;
use OC\Diagnostics\EventLogger;
use OC\Diagnostics\QueryLogger;
+use OC\Federation\CloudFederationFactory;
+use OC\Federation\CloudFederationProviderManager;
use OC\Federation\CloudIdManager;
use OC\Files\Config\UserMountCache;
use OC\Files\Config\UserMountCacheListener;
@@ -87,6 +90,7 @@ use OC\Lock\DBLockingProvider;
use OC\Lock\MemcacheLockingProvider;
use OC\Lock\NoopLockingProvider;
use OC\Lockdown\LockdownManager;
+use OC\Log\LogFactory;
use OC\Mail\Mailer;
use OC\Memcache\ArrayCache;
use OC\Memcache\Factory;
@@ -112,8 +116,10 @@ use OC\Share20\ProviderFactory;
use OC\Share20\ShareHelper;
use OC\SystemTag\ManagerFactory as SystemTagManagerFactory;
use OC\Tagging\TagMapper;
+use OC\Template\IconsCacher;
use OC\Template\JSCombiner;
use OC\Template\SCSSCacher;
+use OCA\Theming\ImageManager;
use OCA\Theming\ThemingDefaults;
use OCP\App\IAppManager;
@@ -122,9 +128,12 @@ use OCP\Collaboration\AutoComplete\IManager;
use OCP\Contacts\ContactsMenu\IContactsStore;
use OCP\Defaults;
use OCA\Theming\Util;
+use OCP\Federation\ICloudFederationFactory;
+use OCP\Federation\ICloudFederationProviderManager;
use OCP\Federation\ICloudIdManager;
use OCP\Authentication\LoginCredentials\IStore;
use OCP\Files\NotFoundException;
+use OCP\GlobalScale\IConfig;
use OCP\ICacheFactory;
use OCP\IDBConnection;
use OCP\IL10N;
@@ -133,6 +142,7 @@ use OCP\ITempManager;
use OCP\Contacts\ContactsMenu\IActionFactory;
use OCP\IUser;
use OCP\Lock\ILockingProvider;
+use OCP\Log\ILogFactory;
use OCP\Remote\Api\IApiFactory;
use OCP\Remote\IInstanceFactory;
use OCP\RichObjectStrings\IValidator;
@@ -161,6 +171,9 @@ class Server extends ServerContainer implements IServerContainer {
parent::__construct();
$this->webRoot = $webRoot;
+ // To find out if we are running from CLI or not
+ $this->registerParameter('isCLI', \OC::$CLI);
+
$this->registerService(\OCP\IServerContainer::class, function (IServerContainer $c) {
return $c;
});
@@ -168,6 +181,12 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerAlias(\OCP\Calendar\IManager::class, \OC\Calendar\Manager::class);
$this->registerAlias('CalendarManager', \OC\Calendar\Manager::class);
+ $this->registerAlias(\OCP\Calendar\Resource\IManager::class, \OC\Calendar\Resource\Manager::class);
+ $this->registerAlias('CalendarResourceBackendManager', \OC\Calendar\Resource\Manager::class);
+
+ $this->registerAlias(\OCP\Calendar\Room\IManager::class, \OC\Calendar\Room\Manager::class);
+ $this->registerAlias('CalendarRoomBackendManager', \OC\Calendar\Room\Manager::class);
+
$this->registerAlias(\OCP\Contacts\IManager::class, \OC\ContactsManager::class);
$this->registerAlias('ContactsManager', \OCP\Contacts\IManager::class);
@@ -333,15 +352,7 @@ class Server extends ServerContainer implements IServerContainer {
$dbConnection = $c->getDatabaseConnection();
return new Authentication\Token\DefaultTokenMapper($dbConnection);
});
- $this->registerService(Authentication\Token\DefaultTokenProvider::class, function (Server $c) {
- $mapper = $c->query(Authentication\Token\DefaultTokenMapper::class);
- $crypto = $c->getCrypto();
- $config = $c->getConfig();
- $logger = $c->getLogger();
- $timeFactory = new TimeFactory();
- return new \OC\Authentication\Token\DefaultTokenProvider($mapper, $crypto, $config, $logger, $timeFactory);
- });
- $this->registerAlias(IProvider::class, Authentication\Token\DefaultTokenProvider::class);
+ $this->registerAlias(IProvider::class, Authentication\Token\Manager::class);
$this->registerService(\OCP\IUserSession::class, function (Server $c) {
$manager = $c->getUserManager();
@@ -414,18 +425,7 @@ class Server extends ServerContainer implements IServerContainer {
});
$this->registerAlias('UserSession', \OCP\IUserSession::class);
- $this->registerService(\OC\Authentication\TwoFactorAuth\Manager::class, function (Server $c) {
- return new \OC\Authentication\TwoFactorAuth\Manager(
- $c->getAppManager(),
- $c->getSession(),
- $c->getConfig(),
- $c->getActivityManager(),
- $c->getLogger(),
- $c->query(IProvider::class),
- $c->query(ITimeFactory::class),
- $c->query(EventDispatcherInterface::class)
- );
- });
+ $this->registerAlias(\OCP\Authentication\TwoFactorAuth\IRegistry::class, \OC\Authentication\TwoFactorAuth\Registry::class);
$this->registerAlias(\OCP\INavigationManager::class, \OC\NavigationManager::class);
$this->registerAlias('NavigationManager', \OCP\INavigationManager::class);
@@ -470,9 +470,6 @@ class Server extends ServerContainer implements IServerContainer {
});
$this->registerAlias('URLGenerator', \OCP\IURLGenerator::class);
- $this->registerService('AppHelper', function ($c) {
- return new \OC\AppHelper();
- });
$this->registerAlias('AppFetcher', AppFetcher::class);
$this->registerAlias('CategoryFetcher', CategoryFetcher::class);
@@ -498,7 +495,7 @@ class Server extends ServerContainer implements IServerContainer {
$version = implode(',', $v);
$instanceId = \OC_Util::getInstanceId();
$path = \OC::$SERVERROOT;
- $prefix = md5($instanceId . '-' . $version . '-' . $path . '-' . $urlGenerator->getBaseUrl());
+ $prefix = md5($instanceId . '-' . $version . '-' . $path);
return new \OC\Memcache\Factory($prefix, $c->getLogger(),
$config->getSystemValue('memcache.local', null),
$config->getSystemValue('memcache.distributed', null),
@@ -548,15 +545,18 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService(\OCP\ILogger::class, function (Server $c) {
$logType = $c->query('AllConfig')->getSystemValue('log_type', 'file');
- $logger = Log::getLogClass($logType);
- call_user_func(array($logger, 'init'));
- $config = $this->getSystemConfig();
+ $factory = new LogFactory($c, $this->getSystemConfig());
+ $logger = $factory->get($logType);
$registry = $c->query(\OCP\Support\CrashReport\IRegistry::class);
- return new Log($logger, $config, null, $registry);
+ return new Log($logger, $this->getSystemConfig(), null, $registry);
});
$this->registerAlias('Logger', \OCP\ILogger::class);
+ $this->registerService(ILogFactory::class, function (Server $c) {
+ return new LogFactory($c, $this->getSystemConfig());
+ });
+
$this->registerService(\OCP\BackgroundJob\IJobList::class, function (Server $c) {
$config = $c->getConfig();
return new \OC\BackgroundJob\JobList(
@@ -570,7 +570,7 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService(\OCP\Route\IRouter::class, function (Server $c) {
$cacheFactory = $c->getMemCacheFactory();
$logger = $c->getLogger();
- if ($cacheFactory->isAvailableLowLatency()) {
+ if ($cacheFactory->isLocalCacheAvailable()) {
$router = new \OC\Route\CachingRouter($cacheFactory->createLocal('route'), $logger);
} else {
$router = new \OC\Route\Router($logger);
@@ -584,7 +584,7 @@ class Server extends ServerContainer implements IServerContainer {
});
$this->registerAlias('Search', \OCP\ISearch::class);
- $this->registerService(\OC\Security\RateLimiting\Limiter::class, function ($c) {
+ $this->registerService(\OC\Security\RateLimiting\Limiter::class, function (Server $c) {
return new \OC\Security\RateLimiting\Limiter(
$this->getUserSession(),
$this->getRequest(),
@@ -633,13 +633,6 @@ class Server extends ServerContainer implements IServerContainer {
});
$this->registerAlias('DatabaseConnection', IDBConnection::class);
- $this->registerService('HTTPHelper', function (Server $c) {
- $config = $c->getConfig();
- return new HTTPHelper(
- $config,
- $c->getHTTPClientService()
- );
- });
$this->registerService(\OCP\Http\Client\IClientService::class, function (Server $c) {
$user = \OC_User::getUser();
@@ -814,7 +807,7 @@ class Server extends ServerContainer implements IServerContainer {
'cookies' => $_COOKIE,
'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD']))
? $_SERVER['REQUEST_METHOD']
- : null,
+ : '',
'urlParams' => $urlParams,
],
$this->getSecureRandom(),
@@ -857,7 +850,13 @@ class Server extends ServerContainer implements IServerContainer {
if (!($memcache instanceof \OC\Memcache\NullCache)) {
return new MemcacheLockingProvider($memcache, $ttl);
}
- return new DBLockingProvider($c->getDatabaseConnection(), $c->getLogger(), new TimeFactory(), $ttl);
+ return new DBLockingProvider(
+ $c->getDatabaseConnection(),
+ $c->getLogger(),
+ new TimeFactory(),
+ $ttl,
+ !\OC::$CLI
+ );
}
return new NoopLockingProvider();
});
@@ -947,10 +946,10 @@ class Server extends ServerContainer implements IServerContainer {
$c->getConfig(),
$c->getL10N('theming'),
$c->getURLGenerator(),
- $c->getAppDataDir('theming'),
$c->getMemCacheFactory(),
- new Util($c->getConfig(), $this->getAppManager(), $this->getAppDataDir('theming')),
- $this->getAppManager()
+ new Util($c->getConfig(), $this->getAppManager(), $c->getAppDataDir('theming')),
+ new ImageManager($c->getConfig(), $c->getAppDataDir('theming'), $c->getURLGenerator(), $this->getMemCacheFactory(), $this->getLogger()),
+ $c->getAppManager()
);
}
return new \OC_Defaults();
@@ -965,7 +964,8 @@ class Server extends ServerContainer implements IServerContainer {
$c->getConfig(),
$c->getThemingDefaults(),
\OC::$SERVERROOT,
- $cacheFactory->createDistributed('SCSS')
+ $this->getMemCacheFactory(),
+ $c->query(IconsCacher::class)
);
});
$this->registerService(JSCombiner::class, function (Server $c) {
@@ -974,7 +974,7 @@ class Server extends ServerContainer implements IServerContainer {
return new JSCombiner(
$c->getAppDataDir('js'),
$c->getURLGenerator(),
- $cacheFactory->createDistributed('JS'),
+ $this->getMemCacheFactory(),
$c->getSystemConfig(),
$c->getLogger()
);
@@ -1069,6 +1069,7 @@ class Server extends ServerContainer implements IServerContainer {
$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]);
+ $instance->registerPlugin(['shareType' => 'SHARE_TYPE_REMOTE_GROUP', 'class' => RemoteGroupPlugin::class]);
return $instance;
});
@@ -1115,6 +1116,18 @@ class Server extends ServerContainer implements IServerContainer {
return new CloudIdManager();
});
+ $this->registerService(IConfig::class, function (Server $c) {
+ return new GlobalScale\Config($c->getConfig());
+ });
+
+ $this->registerService(ICloudFederationProviderManager::class, function (Server $c) {
+ return new CloudFederationProviderManager($c->getAppManager(), $c->getHTTPClientService(), $c->getCloudIdManager(), $c->getLogger());
+ });
+
+ $this->registerService(ICloudFederationFactory::class, function (Server $c) {
+ return new CloudFederationFactory();
+ });
+
$this->registerAlias(\OCP\AppFramework\Utility\IControllerMethodReflector::class, \OC\AppFramework\Utility\ControllerMethodReflector::class);
$this->registerAlias('ControllerMethodReflector', \OCP\AppFramework\Utility\IControllerMethodReflector::class);
@@ -1177,6 +1190,20 @@ class Server extends ServerContainer implements IServerContainer {
return $this->query('CalendarManager');
}
+ /**
+ * @return \OCP\Calendar\Resource\IManager
+ */
+ public function getCalendarResourceBackendManager() {
+ return $this->query('CalendarResourceBackendManager');
+ }
+
+ /**
+ * @return \OCP\Calendar\Room\IManager
+ */
+ public function getCalendarRoomBackendManager() {
+ return $this->query('CalendarRoomBackendManager');
+ }
+
private function connectDispatcher() {
$dispatcher = $this->getEventDispatcher();
@@ -1459,13 +1486,6 @@ class Server extends ServerContainer implements IServerContainer {
}
/**
- * @return \OCP\IHelper
- */
- public function getHelper() {
- return $this->query('AppHelper');
- }
-
- /**
* @return AppFetcher
*/
public function getAppFetcher() {
@@ -1539,6 +1559,14 @@ class Server extends ServerContainer implements IServerContainer {
}
/**
+ * @return ILogFactory
+ * @throws \OCP\AppFramework\QueryException
+ */
+ public function getLogFactory() {
+ return $this->query(ILogFactory::class);
+ }
+
+ /**
* Returns a router for generating and matching urls
*
* @return \OCP\Route\IRouter
@@ -1593,16 +1621,6 @@ class Server extends ServerContainer implements IServerContainer {
}
/**
- * Returns an instance of the HTTP helper class
- *
- * @deprecated Use getHTTPClientService()
- * @return \OC\HTTPHelper
- */
- public function getHTTPHelper() {
- return $this->query('HTTPHelper');
- }
-
- /**
* Get the certificate manager for the user
*
* @param string $userId (optional) if not specified the current loggedin user is used, use null to get the system certificate manager
@@ -1977,6 +1995,20 @@ class Server extends ServerContainer implements IServerContainer {
}
/**
+ * @return \OCP\GlobalScale\IConfig
+ */
+ public function getGlobalScaleConfig() {
+ return $this->query(IConfig::class);
+ }
+
+ /**
+ * @return \OCP\Federation\ICloudFederationProviderManager
+ */
+ public function getCloudFederationProviderManager() {
+ return $this->query(ICloudFederationProviderManager::class);
+ }
+
+ /**
* @return \OCP\Remote\Api\IApiFactory
*/
public function getRemoteApiFactory() {
@@ -1984,6 +2016,13 @@ class Server extends ServerContainer implements IServerContainer {
}
/**
+ * @return \OCP\Federation\ICloudFederationFactory
+ */
+ public function getCloudFederationFactory() {
+ return $this->query(ICloudFederationFactory::class);
+ }
+
+ /**
* @return \OCP\Remote\IInstanceFactory
*/
public function getRemoteInstanceFactory() {
diff --git a/lib/private/Session/CryptoSessionData.php b/lib/private/Session/CryptoSessionData.php
index 530bd9063c3..01cac631870 100644
--- a/lib/private/Session/CryptoSessionData.php
+++ b/lib/private/Session/CryptoSessionData.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -55,7 +56,7 @@ class CryptoSessionData implements \ArrayAccess, ISession {
*/
public function __construct(ISession $session,
ICrypto $crypto,
- $passphrase) {
+ string $passphrase) {
$this->crypto = $crypto;
$this->session = $session;
$this->passphrase = $passphrase;
@@ -92,7 +93,7 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @param string $key
* @param mixed $value
*/
- public function set($key, $value) {
+ public function set(string $key, $value) {
$this->sessionValues[$key] = $value;
$this->isModified = true;
}
@@ -103,7 +104,7 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @param string $key
* @return string|null Either the value or null
*/
- public function get($key) {
+ public function get(string $key) {
if(isset($this->sessionValues[$key])) {
return $this->sessionValues[$key];
}
@@ -117,7 +118,7 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @param string $key
* @return bool
*/
- public function exists($key) {
+ public function exists(string $key): bool {
return isset($this->sessionValues[$key]);
}
@@ -126,7 +127,7 @@ class CryptoSessionData implements \ArrayAccess, ISession {
*
* @param string $key
*/
- public function remove($key) {
+ public function remove(string $key) {
$this->isModified = true;
unset($this->sessionValues[$key]);
$this->session->remove(self::encryptedSessionName);
@@ -149,10 +150,11 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* Wrapper around session_regenerate_id
*
* @param bool $deleteOldSession Whether to delete the old associated session file or not.
+ * @param bool $updateToken Wheater to update the associated auth token
* @return void
*/
- public function regenerateId($deleteOldSession = true) {
- $this->session->regenerateId($deleteOldSession);
+ public function regenerateId(bool $deleteOldSession = true, bool $updateToken = false) {
+ $this->session->regenerateId($deleteOldSession, $updateToken);
}
/**
@@ -162,7 +164,7 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @throws SessionNotAvailableException
* @since 9.1.0
*/
- public function getId() {
+ public function getId(): string {
return $this->session->getId();
}
@@ -182,7 +184,7 @@ class CryptoSessionData implements \ArrayAccess, ISession {
* @param mixed $offset
* @return bool
*/
- public function offsetExists($offset) {
+ public function offsetExists($offset): bool {
return $this->exists($offset);
}
diff --git a/lib/private/Session/Internal.php b/lib/private/Session/Internal.php
index d137d72a048..182754f457c 100644
--- a/lib/private/Session/Internal.php
+++ b/lib/private/Session/Internal.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -29,6 +30,10 @@
namespace OC\Session;
+use OC\Authentication\Exceptions\InvalidTokenException;
+use OC\Authentication\Token\IProvider;
+use OC\SystemConfig;
+use OCP\IConfig;
use OCP\Session\Exceptions\SessionNotAvailableException;
/**
@@ -43,8 +48,8 @@ class Internal extends Session {
* @param string $name
* @throws \Exception
*/
- public function __construct($name) {
- set_error_handler(array($this, 'trapError'));
+ public function __construct(string $name) {
+ set_error_handler([$this, 'trapError']);
$this->invoke('session_name', [$name]);
try {
$this->invoke('session_start');
@@ -61,7 +66,7 @@ class Internal extends Session {
* @param string $key
* @param integer $value
*/
- public function set($key, $value) {
+ public function set(string $key, $value) {
$this->validateSession();
$_SESSION[$key] = $value;
}
@@ -70,7 +75,7 @@ class Internal extends Session {
* @param string $key
* @return mixed
*/
- public function get($key) {
+ public function get(string $key) {
if (!$this->exists($key)) {
return null;
}
@@ -81,14 +86,14 @@ class Internal extends Session {
* @param string $key
* @return bool
*/
- public function exists($key) {
+ public function exists(string $key): bool {
return isset($_SESSION[$key]);
}
/**
* @param string $key
*/
- public function remove($key) {
+ public function remove(string $key) {
if (isset($_SESSION[$key])) {
unset($_SESSION[$key]);
}
@@ -110,14 +115,41 @@ class Internal extends Session {
* Wrapper around session_regenerate_id
*
* @param bool $deleteOldSession Whether to delete the old associated session file or not.
+ * @param bool $updateToken Wheater to update the associated auth token
* @return void
*/
- public function regenerateId($deleteOldSession = true) {
+ public function regenerateId(bool $deleteOldSession = true, bool $updateToken = false) {
+ $oldId = null;
+
+ if ($updateToken) {
+ // Get the old id to update the token
+ try {
+ $oldId = $this->getId();
+ } catch (SessionNotAvailableException $e) {
+ // We can't update a token if there is no previous id
+ $updateToken = false;
+ }
+ }
+
try {
@session_regenerate_id($deleteOldSession);
} catch (\Error $e) {
$this->trapError($e->getCode(), $e->getMessage());
}
+
+ if ($updateToken) {
+ // Get the new id to update the token
+ $newId = $this->getId();
+
+ /** @var IProvider $tokenProvider */
+ $tokenProvider = \OC::$server->query(IProvider::class);
+
+ try {
+ $tokenProvider->renewSessionToken($oldId, $newId);
+ } catch (InvalidTokenException $e) {
+ // Just ignore
+ }
+ }
}
/**
@@ -127,7 +159,7 @@ class Internal extends Session {
* @throws SessionNotAvailableException
* @since 9.1.0
*/
- public function getId() {
+ public function getId(): string {
$id = $this->invoke('session_id', [], true);
if ($id === '') {
throw new SessionNotAvailableException();
@@ -147,7 +179,7 @@ class Internal extends Session {
* @param string $errorString
* @throws \ErrorException
*/
- public function trapError($errorNumber, $errorString) {
+ public function trapError(int $errorNumber, string $errorString) {
throw new \ErrorException($errorString);
}
@@ -167,7 +199,7 @@ class Internal extends Session {
* @throws \ErrorException via trapError
* @return mixed
*/
- private function invoke($functionName, array $parameters = [], $silence = false) {
+ private function invoke(string $functionName, array $parameters = [], bool $silence = false) {
try {
if($silence) {
return @call_user_func_array($functionName, $parameters);
diff --git a/lib/private/Session/Memory.php b/lib/private/Session/Memory.php
index 22d6ffa0110..5a2a3039d7b 100644
--- a/lib/private/Session/Memory.php
+++ b/lib/private/Session/Memory.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -40,16 +41,16 @@ use OCP\Session\Exceptions\SessionNotAvailableException;
class Memory extends Session {
protected $data;
- public function __construct($name) {
+ public function __construct(string $name) {
//no need to use $name since all data is already scoped to this instance
- $this->data = array();
+ $this->data = [];
}
/**
* @param string $key
* @param integer $value
*/
- public function set($key, $value) {
+ public function set(string $key, $value) {
$this->validateSession();
$this->data[$key] = $value;
}
@@ -58,7 +59,7 @@ class Memory extends Session {
* @param string $key
* @return mixed
*/
- public function get($key) {
+ public function get(string $key) {
if (!$this->exists($key)) {
return null;
}
@@ -69,20 +70,20 @@ class Memory extends Session {
* @param string $key
* @return bool
*/
- public function exists($key) {
+ public function exists(string $key): bool {
return isset($this->data[$key]);
}
/**
* @param string $key
*/
- public function remove($key) {
+ public function remove(string $key) {
$this->validateSession();
unset($this->data[$key]);
}
public function clear() {
- $this->data = array();
+ $this->data = [];
}
/**
@@ -90,7 +91,7 @@ class Memory extends Session {
*
* @param bool $deleteOldSession
*/
- public function regenerateId($deleteOldSession = true) {}
+ public function regenerateId(bool $deleteOldSession = true, bool $updateToken = false) {}
/**
* Wrapper around session_id
@@ -99,7 +100,7 @@ class Memory extends Session {
* @throws SessionNotAvailableException
* @since 9.1.0
*/
- public function getId() {
+ public function getId(): string {
throw new SessionNotAvailableException('Memory session does not have an ID');
}
diff --git a/lib/private/Session/Session.php b/lib/private/Session/Session.php
index 49afc564306..cadbb7e7ad4 100644
--- a/lib/private/Session/Session.php
+++ b/lib/private/Session/Session.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -38,13 +39,13 @@ abstract class Session implements \ArrayAccess, ISession {
*
* @param string $name
*/
- abstract public function __construct($name);
+ abstract public function __construct(string $name);
/**
* @param mixed $offset
* @return bool
*/
- public function offsetExists($offset) {
+ public function offsetExists($offset): bool {
return $this->exists($offset);
}
diff --git a/lib/private/Settings/Admin/Additional.php b/lib/private/Settings/Admin/Mail.php
index 36258573047..fc20b7eeb3f 100644
--- a/lib/private/Settings/Admin/Additional.php
+++ b/lib/private/Settings/Admin/Mail.php
@@ -29,7 +29,7 @@ use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
use OCP\Settings\ISettings;
-class Additional implements ISettings {
+class Mail implements ISettings {
/** @var IConfig */
private $config;
@@ -63,6 +63,10 @@ class Additional implements ISettings {
$parameters['mail_smtppassword'] = '********';
}
+ if ($parameters['mail_smtpmode'] === '' || $parameters['mail_smtpmode'] === 'php') {
+ $parameters['mail_smtpmode'] = 'smtp';
+ }
+
return new TemplateResponse('settings', 'settings/admin/additional-mail', $parameters, '');
}
@@ -70,7 +74,7 @@ class Additional implements ISettings {
* @return string the section ID, e.g. 'sharing'
*/
public function getSection() {
- return 'additional';
+ return 'server';
}
/**
@@ -81,6 +85,6 @@ class Additional implements ISettings {
* E.g.: 70
*/
public function getPriority() {
- return 0;
+ return 10;
}
}
diff --git a/lib/private/Settings/Admin/TipsTricks.php b/lib/private/Settings/Admin/Overview.php
index 9b295bb9890..51e5808f487 100644
--- a/lib/private/Settings/Admin/TipsTricks.php
+++ b/lib/private/Settings/Admin/Overview.php
@@ -1,9 +1,8 @@
<?php
/**
- * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
*
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
+ * @author Julius Härtl <jus@bitgrid.net>
*
* @license GNU AGPL version 3 or any later version
*
@@ -18,7 +17,7 @@
* 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/>.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -28,13 +27,10 @@ use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig;
use OCP\Settings\ISettings;
-class TipsTricks implements ISettings {
+class Overview implements ISettings {
/** @var IConfig */
private $config;
- /**
- * @param IConfig $config
- */
public function __construct(IConfig $config) {
$this->config = $config;
}
@@ -43,20 +39,18 @@ class TipsTricks implements ISettings {
* @return TemplateResponse
*/
public function getForm() {
- $databaseOverload = (strpos($this->config->getSystemValue('dbtype'), 'sqlite') !== false);
-
$parameters = [
- 'databaseOverload' => $databaseOverload,
+ 'checkForWorkingWellKnownSetup' => $this->config->getSystemValue('check_for_working_wellknown_setup', true),
];
- return new TemplateResponse('settings', 'settings/admin/tipstricks', $parameters, '');
+ return new TemplateResponse('settings', 'settings/admin/overview', $parameters, '');
}
/**
* @return string the section ID, e.g. 'sharing'
*/
public function getSection() {
- return 'tips-tricks';
+ return 'overview';
}
/**
@@ -67,6 +61,6 @@ class TipsTricks implements ISettings {
* E.g.: 70
*/
public function getPriority() {
- return 0;
+ return 10;
}
}
diff --git a/lib/private/Settings/Admin/Server.php b/lib/private/Settings/Admin/Server.php
index 0b9c042e4f2..1ebea8a4dcd 100644
--- a/lib/private/Settings/Admin/Server.php
+++ b/lib/private/Settings/Admin/Server.php
@@ -74,63 +74,7 @@ class Server implements ISettings {
* @return TemplateResponse
*/
public function getForm() {
- try {
- if ($this->db->getDatabasePlatform() instanceof SqlitePlatform) {
- $invalidTransactionIsolationLevel = false;
- } else {
- $invalidTransactionIsolationLevel = $this->db->getTransactionIsolation() !== Connection::TRANSACTION_READ_COMMITTED;
- }
- } catch (DBALException $e) {
- // ignore
- $invalidTransactionIsolationLevel = false;
- }
-
- $envPath = getenv('PATH');
-
- // warn if outdated version of a memcache module is used
- $caches = [
- 'apcu' => ['name' => $this->l->t('APCu'), 'version' => '4.0.6'],
- 'redis' => ['name' => $this->l->t('Redis'), 'version' => '2.2.5'],
- ];
- $outdatedCaches = [];
- foreach ($caches as $php_module => $data) {
- $isOutdated = extension_loaded($php_module) && version_compare(phpversion($php_module), $data['version'], '<');
- if ($isOutdated) {
- $outdatedCaches[$php_module] = $data;
- }
- }
-
- if ($this->lockingProvider instanceof NoopLockingProvider) {
- $fileLockingType = 'none';
- } else if ($this->lockingProvider instanceof DBLockingProvider) {
- $fileLockingType = 'db';
- } else {
- $fileLockingType = 'cache';
- }
-
- $suggestedOverwriteCliUrl = '';
- if ($this->config->getSystemValue('overwrite.cli.url', '') === '') {
- $suggestedOverwriteCliUrl = $this->request->getServerProtocol() . '://' . $this->request->getInsecureServerHost() . \OC::$WEBROOT;
- if (!$this->config->getSystemValue('config_is_read_only', false)) {
- // Set the overwrite URL when it was not set yet.
- $this->config->setSystemValue('overwrite.cli.url', $suggestedOverwriteCliUrl);
- $suggestedOverwriteCliUrl = '';
- }
- }
-
$parameters = [
- // Diagnosis
- 'readOnlyConfigEnabled' => \OC_Helper::isReadOnlyConfigEnabled(),
- 'isLocaleWorking' => \OC_Util::isSetLocaleWorking(),
- 'isAnnotationsWorking' => \OC_Util::isAnnotationsWorking(),
- 'checkForWorkingWellKnownSetup' => $this->config->getSystemValue('check_for_working_wellknown_setup', true),
- 'has_fileinfo' => \OC_Util::fileInfoLoaded(),
- 'invalidTransactionIsolationLevel' => $invalidTransactionIsolationLevel,
- 'getenvServerNotWorking' => empty($envPath),
- 'OutdatedCacheWarning' => $outdatedCaches,
- 'fileLockingType' => $fileLockingType,
- 'suggestedOverwriteCliUrl' => $suggestedOverwriteCliUrl,
-
// Background jobs
'backgroundjobs_mode' => $this->config->getAppValue('core', 'backgroundjobs_mode', 'ajax'),
'lastcron' => $this->config->getAppValue('core', 'lastcron', false),
diff --git a/lib/private/Settings/Admin/Sharing.php b/lib/private/Settings/Admin/Sharing.php
index dbdacf78dab..dfc0b11478b 100644
--- a/lib/private/Settings/Admin/Sharing.php
+++ b/lib/private/Settings/Admin/Sharing.php
@@ -28,7 +28,9 @@ namespace OC\Settings\Admin;
use OC\Share\Share;
use OCP\AppFramework\Http\TemplateResponse;
+use OCP\Constants;
use OCP\IConfig;
+use OCP\IL10N;
use OCP\Settings\ISettings;
use OCP\Util;
@@ -36,11 +38,15 @@ class Sharing implements ISettings {
/** @var IConfig */
private $config;
+ /** @var IL10N */
+ private $l;
+
/**
* @param IConfig $config
*/
- public function __construct(IConfig $config) {
+ public function __construct(IConfig $config, IL10N $l) {
$this->config = $config;
+ $this->l = $l;
}
/**
@@ -53,27 +59,59 @@ class Sharing implements ISettings {
$parameters = [
// Built-In Sharing
- 'allowGroupSharing' => $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes'),
- 'allowLinks' => $this->config->getAppValue('core', 'shareapi_allow_links', 'yes'),
- 'allowPublicUpload' => $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes'),
- 'allowResharing' => $this->config->getAppValue('core', 'shareapi_allow_resharing', 'yes'),
- 'allowShareDialogUserEnumeration' => $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes'),
- 'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(),
- 'onlyShareWithGroupMembers' => Share::shareWithGroupMembersOnly(),
- 'shareAPIEnabled' => $this->config->getAppValue('core', 'shareapi_enabled', 'yes'),
- 'shareDefaultExpireDateSet' => $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no'),
- 'shareExpireAfterNDays' => $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7'),
- 'shareEnforceExpireDate' => $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no'),
- 'shareExcludeGroups' => $this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes',
- 'shareExcludedGroupsList' => $excludeGroupsList,
- 'publicShareDisclaimerText' => $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null),
- 'enableLinkPasswordByDefault' => $this->config->getAppValue('core', 'shareapi_enable_link_password_by_default', 'no'),
+ 'allowGroupSharing' => $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes'),
+ 'allowLinks' => $this->config->getAppValue('core', 'shareapi_allow_links', 'yes'),
+ 'allowPublicUpload' => $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes'),
+ 'allowResharing' => $this->config->getAppValue('core', 'shareapi_allow_resharing', 'yes'),
+ 'allowShareDialogUserEnumeration' => $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes'),
+ 'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(),
+ 'onlyShareWithGroupMembers' => Share::shareWithGroupMembersOnly(),
+ 'shareAPIEnabled' => $this->config->getAppValue('core', 'shareapi_enabled', 'yes'),
+ 'shareDefaultExpireDateSet' => $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no'),
+ 'shareExpireAfterNDays' => $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7'),
+ 'shareEnforceExpireDate' => $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no'),
+ 'shareExcludeGroups' => $this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes',
+ 'shareExcludedGroupsList' => $excludeGroupsList,
+ 'publicShareDisclaimerText' => $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null),
+ 'enableLinkPasswordByDefault' => $this->config->getAppValue('core', 'shareapi_enable_link_password_by_default', 'no'),
+ 'shareApiDefaultPermissions' => $this->config->getAppValue('core', 'shareapi_default_permissions', Constants::PERMISSION_ALL),
+ 'shareApiDefaultPermissionsCheckboxes' => $this->getSharePermissionList(),
];
return new TemplateResponse('settings', 'settings/admin/sharing', $parameters, '');
}
/**
+ * get share permission list for template
+ *
+ * @return array
+ */
+ private function getSharePermissionList() {
+ return [
+ [
+ 'id' => 'cancreate',
+ 'label' => $this->l->t('Create'),
+ 'value' => Constants::PERMISSION_CREATE
+ ],
+ [
+ 'id' => 'canupdate',
+ 'label' => $this->l->t('Change'),
+ 'value' => Constants::PERMISSION_UPDATE
+ ],
+ [
+ 'id' => 'candelete',
+ 'label' => $this->l->t('Delete'),
+ 'value' => Constants::PERMISSION_DELETE
+ ],
+ [
+ 'id' => 'canshare',
+ 'label' => $this->l->t('Share'),
+ 'value' => Constants::PERMISSION_SHARE
+ ],
+ ];
+ }
+
+ /**
* @return string the section ID, e.g. 'sharing'
*/
public function getSection() {
diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php
index 387460852ab..e9f2a6f5976 100644
--- a/lib/private/Settings/Manager.php
+++ b/lib/private/Settings/Manager.php
@@ -150,12 +150,12 @@ class Manager implements IManager {
/** @var ISection $section */
$section = \OC::$server->query($class);
} catch (QueryException $e) {
- $this->log->logException($e, ['level' => Util::INFO]);
+ $this->log->logException($e, ['level' => ILogger::INFO]);
continue;
}
if (!$section instanceof ISection) {
- $this->log->logException(new \InvalidArgumentException('Invalid settings section registered'), ['level' => Util::INFO]);
+ $this->log->logException(new \InvalidArgumentException('Invalid settings section registered'), ['level' => ILogger::INFO]);
continue;
}
@@ -200,12 +200,12 @@ class Manager implements IManager {
/** @var ISettings $setting */
$setting = \OC::$server->query($class);
} catch (QueryException $e) {
- $this->log->logException($e, ['level' => Util::INFO]);
+ $this->log->logException($e, ['level' => ILogger::INFO]);
continue;
}
if (!$setting instanceof ISettings) {
- $this->log->logException(new \InvalidArgumentException('Invalid settings setting registered'), ['level' => Util::INFO]);
+ $this->log->logException(new \InvalidArgumentException('Invalid settings setting registered'), ['level' => ILogger::INFO]);
continue;
}
@@ -226,12 +226,13 @@ class Manager implements IManager {
public function getAdminSections(): array {
// built-in sections
$sections = [
- 0 => [new Section('server', $this->l->t('Basic settings'), 0, $this->url->imagePath('settings', 'admin.svg'))],
+ 0 => [new Section('overview', $this->l->t('Overview'), 0, $this->url->imagePath('settings', 'admin.svg'))],
+ 1 => [new Section('server', $this->l->t('Basic settings'), 0, $this->url->imagePath('core', 'actions/settings-dark.svg'))],
5 => [new Section('sharing', $this->l->t('Sharing'), 0, $this->url->imagePath('core', 'actions/share.svg'))],
10 => [new Section('security', $this->l->t('Security'), 0, $this->url->imagePath('core', 'actions/password.svg'))],
45 => [new Section('encryption', $this->l->t('Encryption'), 0, $this->url->imagePath('core', 'actions/password.svg'))],
+ 50 => [new Section('groupware', $this->l->t('Groupware'), 0, $this->url->imagePath('core', 'places/contacts.svg'))],
98 => [new Section('additional', $this->l->t('Additional settings'), 0, $this->url->imagePath('core', 'actions/settings-dark.svg'))],
- 99 => [new Section('tips-tricks', $this->l->t('Tips & tricks'), 0, $this->url->imagePath('settings', 'help.svg'))],
];
$appSections = $this->getSections('admin');
@@ -257,11 +258,16 @@ class Manager implements IManager {
private function getBuiltInAdminSettings($section): array {
$forms = [];
+ if ($section === 'overview') {
+ /** @var ISettings $form */
+ $form = new Admin\Overview($this->config);
+ $forms[$form->getPriority()] = [$form];
+ }
if ($section === 'server') {
/** @var ISettings $form */
$form = new Admin\Server($this->dbc, $this->request, $this->config, $this->lockingProvider, $this->l);
$forms[$form->getPriority()] = [$form];
- $form = new Admin\ServerDevNotice();
+ $form = new Admin\Mail($this->config);
$forms[$form->getPriority()] = [$form];
}
if ($section === 'encryption') {
@@ -271,17 +277,7 @@ class Manager implements IManager {
}
if ($section === 'sharing') {
/** @var ISettings $form */
- $form = new Admin\Sharing($this->config);
- $forms[$form->getPriority()] = [$form];
- }
- if ($section === 'additional') {
- /** @var ISettings $form */
- $form = new Admin\Additional($this->config);
- $forms[$form->getPriority()] = [$form];
- }
- if ($section === 'tips-tricks') {
- /** @var ISettings $form */
- $form = new Admin\TipsTricks($this->config);
+ $form = new Admin\Sharing($this->config, $this->l);
$forms[$form->getPriority()] = [$form];
}
@@ -307,10 +303,12 @@ class Manager implements IManager {
$this->l
);
$forms[$form->getPriority()] = [$form];
+ $form = new Personal\ServerDevNotice();
+ $forms[$form->getPriority()] = [$form];
}
if($section === 'security') {
/** @var ISettings $form */
- $form = new Personal\Security();
+ $form = new Personal\Security($this->userManager);
$forms[$form->getPriority()] = [$form];
}
if ($section === 'additional') {
@@ -347,7 +345,7 @@ class Manager implements IManager {
$sections = [
0 => [new Section('personal-info', $this->l->t('Personal info'), 0, $this->url->imagePath('core', 'actions/info.svg'))],
5 => [new Section('security', $this->l->t('Security'), 0, $this->url->imagePath('settings', 'password.svg'))],
- 15 => [new Section('sync-clients', $this->l->t('Sync clients'), 0, $this->url->imagePath('settings', 'change.svg'))],
+ 15 => [new Section('sync-clients', $this->l->t('Mobile & desktop'), 0, $this->url->imagePath('core', 'clients/phone.svg'))],
];
$legacyForms = \OC_App::getForms('personal');
diff --git a/lib/private/Settings/Personal/PersonalInfo.php b/lib/private/Settings/Personal/PersonalInfo.php
index ad277b43194..8c1c8cb19b8 100644
--- a/lib/private/Settings/Personal/PersonalInfo.php
+++ b/lib/private/Settings/Personal/PersonalInfo.php
@@ -4,6 +4,7 @@
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Morris Jobke <hey@morrisjobke.de>
+ * @author Thomas Citharel <tcit@tcit.fr>
*
* @license GNU AGPL version 3 or any later version
*
@@ -39,6 +40,7 @@ use OCP\L10N\IFactory;
use OCP\Settings\ISettings;
class PersonalInfo implements ISettings {
+
/** @var IConfig */
private $config;
/** @var IUserManager */
@@ -51,12 +53,6 @@ class PersonalInfo implements ISettings {
private $appManager;
/** @var IFactory */
private $l10nFactory;
-
- const COMMON_LANGUAGE_CODES = [
- 'en', 'es', 'fr', 'de', 'de_DE', 'ja', 'ar', 'ru', 'nl', 'it',
- 'pt_BR', 'pt_PT', 'da', 'fi_FI', 'nb_NO', 'sv', 'tr', 'zh_CN', 'ko'
- ];
-
/** @var IL10N */
private $l;
@@ -111,6 +107,7 @@ class PersonalInfo implements ISettings {
}
$languageParameters = $this->getLanguages($user);
+ $localeParameters = $this->getLocales($user);
$messageParameters = $this->getMessageParameters($userData);
$parameters = [
@@ -138,8 +135,7 @@ class PersonalInfo implements ISettings {
'twitterScope' => $userData[AccountManager::PROPERTY_TWITTER]['scope'],
'twitterVerification' => $userData[AccountManager::PROPERTY_TWITTER]['verified'],
'groups' => $this->getGroups($user),
- 'passwordChangeSupported' => $user->canChangePassword(),
- ] + $messageParameters + $languageParameters;
+ ] + $messageParameters + $languageParameters + $localeParameters;
return new TemplateResponse('settings', 'settings/personal/personal.info', $parameters, '');
@@ -174,7 +170,7 @@ class PersonalInfo implements ISettings {
private function getGroups(IUser $user) {
$groups = array_map(
function(IGroup $group) {
- return $group->getGID();
+ return $group->getDisplayName();
},
$this->groupManager->getUserGroups($user)
);
@@ -198,63 +194,63 @@ class PersonalInfo implements ISettings {
$uid = $user->getUID();
- $userLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
- $languageCodes = $this->l10nFactory->findAvailableLanguages();
-
- $commonLanguages = [];
- $languages = [];
-
- foreach($languageCodes as $lang) {
- $l = \OC::$server->getL10N('settings', $lang);
- // TRANSLATORS this is the language name for the language switcher in the personal settings and should be the localized version
- $potentialName = (string) $l->t('__language_name__');
- if($l->getLanguageCode() === $lang && $potentialName[0] !== '_') {//first check if the language name is in the translation file
- $ln = array('code' => $lang, 'name' => $potentialName);
- } elseif ($lang === 'en') {
- $ln = ['code' => $lang, 'name' => 'English (US)'];
- }else{//fallback to language code
- $ln=array('code'=>$lang, 'name'=>$lang);
- }
+ $userConfLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
+ $languages = $this->l10nFactory->getLanguages();
- // put appropriate languages into appropriate arrays, to print them sorted
- // used language -> common languages -> divider -> other languages
- if ($lang === $userLang) {
- $userLang = $ln;
- } elseif (in_array($lang, self::COMMON_LANGUAGE_CODES)) {
- $commonLanguages[array_search($lang, self::COMMON_LANGUAGE_CODES)]=$ln;
- } else {
- $languages[]=$ln;
- }
+ // associate the user language with the proper array
+ $userLangIndex = array_search($userConfLang, array_column($languages['commonlanguages'], 'code'));
+ $userLang = $languages['commonlanguages'][$userLangIndex];
+ // search in the other languages
+ if ($userLangIndex === false) {
+ $userLangIndex = array_search($userConfLang, array_column($languages['languages'], 'code'));
+ $userLang = $languages['languages'][$userLangIndex];
}
-
// if user language is not available but set somehow: show the actual code as name
if (!is_array($userLang)) {
$userLang = [
- 'code' => $userLang,
- 'name' => $userLang,
+ 'code' => $userConfLang,
+ 'name' => $userConfLang,
];
}
- ksort($commonLanguages);
+ return array_merge(
+ array('activelanguage' => $userLang),
+ $languages
+ );
+ }
- // sort now by displayed language not the iso-code
- usort( $languages, function ($a, $b) {
- if ($a['code'] === $a['name'] && $b['code'] !== $b['name']) {
- // If a doesn't have a name, but b does, list b before a
- return 1;
- }
- if ($a['code'] !== $a['name'] && $b['code'] === $b['name']) {
- // If a does have a name, but b doesn't, list a before b
- return -1;
- }
- // Otherwise compare the names
- return strcmp($a['name'], $b['name']);
+ private function getLocales(IUser $user) {
+ $forceLanguage = $this->config->getSystemValue('force_locale', false);
+ if($forceLanguage !== false) {
+ return [];
+ }
+
+ $uid = $user->getUID();
+
+ $userLocaleString = $this->config->getUserValue($uid, 'core', 'locale', 'en_US');
+
+ $userLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage());
+
+ $localeCodes = $this->l10nFactory->findAvailableLocales();
+
+ $userLocale = array_filter($localeCodes, function($value) use ($userLocaleString) {
+ return $userLocaleString === $value['code'];
+ });
+
+ if (!empty($userLocale))
+ {
+ $userLocale = reset($userLocale);
+ }
+
+ $localesForLanguage = array_filter($localeCodes, function($localeCode) use ($userLang) {
+ return 0 === strpos($localeCode['code'], $userLang);
});
return [
- 'activelanguage' => $userLang,
- 'commonlanguages' => $commonLanguages,
- 'languages' => $languages
+ 'activelocaleLang' => $userLocaleString,
+ 'activelocale' => $userLocale,
+ 'locales' => $localeCodes,
+ 'localesForLanguage' => $localesForLanguage,
];
}
diff --git a/lib/private/Settings/Personal/Security.php b/lib/private/Settings/Personal/Security.php
index ecbd1199d11..efcfd5589ce 100644
--- a/lib/private/Settings/Personal/Security.php
+++ b/lib/private/Settings/Personal/Security.php
@@ -25,16 +25,33 @@ namespace OC\Settings\Personal;
use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IUserManager;
use OCP\Settings\ISettings;
class Security implements ISettings {
+ private $userManager;
+
+ public function __construct(
+ IUserManager $userManager
+ ) {
+ $this->userManager = $userManager;
+ }
+
/**
* @return TemplateResponse returns the instance with all parameters set, ready to be rendered
* @since 9.1
*/
public function getForm() {
- return new TemplateResponse('settings', 'settings/personal/security');
+ $user = $this->userManager->get(\OC_User::getUser());
+ $passwordChangeSupported = false;
+ if ($user !== null) {
+ $passwordChangeSupported = $user->canChangePassword();
+ }
+
+ return new TemplateResponse('settings', 'settings/personal/security', [
+ 'passwordChangeSupported' => $passwordChangeSupported
+ ]);
}
/**
diff --git a/lib/private/Settings/Admin/ServerDevNotice.php b/lib/private/Settings/Personal/ServerDevNotice.php
index 22637729b0f..fa5a736cded 100644
--- a/lib/private/Settings/Admin/ServerDevNotice.php
+++ b/lib/private/Settings/Personal/ServerDevNotice.php
@@ -18,10 +18,10 @@
* 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/>.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
-namespace OC\Settings\Admin;
+namespace OC\Settings\Personal;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Settings\ISettings;
@@ -31,14 +31,14 @@ class ServerDevNotice implements ISettings {
* @return TemplateResponse
*/
public function getForm() {
- return new TemplateResponse('settings', 'settings/admin/server.development.notice');
+ return new TemplateResponse('settings', 'settings/personal/development.notice');
}
/**
* @return string the section ID, e.g. 'sharing'
*/
public function getSection() {
- return 'server';
+ return 'personal-info';
}
/**
diff --git a/lib/private/Setup.php b/lib/private/Setup.php
index 43fa6c4a117..25e0b4d8817 100644
--- a/lib/private/Setup.php
+++ b/lib/private/Setup.php
@@ -47,6 +47,7 @@ use OC\App\AppStore\Bundles\BundleFetcher;
use OC\Authentication\Token\DefaultTokenCleanupJob;
use OC\Authentication\Token\DefaultTokenProvider;
use OC\Log\Rotate;
+use OC\Preview\BackgroundCleanupJob;
use OCP\Defaults;
use OCP\IL10N;
use OCP\ILogger;
@@ -325,15 +326,20 @@ class Setup {
$secret = $this->random->generate(48);
//write the config file
- $this->config->setValues([
+ $newConfigValues = [
'passwordsalt' => $salt,
'secret' => $secret,
'trusted_domains' => $trustedDomains,
'datadirectory' => $dataDir,
- 'overwrite.cli.url' => $request->getServerProtocol() . '://' . $request->getInsecureServerHost() . \OC::$WEBROOT,
'dbtype' => $dbType,
'version' => implode('.', \OCP\Util::getVersion()),
- ]);
+ ];
+
+ if ($this->config->getValue('overwrite.cli.url', null) === null) {
+ $newConfigValues['overwrite.cli.url'] = $request->getServerProtocol() . '://' . $request->getInsecureServerHost() . \OC::$WEBROOT;
+ }
+
+ $this->config->setValues($newConfigValues);
try {
$dbSetup->initialize($options);
@@ -414,6 +420,7 @@ class Setup {
$jobList = \OC::$server->getJobList();
$jobList->add(DefaultTokenCleanupJob::class);
$jobList->add(Rotate::class);
+ $jobList->add(BackgroundCleanupJob::class);
}
/**
@@ -485,7 +492,7 @@ class Setup {
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/robots.txt";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/updater/";
$content .= "\n RewriteCond %{REQUEST_FILENAME} !/ocs-provider/";
- $content .= "\n RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/.*";
+ $content .= "\n RewriteCond %{REQUEST_URI} !^/\\.well-known/(acme-challenge|pki-validation)/.*";
$content .= "\n RewriteRule . index.php [PT,E=PATH_INFO:$1]";
$content .= "\n RewriteBase " . $rewriteBase;
$content .= "\n <IfModule mod_env.c>";
diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php
index d3b39007aa9..dd215f96cbe 100644
--- a/lib/private/Setup/MySQL.php
+++ b/lib/private/Setup/MySQL.php
@@ -31,6 +31,7 @@ namespace OC\Setup;
use OC\DB\MySqlTools;
use OCP\IDBConnection;
+use OCP\ILogger;
class MySQL extends AbstractDatabase {
public $dbprettyname = 'MySQL/MariaDB';
@@ -70,7 +71,7 @@ class MySQL extends AbstractDatabase {
} catch (\Exception $ex) {
$this->logger->logException($ex, [
'message' => 'Database creation failed.',
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'mysql.setup',
]);
return;
@@ -83,7 +84,7 @@ class MySQL extends AbstractDatabase {
} catch (\Exception $ex) {
$this->logger->logException($ex, [
'message' => 'Could not automatically grant privileges, this can be ignored if database user already had privileges.',
- 'level' => \OCP\Util::DEBUG,
+ 'level' => ILogger::DEBUG,
'app' => 'mysql.setup',
]);
}
@@ -107,7 +108,7 @@ class MySQL extends AbstractDatabase {
catch (\Exception $ex){
$this->logger->logException($ex, [
'message' => 'Database user creation failed.',
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'mysql.setup',
]);
}
@@ -162,7 +163,7 @@ class MySQL extends AbstractDatabase {
} catch (\Exception $ex) {
$this->logger->logException($ex, [
'message' => 'Can not create a new MySQL user, will continue with the provided user.',
- 'level' => \OCP\Util::INFO,
+ 'level' => ILogger::INFO,
'app' => 'mysql.setup',
]);
}
diff --git a/lib/private/Share/Constants.php b/lib/private/Share/Constants.php
index f351f8d7fda..4eb79734c06 100644
--- a/lib/private/Share/Constants.php
+++ b/lib/private/Share/Constants.php
@@ -37,6 +37,7 @@ class Constants {
const SHARE_TYPE_REMOTE = 6;
const SHARE_TYPE_CIRCLE = 7;
const SHARE_TYPE_GUEST = 8;
+ const SHARE_TYPE_REMOTE_GROUP = 9;
const FORMAT_NONE = -1;
const FORMAT_STATUSES = -2;
diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php
index 9507eaf5c1f..52e0628987b 100644
--- a/lib/private/Share/Share.php
+++ b/lib/private/Share/Share.php
@@ -39,13 +39,9 @@
namespace OC\Share;
-use OC\Files\Filesystem;
use OCP\DB\QueryBuilder\IQueryBuilder;
-use OCP\ILogger;
-use OCP\IUserManager;
-use OCP\IUserSession;
-use OCP\IDBConnection;
use OCP\IConfig;
+use OCP\ILogger;
use OCP\Util;
/**
@@ -97,7 +93,7 @@ class Share extends Constants {
\OCP\Util::writeLog('OCP\Share',
'Sharing backend '.$class.' not registered, '.self::$backendTypes[$itemType]['class']
.' is already registered for '.$itemType,
- \OCP\Util::WARN);
+ ILogger::WARN);
}
return false;
}
@@ -269,7 +265,7 @@ class Share extends Constants {
$query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `token` = ?', 1);
$result = $query->execute(array($token));
if ($result === false) {
- \OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage() . ', token=' . $token, \OCP\Util::ERROR);
+ \OCP\Util::writeLog('OCP\Share', \OC_DB::getErrorMessage() . ', token=' . $token, ILogger::ERROR);
}
$row = $result->fetchRow();
if ($row === false) {
@@ -288,29 +284,6 @@ class Share extends Constants {
}
/**
- * resolves reshares down to the last real share
- * @param array $linkItem
- * @return array file owner
- */
- public static function resolveReShare($linkItem)
- {
- if (isset($linkItem['parent'])) {
- $parent = $linkItem['parent'];
- while (isset($parent)) {
- $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `id` = ?', 1);
- $item = $query->execute(array($parent))->fetchRow();
- if (isset($item['parent'])) {
- $parent = $item['parent'];
- } else {
- return $item;
- }
- }
- }
- return $linkItem;
- }
-
-
- /**
* Get the shared items of item type owned by the current user
* @param string $itemType
* @param int $format (optional) Format type must be defined by the backend
@@ -354,6 +327,7 @@ class Share extends Constants {
* @throws \OC\HintException when the share type is remote and the shareWith is invalid
* @throws \Exception
* @since 5.0.0 - parameter $itemSourceName was added in 6.0.0, parameter $expirationDate was added in 7.0.0, parameter $passwordChanged added in 9.0.0
+ * @deprecated 14.0.0 TESTS ONLY - this methods is as of 2018-06 only used by tests
*/
public static function shareItem($itemType, $itemSource, $shareType, $shareWith, $permissions, $itemSourceName = null, \DateTime $expirationDate = null, $passwordChanged = null) {
@@ -363,7 +337,7 @@ class Share extends Constants {
if ($backend->isShareTypeAllowed($shareType) === false) {
$message = 'Sharing %s failed, because the backend does not allow shares from type %i';
$message_t = $l->t('Sharing %s failed, because the backend does not allow shares from type %i', array($itemSourceName, $shareType));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareType), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareType), ILogger::DEBUG);
throw new \Exception($message_t);
}
@@ -384,14 +358,14 @@ class Share extends Constants {
if (!$path) {
$message = 'Sharing %s failed, because the file does not exist';
$message_t = $l->t('Sharing %s failed, because the file does not exist', array($itemSourceName));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), ILogger::DEBUG);
throw new \Exception($message_t);
}
// verify that the user has share permission
if (!\OC\Files\Filesystem::isSharable($path) || \OCP\Util::isSharingDisabledForUser()) {
$message = 'You are not allowed to share %s';
$message_t = $l->t('You are not allowed to share %s', [$path]);
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $path), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $path), ILogger::DEBUG);
throw new \Exception($message_t);
}
}
@@ -404,7 +378,7 @@ class Share extends Constants {
foreach ($mounts as $mount) {
if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) {
$message = 'Sharing "' . $itemSourceName . '" failed, because it contains files shared with you!';
- \OCP\Util::writeLog('OCP\Share', $message, \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', $message, ILogger::DEBUG);
throw new \Exception($message);
}
@@ -436,13 +410,13 @@ class Share extends Constants {
if ($shareWith == $uidOwner) {
$message = 'Sharing %s failed, because you can not share with yourself';
$message_t = $l->t('Sharing %s failed, because you can not share with yourself', [$itemName]);
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), ILogger::DEBUG);
throw new \Exception($message_t);
}
if (!\OC::$server->getUserManager()->userExists($shareWith)) {
$message = 'Sharing %s failed, because the user %s does not exist';
$message_t = $l->t('Sharing %s failed, because the user %s does not exist', array($itemSourceName, $shareWith));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
throw new \Exception($message_t);
}
if ($shareWithinGroupOnly) {
@@ -463,7 +437,7 @@ class Share extends Constants {
$message = 'Sharing %s failed, because the user '
.'%s is not a member of any groups that %s is a member of';
$message_t = $l->t('Sharing %s failed, because the user %s is not a member of any groups that %s is a member of', array($itemName, $shareWith, $uidOwner));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemName, $shareWith, $uidOwner), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemName, $shareWith, $uidOwner), ILogger::DEBUG);
throw new \Exception($message_t);
}
}
@@ -476,7 +450,7 @@ class Share extends Constants {
if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
$message = 'Sharing %s failed, because this item is already shared with %s';
$message_t = $l->t('Sharing %s failed, because this item is already shared with %s', array($itemSourceName, $shareWith));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
throw new \Exception($message_t);
}
}
@@ -488,7 +462,7 @@ class Share extends Constants {
if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
$message = 'Sharing %s failed, because this item is already shared with user %s';
$message_t = $l->t('Sharing %s failed, because this item is already shared with user %s', array($itemSourceName, $shareWith));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), \OCP\Util::ERROR);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::ERROR);
throw new \Exception($message_t);
}
}
@@ -496,7 +470,7 @@ class Share extends Constants {
if (!\OC::$server->getGroupManager()->groupExists($shareWith)) {
$message = 'Sharing %s failed, because the group %s does not exist';
$message_t = $l->t('Sharing %s failed, because the group %s does not exist', array($itemSourceName, $shareWith));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
throw new \Exception($message_t);
}
if ($shareWithinGroupOnly) {
@@ -506,7 +480,7 @@ class Share extends Constants {
$message = 'Sharing %s failed, because '
. '%s is not a member of the group %s';
$message_t = $l->t('Sharing %s failed, because %s is not a member of the group %s', array($itemSourceName, $uidOwner, $shareWith));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $uidOwner, $shareWith), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $uidOwner, $shareWith), ILogger::DEBUG);
throw new \Exception($message_t);
}
}
@@ -518,7 +492,7 @@ class Share extends Constants {
if ($checkExists['share_with'] === $shareWith && $checkExists['share_type'] === \OCP\Share::SHARE_TYPE_GROUP) {
$message = 'Sharing %s failed, because this item is already shared with %s';
$message_t = $l->t('Sharing %s failed, because this item is already shared with %s', array($itemSourceName, $shareWith));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
throw new \Exception($message_t);
}
}
@@ -585,7 +559,7 @@ class Share extends Constants {
if (\OCP\Util::isPublicLinkPasswordRequired() && empty($shareWith)) {
$message = 'You need to provide a password to create a public link, only protected links are allowed';
$message_t = $l->t('You need to provide a password to create a public link, only protected links are allowed');
- \OCP\Util::writeLog('OCP\Share', $message, \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', $message, ILogger::DEBUG);
throw new \Exception($message_t);
}
@@ -613,7 +587,7 @@ class Share extends Constants {
}
$message = 'Sharing %s failed, because sharing with links is not allowed';
$message_t = $l->t('Sharing %s failed, because sharing with links is not allowed', array($itemSourceName));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), ILogger::DEBUG);
throw new \Exception($message_t);
} else if ($shareType === self::SHARE_TYPE_REMOTE) {
@@ -624,7 +598,7 @@ class Share extends Constants {
$shareWith, $uidOwner, self::FORMAT_NONE, null, 1, true, true)) {
$message = 'Sharing %s failed, because this item is already shared with %s';
$message_t = $l->t('Sharing %s failed, because this item is already shared with %s', array($itemSourceName, $shareWith));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
throw new \Exception($message_t);
}
@@ -635,7 +609,7 @@ class Share extends Constants {
if (Helper::isSameUserOnSameServer($user, $remote, $currentUser, $currentServer)) {
$message = 'Not allowed to create a federated share with the same user.';
$message_t = $l->t('Not allowed to create a federated share with the same user');
- \OCP\Util::writeLog('OCP\Share', $message, \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', $message, ILogger::DEBUG);
throw new \Exception($message_t);
}
@@ -662,7 +636,7 @@ class Share extends Constants {
// Future share types need to include their own conditions
$message = 'Share type %s is not valid for %s';
$message_t = $l->t('Share type %s is not valid for %s', array($shareType, $itemSource));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $shareType, $itemSource), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $shareType, $itemSource), ILogger::DEBUG);
throw new \Exception($message_t);
}
@@ -731,7 +705,7 @@ class Share extends Constants {
$result = $query->execute(array($status, $itemType, $itemSource, $shareType, $recipient));
if($result === false) {
- \OCP\Util::writeLog('OCP\Share', 'Couldn\'t set send mail status', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('OCP\Share', 'Couldn\'t set send mail status', ILogger::ERROR);
}
}
@@ -768,7 +742,7 @@ class Share extends Constants {
if ($date > $maxDate) {
$warning = 'Cannot set expiration date. Shares cannot expire later than ' . $maxDays . ' after they have been shared';
$warning_t = $l->t('Cannot set expiration date. Shares cannot expire later than %s after they have been shared', array($maxDays));
- \OCP\Util::writeLog('OCP\Share', $warning, \OCP\Util::WARN);
+ \OCP\Util::writeLog('OCP\Share', $warning, ILogger::WARN);
throw new \Exception($warning_t);
}
}
@@ -776,7 +750,7 @@ class Share extends Constants {
if ($date < $today) {
$message = 'Cannot set expiration date. Expiration date is in the past';
$message_t = $l->t('Cannot set expiration date. Expiration date is in the past');
- \OCP\Util::writeLog('OCP\Share', $message, \OCP\Util::WARN);
+ \OCP\Util::writeLog('OCP\Share', $message, ILogger::WARN);
throw new \Exception($message_t);
}
@@ -877,20 +851,20 @@ class Share extends Constants {
if (!(self::$backends[$itemType] instanceof \OCP\Share_Backend)) {
$message = 'Sharing backend %s must implement the interface OCP\Share_Backend';
$message_t = $l->t('Sharing backend %s must implement the interface OCP\Share_Backend', array($class));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $class), \OCP\Util::ERROR);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $class), ILogger::ERROR);
throw new \Exception($message_t);
}
return self::$backends[$itemType];
} else {
$message = 'Sharing backend %s not found';
$message_t = $l->t('Sharing backend %s not found', array($class));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $class), \OCP\Util::ERROR);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $class), ILogger::ERROR);
throw new \Exception($message_t);
}
}
$message = 'Sharing backend for %s not found';
$message_t = $l->t('Sharing backend for %s not found', array($itemType));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemType), \OCP\Util::ERROR);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemType), ILogger::ERROR);
throw new \Exception($message_t);
}
@@ -1038,7 +1012,7 @@ class Share extends Constants {
} else {
$itemTypes = $collectionTypes;
}
- $placeholders = join(',', array_fill(0, count($itemTypes), '?'));
+ $placeholders = implode(',', array_fill(0, count($itemTypes), '?'));
$where = ' WHERE `item_type` IN ('.$placeholders.'))';
$queryArgs = $itemTypes;
} else {
@@ -1064,7 +1038,7 @@ class Share extends Constants {
$groups = \OC::$server->getGroupManager()->getUserGroupIds($user);
}
if (!empty($groups)) {
- $placeholders = join(',', array_fill(0, count($groups), '?'));
+ $placeholders = implode(',', array_fill(0, count($groups), '?'));
$where .= ' OR (`share_type` = ? AND `share_with` IN ('.$placeholders.')) ';
$queryArgs[] = self::SHARE_TYPE_GROUP;
$queryArgs = array_merge($queryArgs, $groups);
@@ -1129,7 +1103,7 @@ class Share extends Constants {
}
$queryArgs[] = $item;
if ($includeCollections && $collectionTypes && !in_array('folder', $collectionTypes)) {
- $placeholders = join(',', array_fill(0, count($collectionTypes), '?'));
+ $placeholders = implode(',', array_fill(0, count($collectionTypes), '?'));
$where .= ' OR `item_type` IN ('.$placeholders.'))';
$queryArgs = array_merge($queryArgs, $collectionTypes);
}
@@ -1161,7 +1135,7 @@ class Share extends Constants {
if ($result === false) {
\OCP\Util::writeLog('OCP\Share',
\OC_DB::getErrorMessage() . ', select=' . $select . ' where=',
- \OCP\Util::ERROR);
+ ILogger::ERROR);
}
$items = array();
$targets = array();
@@ -1225,7 +1199,7 @@ class Share extends Constants {
if ($result === false) {
\OCP\Util::writeLog('OCP\Share', 'Can\'t select parent: ' .
\OC_DB::getErrorMessage() . ', select=' . $select . ' where=' . $where,
- \OCP\Util::ERROR);
+ ILogger::ERROR);
} else {
$parentRow = $parentResult->fetchRow();
$tmpPath = $parentRow['file_target'];
@@ -1266,7 +1240,8 @@ class Share extends Constants {
$row['share_with_displayname'] = $row['share_with'];
if ( isset($row['share_with']) && $row['share_with'] != '' &&
$row['share_type'] === self::SHARE_TYPE_USER) {
- $row['share_with_displayname'] = \OCP\User::getDisplayName($row['share_with']);
+ $shareWithUser = \OC::$server->getUserManager()->get($row['share_with']);
+ $row['share_with_displayname'] = $shareWithUser === null ? $row['share_with'] : $shareWithUser->getDisplayName();
} else if(isset($row['share_with']) && $row['share_with'] != '' &&
$row['share_type'] === self::SHARE_TYPE_REMOTE) {
$addressBookEntries = \OC::$server->getContactsManager()->search($row['share_with'], ['CLOUD']);
@@ -1279,7 +1254,8 @@ class Share extends Constants {
}
}
if ( isset($row['uid_owner']) && $row['uid_owner'] != '') {
- $row['displayname_owner'] = \OCP\User::getDisplayName($row['uid_owner']);
+ $ownerUser = \OC::$server->getUserManager()->get($row['uid_owner']);
+ $row['displayname_owner'] = $ownerUser === null ? $row['uid_owner'] : $ownerUser->getDisplayName();
}
if ($row['permissions'] > 0) {
@@ -1694,7 +1670,7 @@ class Share extends Constants {
$message = 'Sharing %s failed, because the user %s is the original sharer';
$message_t = $l->t('Sharing failed, because the user %s is the original sharer', [$shareWith]);
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $shareWith), ILogger::DEBUG);
throw new \Exception($message_t);
}
}
@@ -1706,7 +1682,7 @@ class Share extends Constants {
$message = 'Sharing %s failed, because the permissions exceed permissions granted to %s';
$message_t = $l->t('Sharing %s failed, because the permissions exceed permissions granted to %s', array($itemSourceName, $uidOwner));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $uidOwner), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName, $uidOwner), ILogger::DEBUG);
throw new \Exception($message_t);
} else {
// TODO Don't check if inside folder
@@ -1738,7 +1714,7 @@ class Share extends Constants {
$message = 'Sharing %s failed, because resharing is not allowed';
$message_t = $l->t('Sharing %s failed, because resharing is not allowed', array($itemSourceName));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSourceName), ILogger::DEBUG);
throw new \Exception($message_t);
}
} else {
@@ -1751,7 +1727,7 @@ class Share extends Constants {
$message = 'Sharing %s failed, because the sharing backend for '
.'%s could not find its source';
$message_t = $l->t('Sharing %s failed, because the sharing backend for %s could not find its source', array($itemSource, $itemType));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSource, $itemType), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSource, $itemType), ILogger::DEBUG);
throw new \Exception($message_t);
}
if ($backend instanceof \OCP\Share_Backend_File_Dependent) {
@@ -1766,7 +1742,7 @@ class Share extends Constants {
$message = 'Sharing %s failed, because the file could not be found in the file cache';
$message_t = $l->t('Sharing %s failed, because the file could not be found in the file cache', array($itemSource));
- \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSource), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemSource), ILogger::DEBUG);
throw new \Exception($message_t);
}
} else {
@@ -1996,7 +1972,22 @@ class Share extends Constants {
while ($result['success'] === false && $try < 2) {
$federationEndpoints = $discoveryService->discover($protocol . $remoteDomain, 'FEDERATED_SHARING');
$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
- $result = \OC::$server->getHTTPHelper()->post($protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, $fields);
+ $client = \OC::$server->getHTTPClientService()->newClient();
+
+ try {
+ $response = $client->post(
+ $protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT,
+ [
+ 'body' => $fields,
+ 'connect_timeout' => 10,
+ ]
+ );
+
+ $result = ['success' => true, 'result' => $response->getBody()];
+ } catch (\Exception $e) {
+ $result = ['success' => false, 'result' => $e->getMessage()];
+ }
+
$try++;
$protocol = 'http://';
}
diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php
index b9ab7a46873..5e52156d1d0 100644
--- a/lib/private/Share20/DefaultShareProvider.php
+++ b/lib/private/Share20/DefaultShareProvider.php
@@ -30,8 +30,8 @@
namespace OC\Share20;
use OC\Files\Cache\Cache;
-use OCP\Files\File;
use OCP\Files\Folder;
+use OCP\Share\IShare;
use OCP\Share\IShareProvider;
use OC\Share20\Exception\InvalidShare;
use OC\Share20\Exception\ProviderException;
@@ -413,6 +413,41 @@ class DefaultShareProvider implements IShareProvider {
/**
* @inheritdoc
+ *
+ * For now this only works for group shares
+ * If this gets implemented for normal shares we have to extend it
+ */
+ public function restore(IShare $share, string $recipient): IShare {
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->select('permissions')
+ ->from('share')
+ ->where(
+ $qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))
+ );
+ $cursor = $qb->execute();
+ $data = $cursor->fetch();
+ $cursor->closeCursor();
+
+ $originalPermission = $data['permissions'];
+
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->update('share')
+ ->set('permissions', $qb->createNamedParameter($originalPermission))
+ ->where(
+ $qb->expr()->eq('parent', $qb->createNamedParameter($share->getParent()))
+ )->andWhere(
+ $qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP))
+ )->andWhere(
+ $qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))
+ );
+
+ $qb->execute();
+
+ return $this->getShareById($share->getId(), $recipient);
+ }
+
+ /**
+ * @inheritdoc
*/
public function move(\OCP\Share\IShare $share, $recipient) {
if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) {
@@ -923,6 +958,7 @@ class DefaultShareProvider implements IShareProvider {
while($data = $stmt->fetch()) {
$shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
$shareMap[$data['parent']]->setTarget($data['file_target']);
+ $shareMap[$data['parent']]->setParent($data['parent']);
}
$stmt->closeCursor();
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index 0ae96f29ded..76b523afd10 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -61,6 +61,7 @@ use OCP\Share\Exceptions\GenericShareException;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager;
use OCP\Share\IProviderFactory;
+use OCP\Share\IShare;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\GenericEvent;
use OCP\Share\IShareProvider;
@@ -225,6 +226,10 @@ class Manager implements IManager {
if ($share->getSharedWith() === null) {
throw new \InvalidArgumentException('SharedWith should not be empty');
}
+ } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
+ if ($share->getSharedWith() === null) {
+ throw new \InvalidArgumentException('SharedWith should not be empty');
+ }
} else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_EMAIL) {
if ($share->getSharedWith() === null) {
throw new \InvalidArgumentException('SharedWith should not be empty');
@@ -735,7 +740,7 @@ class Manager implements IManager {
$text = $l->t('%s shared »%s« with you.', [$initiatorDisplayName, $filename]);
$emailTemplate->addBodyText(
- $text . ' ' . $l->t('Click the button below to open it.'),
+ htmlspecialchars($text . ' ' . $l->t('Click the button below to open it.')),
$text
);
$emailTemplate->addBodyButton(
@@ -978,6 +983,13 @@ class Manager implements IManager {
$this->eventDispatcher->dispatch('OCP\Share::postUnshareFromSelf', $event);
}
+ public function restoreShare(IShare $share, string $recipientId): IShare {
+ list($providerId, ) = $this->splitFullId($share->getFullId());
+ $provider = $this->factory->getProvider($providerId);
+
+ return $provider->restore($share, $recipientId);
+ }
+
/**
* @inheritdoc
*/
@@ -1124,6 +1136,25 @@ class Manager implements IManager {
/**
* @inheritdoc
*/
+ public function getDeletedSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0) {
+ $shares = $this->getSharedWith($userId, $shareType, $node, $limit, $offset);
+
+ // Only get deleted shares
+ $shares = array_filter($shares, function(IShare $share) {
+ return $share->getPermissions() === 0;
+ });
+
+ // Only get shares where the owner still exists
+ $shares = array_filter($shares, function (IShare $share) {
+ return $this->userManager->userExists($share->getShareOwner());
+ });
+
+ return $shares;
+ }
+
+ /**
+ * @inheritdoc
+ */
public function getShareById($id, $recipient = null) {
if ($id === null) {
throw new ShareNotFound();
@@ -1555,6 +1586,13 @@ class Manager implements IManager {
/**
* @inheritdoc
*/
+ public function outgoingServer2ServerGroupSharesAllowed() {
+ return $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no') === 'yes';
+ }
+
+ /**
+ * @inheritdoc
+ */
public function shareProviderExists($shareType) {
try {
$this->factory->getProviderForType($shareType);
diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php
index 3716189445f..e4d34146911 100644
--- a/lib/private/Share20/ProviderFactory.php
+++ b/lib/private/Share20/ProviderFactory.php
@@ -29,10 +29,10 @@
namespace OC\Share20;
use OC\CapabilitiesManager;
-use OC\GlobalScale\Config;
use OCA\FederatedFileSharing\AddressHandler;
use OCA\FederatedFileSharing\FederatedShareProvider;
use OCA\FederatedFileSharing\Notifications;
+use OCA\FederatedFileSharing\OCM\CloudFederationProvider;
use OCA\FederatedFileSharing\TokenHandler;
use OCA\ShareByMail\Settings\SettingsManager;
use OCA\ShareByMail\ShareByMailProvider;
@@ -116,7 +116,9 @@ class ProviderFactory implements IProviderFactory {
$addressHandler,
$this->serverContainer->getHTTPClientService(),
$this->serverContainer->query(\OCP\OCS\IDiscoveryService::class),
- $this->serverContainer->getJobList()
+ $this->serverContainer->getJobList(),
+ \OC::$server->getCloudFederationProviderManager(),
+ \OC::$server->getCloudFederationFactory()
);
$tokenHandler = new TokenHandler(
$this->serverContainer->getSecureRandom()
@@ -133,7 +135,8 @@ class ProviderFactory implements IProviderFactory {
$this->serverContainer->getConfig(),
$this->serverContainer->getUserManager(),
$this->serverContainer->getCloudIdManager(),
- $this->serverContainer->query(Config::class)
+ $this->serverContainer->getGlobalScaleConfig(),
+ $this->serverContainer->getCloudFederationProviderManager()
);
}
@@ -248,7 +251,7 @@ class ProviderFactory implements IProviderFactory {
$shareType === \OCP\Share::SHARE_TYPE_LINK
) {
$provider = $this->defaultShareProvider();
- } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE) {
+ } else if ($shareType === \OCP\Share::SHARE_TYPE_REMOTE || $shareType === \OCP\Share::SHARE_TYPE_REMOTE_GROUP) {
$provider = $this->federatedShareProvider();
} else if ($shareType === \OCP\Share::SHARE_TYPE_EMAIL) {
$provider = $this->getShareByMailProvider();
diff --git a/lib/private/Share20/Share.php b/lib/private/Share20/Share.php
index 1836d6708c5..d7810165dac 100644
--- a/lib/private/Share20/Share.php
+++ b/lib/private/Share20/Share.php
@@ -48,6 +48,10 @@ class Share implements \OCP\Share\IShare {
/** @var string */
private $sharedWith;
/** @var string */
+ private $sharedWithDisplayName;
+ /** @var string */
+ private $sharedWithAvatar;
+ /** @var string */
private $sharedBy;
/** @var string */
private $shareOwner;
@@ -254,6 +258,42 @@ class Share implements \OCP\Share\IShare {
/**
* @inheritdoc
*/
+ public function setSharedWithDisplayName($displayName) {
+ if (!is_string($displayName)) {
+ throw new \InvalidArgumentException();
+ }
+ $this->sharedWithDisplayName = $displayName;
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getSharedWithDisplayName() {
+ return $this->sharedWithDisplayName;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setSharedWithAvatar($src) {
+ if (!is_string($src)) {
+ throw new \InvalidArgumentException();
+ }
+ $this->sharedWithAvatar = $src;
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getSharedWithAvatar() {
+ return $this->sharedWithAvatar;
+ }
+
+ /**
+ * @inheritdoc
+ */
public function setPermissions($permissions) {
//TODO checkes
diff --git a/lib/private/Streamer.php b/lib/private/Streamer.php
index 7b178fda652..51c2c923c23 100644
--- a/lib/private/Streamer.php
+++ b/lib/private/Streamer.php
@@ -24,6 +24,7 @@
namespace OC;
+use OCP\IRequest;
use ownCloud\TarStreamer\TarStreamer;
use ZipStreamer\ZipStreamer;
@@ -33,12 +34,42 @@ class Streamer {
// streamer instance
private $streamerInstance;
-
- public function __construct(){
- /** @var \OCP\IRequest */
- $request = \OC::$server->getRequest();
-
- if ($request->isUserAgent($this->preferTarFor)) {
+
+ /**
+ * Streamer constructor.
+ *
+ * @param IRequest $request
+ * @param int $size The size of the files in bytes
+ * @param int $numberOfFiles The number of files (and directories) that will
+ * be included in the streamed file
+ */
+ public function __construct(IRequest $request, int $size, int $numberOfFiles){
+
+ /**
+ * zip32 constraints for a basic (without compression, volumes nor
+ * encryption) zip file according to the Zip specification:
+ * - No file size is larger than 4 bytes (file size < 4294967296); see
+ * 4.4.9 uncompressed size
+ * - The size of all files plus their local headers is not larger than
+ * 4 bytes; see 4.4.16 relative offset of local header and 4.4.24
+ * offset of start of central directory with respect to the starting
+ * disk number
+ * - The total number of entries (files and directories) in the zip file
+ * is not larger than 2 bytes (number of entries < 65536); see 4.4.22
+ * total number of entries in the central dir
+ * - The size of the central directory is not larger than 4 bytes; see
+ * 4.4.23 size of the central directory
+ *
+ * Due to all that, zip32 is used if the size is below 4GB and there are
+ * less than 65536 files; the margin between 4*1000^3 and 4*1024^3
+ * should give enough room for the extra zip metadata. Technically, it
+ * would still be possible to create an invalid zip32 file (for example,
+ * a zip file from files smaller than 4GB with a central directory
+ * larger than 4GiB), but it should not happen in the real world.
+ */
+ if ($size < 4 * 1000 * 1000 * 1000 && $numberOfFiles < 65536) {
+ $this->streamerInstance = new ZipStreamer(['zip64' => false]);
+ } else if ($request->isUserAgent($this->preferTarFor)) {
$this->streamerInstance = new TarStreamer();
} else {
$this->streamerInstance = new ZipStreamer(['zip64' => PHP_INT_SIZE !== 4]);
diff --git a/lib/private/SubAdmin.php b/lib/private/SubAdmin.php
index cd16d07e43d..44d79d8994e 100644
--- a/lib/private/SubAdmin.php
+++ b/lib/private/SubAdmin.php
@@ -62,7 +62,7 @@ class SubAdmin extends PublicEmitter {
$this->post_deleteUser($user);
});
$this->groupManager->listen('\OC\Group', 'postDelete', function($group) {
- $this->post_deleteGroup($group);
+ $this->post_deleteGroup($group);
});
}
@@ -123,7 +123,7 @@ class SubAdmin extends PublicEmitter {
while($row = $result->fetch()) {
$group = $this->groupManager->get($row['gid']);
if(!is_null($group)) {
- $groups[] = $group;
+ $groups[$group->getGID()] = $group;
}
}
$result->closeCursor();
@@ -132,6 +132,17 @@ class SubAdmin extends PublicEmitter {
}
/**
+ * get an array of groupid and displayName for a user
+ * @param IUser $user
+ * @return array ['displayName' => displayname]
+ */
+ public function getSubAdminsGroupsName(IUser $user) {
+ return array_map(function($group) {
+ return array('displayName' => $group->getDisplayName());
+ }, $this->getSubAdminsGroups($user));
+ }
+
+ /**
* get SubAdmins of a group
* @param IGroup $group the group
* @return IUser[]
@@ -185,7 +196,7 @@ class SubAdmin extends PublicEmitter {
/**
* checks if a user is a SubAdmin of a group
- * @param IUser $user
+ * @param IUser $user
* @param IGroup $group
* @return bool
*/
@@ -210,7 +221,7 @@ class SubAdmin extends PublicEmitter {
/**
* checks if a user is a SubAdmin
- * @param IUser $user
+ * @param IUser $user
* @return bool
*/
public function isSubAdmin(IUser $user) {
diff --git a/lib/private/SystemTag/ManagerFactory.php b/lib/private/SystemTag/ManagerFactory.php
index 12af2523f47..839a819a04a 100644
--- a/lib/private/SystemTag/ManagerFactory.php
+++ b/lib/private/SystemTag/ManagerFactory.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -57,7 +58,7 @@ class ManagerFactory implements ISystemTagManagerFactory {
* @return ISystemTagManager
* @since 9.0.0
*/
- public function getManager() {
+ public function getManager(): ISystemTagManager {
return new SystemTagManager(
$this->serverContainer->getDatabaseConnection(),
$this->serverContainer->getGroupManager(),
@@ -72,7 +73,7 @@ class ManagerFactory implements ISystemTagManagerFactory {
* @return ISystemTagObjectMapper
* @since 9.0.0
*/
- public function getObjectMapper() {
+ public function getObjectMapper(): ISystemTagObjectMapper {
return new SystemTagObjectMapper(
$this->serverContainer->getDatabaseConnection(),
$this->getManager(),
diff --git a/lib/private/SystemTag/SystemTag.php b/lib/private/SystemTag/SystemTag.php
index 15eb15efd9e..3b0cf23c9a8 100644
--- a/lib/private/SystemTag/SystemTag.php
+++ b/lib/private/SystemTag/SystemTag.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -55,7 +56,7 @@ class SystemTag implements ISystemTag {
* @param bool $userVisible whether the tag is user visible
* @param bool $userAssignable whether the tag is user assignable
*/
- public function __construct($id, $name, $userVisible, $userAssignable) {
+ public function __construct(string $id, string $name, bool $userVisible, bool $userAssignable) {
$this->id = $id;
$this->name = $name;
$this->userVisible = $userVisible;
@@ -65,28 +66,28 @@ class SystemTag implements ISystemTag {
/**
* {@inheritdoc}
*/
- public function getId() {
+ public function getId(): string {
return $this->id;
}
/**
* {@inheritdoc}
*/
- public function getName() {
+ public function getName(): string {
return $this->name;
}
/**
* {@inheritdoc}
*/
- public function isUserVisible() {
+ public function isUserVisible(): bool {
return $this->userVisible;
}
/**
* {@inheritdoc}
*/
- public function isUserAssignable() {
+ public function isUserAssignable(): bool {
return $this->userAssignable;
}
}
diff --git a/lib/private/SystemTag/SystemTagManager.php b/lib/private/SystemTag/SystemTagManager.php
index 642ce515801..055b744e5c3 100644
--- a/lib/private/SystemTag/SystemTagManager.php
+++ b/lib/private/SystemTag/SystemTagManager.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -65,6 +66,7 @@ class SystemTagManager implements ISystemTagManager {
* Constructor.
*
* @param IDBConnection $connection database connection
+ * @param IGroupManager $groupManager
* @param EventDispatcherInterface $dispatcher
*/
public function __construct(
@@ -87,8 +89,8 @@ class SystemTagManager implements ISystemTagManager {
/**
* {@inheritdoc}
*/
- public function getTagsByIds($tagIds) {
- if (!is_array($tagIds)) {
+ public function getTagsByIds($tagIds): array {
+ if (!\is_array($tagIds)) {
$tagIds = [$tagIds];
}
@@ -117,7 +119,7 @@ class SystemTagManager implements ISystemTagManager {
$result->closeCursor();
- if (count($tags) !== count($tagIds)) {
+ if (\count($tags) !== \count($tagIds)) {
throw new TagNotFoundException(
'Tag id(s) not found', 0, null, array_diff($tagIds, array_keys($tags))
);
@@ -129,14 +131,14 @@ class SystemTagManager implements ISystemTagManager {
/**
* {@inheritdoc}
*/
- public function getAllTags($visibilityFilter = null, $nameSearchPattern = null) {
+ public function getAllTags($visibilityFilter = null, $nameSearchPattern = null): array {
$tags = [];
$query = $this->connection->getQueryBuilder();
$query->select('*')
->from(self::TAG_TABLE);
- if (!is_null($visibilityFilter)) {
+ if (!\is_null($visibilityFilter)) {
$query->andWhere($query->expr()->eq('visibility', $query->createNamedParameter((int)$visibilityFilter)));
}
@@ -167,14 +169,11 @@ class SystemTagManager implements ISystemTagManager {
/**
* {@inheritdoc}
*/
- public function getTag($tagName, $userVisible, $userAssignable) {
- $userVisible = (int)$userVisible;
- $userAssignable = (int)$userAssignable;
-
+ public function getTag(string $tagName, bool $userVisible, bool $userAssignable): ISystemTag {
$result = $this->selectTagQuery
->setParameter('name', $tagName)
- ->setParameter('visibility', $userVisible)
- ->setParameter('editable', $userAssignable)
+ ->setParameter('visibility', $userVisible ? 1 : 0)
+ ->setParameter('editable', $userAssignable ? 1 : 0)
->execute();
$row = $result->fetch();
@@ -191,16 +190,13 @@ class SystemTagManager implements ISystemTagManager {
/**
* {@inheritdoc}
*/
- public function createTag($tagName, $userVisible, $userAssignable) {
- $userVisible = (int)$userVisible;
- $userAssignable = (int)$userAssignable;
-
+ public function createTag(string $tagName, bool $userVisible, bool $userAssignable): ISystemTag {
$query = $this->connection->getQueryBuilder();
$query->insert(self::TAG_TABLE)
->values([
'name' => $query->createNamedParameter($tagName),
- 'visibility' => $query->createNamedParameter($userVisible),
- 'editable' => $query->createNamedParameter($userAssignable),
+ 'visibility' => $query->createNamedParameter($userVisible ? 1 : 0),
+ 'editable' => $query->createNamedParameter($userAssignable ? 1 : 0),
]);
try {
@@ -216,10 +212,10 @@ class SystemTagManager implements ISystemTagManager {
$tagId = $query->getLastInsertId();
$tag = new SystemTag(
- (int)$tagId,
+ (string)$tagId,
$tagName,
- (bool)$userVisible,
- (bool)$userAssignable
+ $userVisible,
+ $userAssignable
);
$this->dispatcher->dispatch(ManagerEvent::EVENT_CREATE, new ManagerEvent(
@@ -232,10 +228,7 @@ class SystemTagManager implements ISystemTagManager {
/**
* {@inheritdoc}
*/
- public function updateTag($tagId, $tagName, $userVisible, $userAssignable) {
- $userVisible = (int)$userVisible;
- $userAssignable = (int)$userAssignable;
-
+ public function updateTag(string $tagId, string $tagName, bool $userVisible, bool $userAssignable) {
try {
$tags = $this->getTagsByIds($tagId);
} catch (TagNotFoundException $e) {
@@ -246,10 +239,10 @@ class SystemTagManager implements ISystemTagManager {
$beforeUpdate = array_shift($tags);
$afterUpdate = new SystemTag(
- (int) $tagId,
+ $tagId,
$tagName,
- (bool) $userVisible,
- (bool) $userAssignable
+ $userVisible,
+ $userAssignable
);
$query = $this->connection->getQueryBuilder();
@@ -259,8 +252,8 @@ class SystemTagManager implements ISystemTagManager {
->set('editable', $query->createParameter('editable'))
->where($query->expr()->eq('id', $query->createParameter('tagid')))
->setParameter('name', $tagName)
- ->setParameter('visibility', $userVisible)
- ->setParameter('editable', $userAssignable)
+ ->setParameter('visibility', $userVisible ? 1 : 0)
+ ->setParameter('editable', $userAssignable ? 1 : 0)
->setParameter('tagid', $tagId);
try {
@@ -286,7 +279,7 @@ class SystemTagManager implements ISystemTagManager {
* {@inheritdoc}
*/
public function deleteTags($tagIds) {
- if (!is_array($tagIds)) {
+ if (!\is_array($tagIds)) {
$tagIds = [$tagIds];
}
@@ -337,7 +330,7 @@ class SystemTagManager implements ISystemTagManager {
/**
* {@inheritdoc}
*/
- public function canUserAssignTag(ISystemTag $tag, IUser $user) {
+ public function canUserAssignTag(ISystemTag $tag, IUser $user): bool {
// early check to avoid unneeded group lookups
if ($tag->isUserAssignable() && $tag->isUserVisible()) {
return true;
@@ -365,7 +358,7 @@ class SystemTagManager implements ISystemTagManager {
/**
* {@inheritdoc}
*/
- public function canUserSeeTag(ISystemTag $tag, IUser $user) {
+ public function canUserSeeTag(ISystemTag $tag, IUser $user): bool {
if ($tag->isUserVisible()) {
return true;
}
@@ -378,13 +371,13 @@ class SystemTagManager implements ISystemTagManager {
}
private function createSystemTagFromRow($row) {
- return new SystemTag((int)$row['id'], $row['name'], (bool)$row['visibility'], (bool)$row['editable']);
+ return new SystemTag((string)$row['id'], $row['name'], (bool)$row['visibility'], (bool)$row['editable']);
}
/**
* {@inheritdoc}
*/
- public function setTagGroups(ISystemTag $tag, $groupIds) {
+ public function setTagGroups(ISystemTag $tag, array $groupIds) {
// delete relationships first
$this->connection->beginTransaction();
try {
@@ -418,7 +411,7 @@ class SystemTagManager implements ISystemTagManager {
/**
* {@inheritdoc}
*/
- public function getTagGroups(ISystemTag $tag) {
+ public function getTagGroups(ISystemTag $tag): array {
$groupIds = [];
$query = $this->connection->getQueryBuilder();
$query->select('gid')
diff --git a/lib/private/SystemTag/SystemTagObjectMapper.php b/lib/private/SystemTag/SystemTagObjectMapper.php
index 75bf37c652c..8ecc46b4357 100644
--- a/lib/private/SystemTag/SystemTagObjectMapper.php
+++ b/lib/private/SystemTag/SystemTagObjectMapper.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -63,8 +64,8 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
/**
* {@inheritdoc}
*/
- public function getTagIdsForObjects($objIds, $objectType) {
- if (!is_array($objIds)) {
+ public function getTagIdsForObjects($objIds, string $objectType): array {
+ if (!\is_array($objIds)) {
$objIds = [$objIds];
} else if (empty($objIds)) {
return [];
@@ -99,8 +100,8 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
/**
* {@inheritdoc}
*/
- public function getObjectIdsForTags($tagIds, $objectType, $limit = 0, $offset = '') {
- if (!is_array($tagIds)) {
+ public function getObjectIdsForTags($tagIds, string $objectType, int $limit = 0, string $offset = ''): array {
+ if (!\is_array($tagIds)) {
$tagIds = [$tagIds];
}
@@ -113,7 +114,7 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
->andWhere($query->expr()->eq('objecttype', $query->createNamedParameter($objectType)));
if ($limit) {
- if (count($tagIds) !== 1) {
+ if (\count($tagIds) !== 1) {
throw new \InvalidArgumentException('Limit is only allowed with a single tag');
}
@@ -138,8 +139,8 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
/**
* {@inheritdoc}
*/
- public function assignTags($objId, $objectType, $tagIds) {
- if (!is_array($tagIds)) {
+ public function assignTags(string $objId, string $objectType, $tagIds) {
+ if (!\is_array($tagIds)) {
$tagIds = [$tagIds];
}
@@ -173,8 +174,8 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
/**
* {@inheritdoc}
*/
- public function unassignTags($objId, $objectType, $tagIds) {
- if (!is_array($tagIds)) {
+ public function unassignTags(string $objId, string $objectType, $tagIds) {
+ if (!\is_array($tagIds)) {
$tagIds = [$tagIds];
}
@@ -201,10 +202,10 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
/**
* {@inheritdoc}
*/
- public function haveTag($objIds, $objectType, $tagId, $all = true) {
+ public function haveTag($objIds, string $objectType, string $tagId, bool $all = true): bool {
$this->assertTagsExist([$tagId]);
- if (!is_array($objIds)) {
+ if (!\is_array($objIds)) {
$objIds = [$objIds];
}
@@ -232,10 +233,10 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
$result->closeCursor();
if ($all) {
- return ((int)$row[0] === count($objIds));
- } else {
- return (bool) $row;
+ return ((int)$row[0] === \count($objIds));
}
+
+ return (bool) $row;
}
/**
@@ -247,7 +248,7 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper {
*/
private function assertTagsExist($tagIds) {
$tags = $this->tagManager->getTagsByIds($tagIds);
- if (count($tags) !== count($tagIds)) {
+ if (\count($tags) !== \count($tagIds)) {
// at least one tag missing, bail out
$foundTagIds = array_map(
function(ISystemTag $tag) {
diff --git a/lib/private/Tags.php b/lib/private/Tags.php
index 1b3505da5bd..10c9affa277 100644
--- a/lib/private/Tags.php
+++ b/lib/private/Tags.php
@@ -47,6 +47,7 @@ namespace OC;
use OC\Tagging\Tag;
use OC\Tagging\TagMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\ILogger;
class Tags implements \OCP\ITags {
@@ -236,15 +237,15 @@ class Tags implements \OCP\ITags {
}
$entries[$objId][] = $row['category'];
}
- if (\OCP\DB::isError($result)) {
- \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage(), \OCP\Util::ERROR);
+ if ($result === null) {
+ \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
return false;
}
}
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return false;
@@ -270,7 +271,7 @@ class Tags implements \OCP\ITags {
} elseif(is_string($tag)) {
$tag = trim($tag);
if($tag === '') {
- \OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', ILogger::DEBUG);
return false;
}
$tagId = $this->getTagId($tag);
@@ -288,16 +289,16 @@ class Tags implements \OCP\ITags {
. '` WHERE `categoryid` = ?';
try {
- $stmt = \OCP\DB::prepare($sql);
+ $stmt = \OC_DB::prepare($sql);
$result = $stmt->execute(array($tagId));
- if (\OCP\DB::isError($result)) {
- \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage(), \OCP\Util::ERROR);
+ if ($result === null) {
+ \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
return false;
}
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return false;
@@ -360,11 +361,11 @@ class Tags implements \OCP\ITags {
$name = trim($name);
if($name === '') {
- \OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
return false;
}
if($this->userHasTag($name, $this->user)) {
- \OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', ILogger::DEBUG);
return false;
}
try {
@@ -374,12 +375,12 @@ class Tags implements \OCP\ITags {
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return false;
}
- \OCP\Util::writeLog('core', __METHOD__.', id: ' . $tag->getId(), \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', __METHOD__.', id: ' . $tag->getId(), ILogger::DEBUG);
return $tag->getId();
}
@@ -395,7 +396,7 @@ class Tags implements \OCP\ITags {
$to = trim($to);
if($to === '' || $from === '') {
- \OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', ILogger::DEBUG);
return false;
}
@@ -405,13 +406,13 @@ class Tags implements \OCP\ITags {
$key = $this->getTagByName($from);
}
if($key === false) {
- \OCP\Util::writeLog('core', __METHOD__.', tag: ' . $from. ' does not exist', \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', __METHOD__.', tag: ' . $from. ' does not exist', ILogger::DEBUG);
return false;
}
$tag = $this->tags[$key];
if($this->userHasTag($to, $tag->getOwner())) {
- \OCP\Util::writeLog('core', __METHOD__.', A tag named ' . $to. ' already exists for user ' . $tag->getOwner() . '.', \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', __METHOD__.', A tag named ' . $to. ' already exists for user ' . $tag->getOwner() . '.', ILogger::DEBUG);
return false;
}
@@ -421,7 +422,7 @@ class Tags implements \OCP\ITags {
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return false;
@@ -476,7 +477,7 @@ class Tags implements \OCP\ITags {
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
}
@@ -485,18 +486,19 @@ class Tags implements \OCP\ITags {
// reload tags to get the proper ids.
$this->tags = $this->mapper->loadTags($this->owners, $this->type);
\OCP\Util::writeLog('core', __METHOD__.', tags: ' . print_r($this->tags, true),
- \OCP\Util::DEBUG);
+ ILogger::DEBUG);
// Loop through temporarily cached objectid/tagname pairs
// and save relations.
$tags = $this->tags;
// For some reason this is needed or array_search(i) will return 0..?
ksort($tags);
+ $dbConnection = \OC::$server->getDatabaseConnection();
foreach(self::$relations as $relation) {
$tagId = $this->getTagId($relation['tag']);
- \OCP\Util::writeLog('core', __METHOD__ . 'catid, ' . $relation['tag'] . ' ' . $tagId, \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', __METHOD__ . 'catid, ' . $relation['tag'] . ' ' . $tagId, ILogger::DEBUG);
if($tagId) {
try {
- \OCP\DB::insertIfNotExist(self::RELATION_TABLE,
+ $dbConnection->insertIfNotExist(self::RELATION_TABLE,
array(
'objid' => $relation['objid'],
'categoryid' => $tagId,
@@ -505,7 +507,7 @@ class Tags implements \OCP\ITags {
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
}
@@ -514,7 +516,7 @@ class Tags implements \OCP\ITags {
self::$relations = array(); // reset
} else {
\OCP\Util::writeLog('core', __METHOD__.', $this->tags is not an array! '
- . print_r($this->tags, true), \OCP\Util::ERROR);
+ . print_r($this->tags, true), ILogger::ERROR);
}
}
@@ -529,23 +531,23 @@ class Tags implements \OCP\ITags {
// Find all objectid/tagId pairs.
$result = null;
try {
- $stmt = \OCP\DB::prepare('SELECT `id` FROM `' . self::TAG_TABLE . '` '
+ $stmt = \OC_DB::prepare('SELECT `id` FROM `' . self::TAG_TABLE . '` '
. 'WHERE `uid` = ?');
$result = $stmt->execute(array($arguments['uid']));
- if (\OCP\DB::isError($result)) {
- \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage(), \OCP\Util::ERROR);
+ if ($result === null) {
+ \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
}
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
}
if(!is_null($result)) {
try {
- $stmt = \OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
+ $stmt = \OC_DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
. 'WHERE `categoryid` = ?');
while( $row = $result->fetchRow()) {
try {
@@ -553,7 +555,7 @@ class Tags implements \OCP\ITags {
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
}
@@ -561,22 +563,22 @@ class Tags implements \OCP\ITags {
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
}
}
try {
- $stmt = \OCP\DB::prepare('DELETE FROM `' . self::TAG_TABLE . '` '
+ $stmt = \OC_DB::prepare('DELETE FROM `' . self::TAG_TABLE . '` '
. 'WHERE `uid` = ?');
$result = $stmt->execute(array($arguments['uid']));
- if (\OCP\DB::isError($result)) {
- \OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OCP\DB::getErrorMessage(), \OCP\Util::ERROR);
+ if ($result === null) {
+ \OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
}
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
}
@@ -599,16 +601,16 @@ class Tags implements \OCP\ITags {
$query .= 'WHERE `objid` IN (' . str_repeat('?,', count($ids)-1) . '?) ';
$query .= 'AND `type`= ?';
$updates[] = $this->type;
- $stmt = \OCP\DB::prepare($query);
+ $stmt = \OC_DB::prepare($query);
$result = $stmt->execute($updates);
- if (\OCP\DB::isError($result)) {
- \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage(), \OCP\Util::ERROR);
+ if ($result === null) {
+ \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
return false;
}
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return false;
@@ -627,7 +629,7 @@ class Tags implements \OCP\ITags {
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return array();
@@ -668,7 +670,7 @@ class Tags implements \OCP\ITags {
if(is_string($tag) && !is_numeric($tag)) {
$tag = trim($tag);
if($tag === '') {
- \OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
return false;
}
if(!$this->hasTag($tag)) {
@@ -679,7 +681,7 @@ class Tags implements \OCP\ITags {
$tagId = $tag;
}
try {
- \OCP\DB::insertIfNotExist(self::RELATION_TABLE,
+ \OC::$server->getDatabaseConnection()->insertIfNotExist(self::RELATION_TABLE,
array(
'objid' => $objid,
'categoryid' => $tagId,
@@ -688,7 +690,7 @@ class Tags implements \OCP\ITags {
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return false;
@@ -707,7 +709,7 @@ class Tags implements \OCP\ITags {
if(is_string($tag) && !is_numeric($tag)) {
$tag = trim($tag);
if($tag === '') {
- \OCP\Util::writeLog('core', __METHOD__.', Tag name is empty', \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', __METHOD__.', Tag name is empty', ILogger::DEBUG);
return false;
}
$tagId = $this->getTagId($tag);
@@ -718,12 +720,12 @@ class Tags implements \OCP\ITags {
try {
$sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
. 'WHERE `objid` = ? AND `categoryid` = ? AND `type` = ?';
- $stmt = \OCP\DB::prepare($sql);
+ $stmt = \OC_DB::prepare($sql);
$stmt->execute(array($objid, $tagId, $this->type));
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return false;
@@ -746,7 +748,7 @@ class Tags implements \OCP\ITags {
array_filter($names);
\OCP\Util::writeLog('core', __METHOD__ . ', before: '
- . print_r($this->tags, true), \OCP\Util::DEBUG);
+ . print_r($this->tags, true), ILogger::DEBUG);
foreach($names as $name) {
$id = null;
@@ -762,24 +764,24 @@ class Tags implements \OCP\ITags {
$this->mapper->delete($tag);
} else {
\OCP\Util::writeLog('core', __METHOD__ . 'Cannot delete tag ' . $name
- . ': not found.', \OCP\Util::ERROR);
+ . ': not found.', ILogger::ERROR);
}
if(!is_null($id) && $id !== false) {
try {
$sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
. 'WHERE `categoryid` = ?';
- $stmt = \OCP\DB::prepare($sql);
+ $stmt = \OC_DB::prepare($sql);
$result = $stmt->execute(array($id));
- if (\OCP\DB::isError($result)) {
+ if ($result === null) {
\OCP\Util::writeLog('core',
- __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage(),
- \OCP\Util::ERROR);
+ __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(),
+ ILogger::ERROR);
return false;
}
} catch(\Exception $e) {
\OC::$server->getLogger()->logException($e, [
'message' => __METHOD__,
- 'level' => \OCP\Util::ERROR,
+ 'level' => ILogger::ERROR,
'app' => 'core',
]);
return false;
diff --git a/lib/private/Template/Base.php b/lib/private/Template/Base.php
index 18cf6324089..09be5ab7ddf 100644
--- a/lib/private/Template/Base.php
+++ b/lib/private/Template/Base.php
@@ -166,8 +166,11 @@ class Base {
$l = $this->l10n;
$theme = $this->theme;
- if( !is_null($additionalParams)) {
+ if(!is_null($additionalParams)) {
$_ = array_merge( $additionalParams, $this->vars );
+ foreach ($_ as $var => $value) {
+ ${$var} = $value;
+ }
}
// Include
diff --git a/lib/private/Template/IconsCacher.php b/lib/private/Template/IconsCacher.php
new file mode 100644
index 00000000000..c262d26654f
--- /dev/null
+++ b/lib/private/Template/IconsCacher.php
@@ -0,0 +1,147 @@
+<?php
+declare (strict_types = 1);
+/**
+ * @copyright Copyright (c) 2018, John Molakvoæ (skjnldsv@protonmail.com)
+ *
+ * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Template;
+
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+use OCP\Files\SimpleFS\ISimpleFolder;
+use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\ILogger;
+use OCP\IURLGenerator;
+use OC\Files\AppData\Factory;
+
+class IconsCacher {
+
+ /** @var ILogger */
+ protected $logger;
+
+ /** @var IAppData */
+ protected $appData;
+
+ /** @var ISimpleFolder */
+ private $folder;
+
+ /** @var IURLGenerator */
+ protected $urlGenerator;
+
+ /** @var string */
+ private $iconVarRE = '/--(icon-[a-z0-9-]+): url\(["\']([a-z0-9-_\~\/\?\&\=\.]+)[^;]+;/m';
+
+ /** @var string */
+ private $fileName = 'icons-vars.css';
+
+ /**
+ * @param ILogger $logger
+ * @param Factory $appDataFactory
+ * @param IURLGenerator $urlGenerator
+ */
+ public function __construct(ILogger $logger,
+ Factory $appDataFactory,
+ IURLGenerator $urlGenerator) {
+ $this->logger = $logger;
+ $this->appData = $appDataFactory->get('css');
+ $this->urlGenerator = $urlGenerator;
+
+ try {
+ $this->folder = $this->appData->getFolder('icons');
+ } catch (NotFoundException $e) {
+ $this->folder = $this->appData->newFolder('icons');
+ }
+ }
+
+ private function getIconsFromCss(string $css): array{
+ preg_match_all($this->iconVarRE, $css, $matches, PREG_SET_ORDER);
+ $icons = [];
+ foreach ($matches as $icon) {
+ $icons[$icon[1]] = $icon[2];
+ }
+
+ return $icons;
+ }
+ /**
+ * Parse and cache css
+ *
+ * @param string $css
+ */
+ public function setIconsCss(string $css) {
+
+ $cachedFile = $this->getCachedCSS();
+ if (!$cachedFile) {
+ $currentData = '';
+ } else {
+ $currentData = $cachedFile->getContent();
+ }
+
+ // remove :root
+ $currentData = str_replace([':root {', '}'], '', $currentData);
+
+ $icons = $this->getIconsFromCss($currentData . $css);
+
+ $data = '';
+ foreach ($icons as $icon => $url) {
+ $data .= "--$icon: url('$url?v=1');";
+ }
+
+ if (strlen($data) > 0) {
+ if (!$cachedFile) {
+ $cachedFile = $this->folder->newFile($this->fileName);
+ }
+
+ $data = ":root {
+ $data
+ }";
+ $cachedFile->putContent($data);
+ }
+
+ return preg_replace($this->iconVarRE, '', $css);
+ }
+
+ /**
+ * Get icons css file
+ * @return ISimpleFile|boolean
+ */
+ public function getCachedCSS() {
+ try {
+ return $this->folder->getFile($this->fileName);
+ } catch (NotFoundException $e) {
+ return false;
+ }
+ }
+
+ public function injectCss() {
+ // Only inject once
+ foreach (\OC_Util::$headers as $header) {
+ if (
+ array_key_exists('attributes', $header) &&
+ array_key_exists('href', $header['attributes']) &&
+ strpos($header['attributes']['href'], $this->fileName) !== false) {
+ return;
+ }
+ }
+ $linkToCSS = substr($this->urlGenerator->linkToRoute('core.Css.getCss', ['appName' => 'icons', 'fileName' => $this->fileName]), strlen(\OC::$WEBROOT));
+ \OC_Util::addHeader('link', ['rel' => 'stylesheet', 'href' => $linkToCSS], null, true);
+ }
+
+} \ No newline at end of file
diff --git a/lib/private/Template/JSCombiner.php b/lib/private/Template/JSCombiner.php
index c5adcee6854..93683753899 100644
--- a/lib/private/Template/JSCombiner.php
+++ b/lib/private/Template/JSCombiner.php
@@ -30,6 +30,7 @@ use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFolder;
+use OCP\ICacheFactory;
use OCP\ILogger;
use OCP\IURLGenerator;
@@ -50,21 +51,25 @@ class JSCombiner {
/** @var ILogger */
protected $logger;
+ /** @var ICacheFactory */
+ private $cacheFactory;
+
/**
* @param IAppData $appData
* @param IURLGenerator $urlGenerator
- * @param ICache $depsCache
+ * @param ICacheFactory $cacheFactory
* @param SystemConfig $config
* @param ILogger $logger
*/
public function __construct(IAppData $appData,
IURLGenerator $urlGenerator,
- ICache $depsCache,
+ ICacheFactory $cacheFactory,
SystemConfig $config,
ILogger $logger) {
$this->appData = $appData;
$this->urlGenerator = $urlGenerator;
- $this->depsCache = $depsCache;
+ $this->cacheFactory = $cacheFactory;
+ $this->depsCache = $this->cacheFactory->createDistributed('JS-' . md5($this->urlGenerator->getBaseUrl()));
$this->config = $config;
$this->logger = $logger;
}
@@ -104,13 +109,20 @@ class JSCombiner {
* @return bool
*/
protected function isCached($fileName, ISimpleFolder $folder) {
- $fileName = str_replace('.json', '.js', $fileName) . '.deps';
+ $fileName = str_replace('.json', '.js', $fileName);
+
+ if (!$folder->fileExists($fileName)) {
+ return false;
+ }
+
+ $fileName = $fileName . '.deps';
try {
$deps = $this->depsCache->get($folder->getName() . '-' . $fileName);
if ($deps === null || $deps === '') {
$depFile = $folder->getFile($fileName);
$deps = $depFile->getContent();
}
+
// check again
if ($deps === null || $deps === '') {
$this->logger->info('JSCombiner: deps file empty: ' . $fileName);
@@ -236,7 +248,7 @@ class JSCombiner {
* @throws NotFoundException
*/
public function resetCache() {
- $this->depsCache->clear();
+ $this->cacheFactory->createDistributed('JS-')->clear();
$appDirectory = $this->appData->getDirectoryListing();
foreach ($appDirectory as $folder) {
foreach ($folder->getDirectoryListing() as $file) {
diff --git a/lib/private/Template/JSConfigHelper.php b/lib/private/Template/JSConfigHelper.php
index b8bff074200..b691a8a64cb 100644
--- a/lib/private/Template/JSConfigHelper.php
+++ b/lib/private/Template/JSConfigHelper.php
@@ -28,6 +28,7 @@
namespace OC\Template;
use bantu\IniGetWrapper\IniGetWrapper;
+use OC\CapabilitiesManager;
use OCP\App\IAppManager;
use OCP\Defaults;
use OCP\IConfig;
@@ -66,6 +67,9 @@ class JSConfigHelper {
/** @var IURLGenerator */
private $urlGenerator;
+ /** @var CapabilitiesManager */
+ private $capabilitiesManager;
+
/**
* @param IL10N $l
* @param Defaults $defaults
@@ -76,6 +80,7 @@ class JSConfigHelper {
* @param IGroupManager $groupManager
* @param IniGetWrapper $iniWrapper
* @param IURLGenerator $urlGenerator
+ * @param CapabilitiesManager $capabilitiesManager
*/
public function __construct(IL10N $l,
Defaults $defaults,
@@ -85,7 +90,8 @@ class JSConfigHelper {
IConfig $config,
IGroupManager $groupManager,
IniGetWrapper $iniWrapper,
- IURLGenerator $urlGenerator) {
+ IURLGenerator $urlGenerator,
+ CapabilitiesManager $capabilitiesManager) {
$this->l = $l;
$this->defaults = $defaults;
$this->appManager = $appManager;
@@ -95,6 +101,7 @@ class JSConfigHelper {
$this->groupManager = $groupManager;
$this->iniWrapper = $iniWrapper;
$this->urlGenerator = $urlGenerator;
+ $this->capabilitiesManager = $capabilitiesManager;
}
public function getConfig() {
@@ -146,6 +153,8 @@ class JSConfigHelper {
$lastConfirmTimestamp = 0;
}
+ $capabilities = $this->capabilitiesManager->getCapabilities();
+
$array = [
"oc_debug" => $this->config->getSystemValue('debug', false) ? 'true' : 'false',
"oc_isadmin" => $this->groupManager->isAdmin($uid) ? 'true' : 'false',
@@ -252,6 +261,7 @@ class JSConfigHelper {
'longFooter' => $this->defaults->getLongFooter(),
'folder' => \OC_Util::getTheme(),
]),
+ "oc_capabilities" => json_encode($capabilities),
];
if ($this->currentUser !== null) {
diff --git a/lib/private/Template/SCSSCacher.php b/lib/private/Template/SCSSCacher.php
index 433d5e5d0bf..9dcedb94daf 100644
--- a/lib/private/Template/SCSSCacher.php
+++ b/lib/private/Template/SCSSCacher.php
@@ -32,16 +32,18 @@ use Leafo\ScssPhp\Compiler;
use Leafo\ScssPhp\Exception\ParserException;
use Leafo\ScssPhp\Formatter\Crunched;
use Leafo\ScssPhp\Formatter\Expanded;
-use OC\Files\AppData\Factory;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\SimpleFS\ISimpleFolder;
use OCP\ICache;
+use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\ILogger;
use OCP\IURLGenerator;
+use OC\Files\AppData\Factory;
+use OC\Template\IconsCacher;
class SCSSCacher {
@@ -69,6 +71,12 @@ class SCSSCacher {
/** @var null|string */
private $injectedVariables;
+ /** @var ICacheFactory */
+ private $cacheFactory;
+
+ /** @var IconsCacher */
+ private $iconsCacher;
+
/**
* @param ILogger $logger
* @param Factory $appDataFactory
@@ -76,7 +84,8 @@ class SCSSCacher {
* @param IConfig $config
* @param \OC_Defaults $defaults
* @param string $serverRoot
- * @param ICache $depsCache
+ * @param ICacheFactory $cacheFactory
+ * @param IconsCacher $iconsCacher
*/
public function __construct(ILogger $logger,
Factory $appDataFactory,
@@ -84,14 +93,17 @@ class SCSSCacher {
IConfig $config,
\OC_Defaults $defaults,
$serverRoot,
- ICache $depsCache) {
- $this->logger = $logger;
- $this->appData = $appDataFactory->get('css');
+ ICacheFactory $cacheFactory,
+ IconsCacher $iconsCacher) {
+ $this->logger = $logger;
+ $this->appData = $appDataFactory->get('css');
$this->urlGenerator = $urlGenerator;
- $this->config = $config;
- $this->defaults = $defaults;
- $this->serverRoot = $serverRoot;
- $this->depsCache = $depsCache;
+ $this->config = $config;
+ $this->defaults = $defaults;
+ $this->serverRoot = $serverRoot;
+ $this->cacheFactory = $cacheFactory;
+ $this->depsCache = $cacheFactory->createDistributed('SCSS-' . md5($this->urlGenerator->getBaseUrl()));
+ $this->iconsCacher = $iconsCacher;
}
/**
@@ -107,23 +119,34 @@ class SCSSCacher {
$path = explode('/', $root . '/' . $file);
$fileNameSCSS = array_pop($path);
- $fileNameCSS = $this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS));
+ $fileNameCSS = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS)), $app);
- $path = implode('/', $path);
+ $path = implode('/', $path);
$webDir = $this->getWebDir($path, $app, $this->serverRoot, \OC::$WEBROOT);
try {
$folder = $this->appData->getFolder($app);
- } catch(NotFoundException $e) {
+ } catch (NotFoundException $e) {
// creating css appdata folder
$folder = $this->appData->newFolder($app);
}
-
- if(!$this->variablesChanged() && $this->isCached($fileNameCSS, $folder)) {
+ if (!$this->variablesChanged() && $this->isCached($fileNameCSS, $folder)) {
+ // Inject icons vars css if any
+ if ($this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) {
+ $this->iconsCacher->injectCss();
+ }
return true;
}
- return $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
+
+ $cached = $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
+
+ // Inject icons vars css if any
+ if ($this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) {
+ $this->iconsCacher->injectCss();
+ }
+
+ return $cached;
}
/**
@@ -132,8 +155,10 @@ class SCSSCacher {
* @return ISimpleFile
*/
public function getCachedCSS(string $appName, string $fileName): ISimpleFile {
- $folder = $this->appData->getFolder($appName);
- return $folder->getFile($this->prependBaseurlPrefix($fileName));
+ $folder = $this->appData->getFolder($appName);
+ $cachedFileName = $this->prependVersionPrefix($this->prependBaseurlPrefix($fileName), $appName);
+
+ return $folder->getFile($cachedFileName);
}
/**
@@ -147,24 +172,26 @@ class SCSSCacher {
$cachedFile = $folder->getFile($fileNameCSS);
if ($cachedFile->getSize() > 0) {
$depFileName = $fileNameCSS . '.deps';
- $deps = $this->depsCache->get($folder->getName() . '-' . $depFileName);
+ $deps = $this->depsCache->get($folder->getName() . '-' . $depFileName);
if ($deps === null) {
$depFile = $folder->getFile($depFileName);
- $deps = $depFile->getContent();
+ $deps = $depFile->getContent();
//Set to memcache for next run
$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
}
$deps = json_decode($deps, true);
- foreach ((array)$deps as $file=>$mtime) {
+ foreach ((array) $deps as $file => $mtime) {
if (!file_exists($file) || filemtime($file) > $mtime) {
return false;
}
}
+
return true;
}
+
return false;
- } catch(NotFoundException $e) {
+ } catch (NotFoundException $e) {
return false;
}
}
@@ -175,11 +202,13 @@ class SCSSCacher {
*/
private function variablesChanged(): bool {
$injectedVariables = $this->getInjectedVariables();
- if($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) {
+ if ($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) {
$this->resetCache();
$this->config->setAppValue('core', 'scss.variables', md5($injectedVariables));
+
return true;
}
+
return false;
}
@@ -198,11 +227,12 @@ class SCSSCacher {
$scss = new Compiler();
$scss->setImportPaths([
$path,
- $this->serverRoot . '/core/css/',
+ $this->serverRoot . '/core/css/'
]);
+
// Continue after throw
$scss->setIgnoreErrors(true);
- if($this->config->getSystemValue('debug')) {
+ if ($this->config->getSystemValue('debug')) {
// Debug mode
$scss->setFormatter(Expanded::class);
$scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
@@ -213,7 +243,7 @@ class SCSSCacher {
try {
$cachedfile = $folder->getFile($fileNameCSS);
- } catch(NotFoundException $e) {
+ } catch (NotFoundException $e) {
$cachedfile = $folder->newFile($fileNameCSS);
}
@@ -227,14 +257,20 @@ class SCSSCacher {
// Compile
try {
$compiledScss = $scss->compile(
+ '$webroot: \'' . $this->getRoutePrefix() . '\';' .
'@import "variables.scss";' .
+ '@import "functions.scss";' .
$this->getInjectedVariables() .
- '@import "'.$fileNameSCSS.'";');
- } catch(ParserException $e) {
+ '@import "' . $fileNameSCSS . '";');
+ } catch (ParserException $e) {
$this->logger->error($e, ['app' => 'core']);
+
return false;
}
+ // Parse Icons and create related css variables
+ $compiledScss = $this->iconsCacher->setIconsCss($compiledScss);
+
// Gzip file
try {
$gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
@@ -249,10 +285,12 @@ class SCSSCacher {
$depFile->putContent($deps);
$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
$gzipFile->putContent(gzencode($data, 9));
- $this->logger->debug('SCSSCacher: '.$webDir.'/'.$fileNameSCSS.' compiled and successfully cached', ['app' => 'core']);
+ $this->logger->debug('SCSSCacher: ' . $webDir . '/' . $fileNameSCSS . ' compiled and successfully cached', ['app' => 'core']);
+
return true;
- } catch(NotPermittedException $e) {
+ } catch (NotPermittedException $e) {
$this->logger->error('SCSSCacher: unable to cache: ' . $fileNameSCSS);
+
return false;
}
}
@@ -263,11 +301,15 @@ class SCSSCacher {
*/
public function resetCache() {
$this->injectedVariables = null;
- $this->depsCache->clear();
+ $this->cacheFactory->createDistributed('SCSS-')->clear();
$appDirectory = $this->appData->getDirectoryListing();
foreach ($appDirectory as $folder) {
foreach ($folder->getDirectoryListing() as $file) {
- $file->delete();
+ try {
+ $file->delete();
+ } catch (NotPermittedException $e) {
+ $this->logger->logException($e, ['message' => 'SCSSCacher: unable to delete file: ' . $file->getName()]);
+ }
}
}
}
@@ -303,8 +345,9 @@ class SCSSCacher {
* @return string
*/
private function rebaseUrls(string $css, string $webDir): string {
- $re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
- $subst = 'url(\''.$webDir.'/$1\')';
+ $re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
+ $subst = 'url(\'' . $webDir . '/$1\')';
+
return preg_replace($re, $subst, $css);
}
@@ -316,20 +359,44 @@ class SCSSCacher {
*/
public function getCachedSCSS(string $appName, string $fileName): string {
$tmpfileLoc = explode('/', $fileName);
- $fileName = array_pop($tmpfileLoc);
- $fileName = $this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName));
+ $fileName = array_pop($tmpfileLoc);
+ $fileName = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName)), $appName);
return substr($this->urlGenerator->linkToRoute('core.Css.getCss', ['fileName' => $fileName, 'appName' => $appName]), strlen(\OC::$WEBROOT) + 1);
}
/**
* Prepend hashed base url to the css file
- * @param string$cssFile
+ * @param string $cssFile
* @return string
*/
private function prependBaseurlPrefix(string $cssFile): string {
- $frontendController = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
- return substr(md5($this->urlGenerator->getBaseUrl() . $frontendController), 0, 8) . '-' . $cssFile;
+ return substr(md5($this->urlGenerator->getBaseUrl() . $this->getRoutePrefix()), 0, 4) . '-' . $cssFile;
+ }
+
+ private function getRoutePrefix() {
+ $frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
+ $prefix = \OC::$WEBROOT . '/index.php';
+ if ($frontControllerActive) {
+ $prefix = \OC::$WEBROOT;
+ }
+ return $prefix;
+ }
+
+ /**
+ * Prepend hashed app version hash
+ * @param string $cssFile
+ * @param string $appId
+ * @return string
+ */
+ private function prependVersionPrefix(string $cssFile, string $appId): string {
+ $appVersion = \OC_App::getAppVersion($appId);
+ if ($appVersion !== '0') {
+ return substr(md5($appVersion), 0, 4) . '-' . $cssFile;
+ }
+ $coreVersion = \OC_Util::getVersionString();
+
+ return substr(md5($coreVersion), 0, 4) . '-' . $cssFile;
}
/**
@@ -342,12 +409,14 @@ class SCSSCacher {
*/
private function getWebDir(string $path, string $appName, string $serverRoot, string $webRoot): string {
// Detect if path is within server root AND if path is within an app path
- if ( strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) {
+ if (strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) {
// Get the file path within the app directory
$appDirectoryPath = explode($appName, $path)[1];
// Remove the webroot
- return str_replace($webRoot, '', $appWebPath.$appDirectoryPath);
+
+ return str_replace($webRoot, '', $appWebPath . $appDirectoryPath);
}
- return $webRoot.substr($path, strlen($serverRoot));
+
+ return $webRoot . substr($path, strlen($serverRoot));
}
}
diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php
index 3acdae0e395..1efdf8b441c 100644
--- a/lib/private/TemplateLayout.php
+++ b/lib/private/TemplateLayout.php
@@ -80,9 +80,9 @@ class TemplateLayout extends \OC_Template {
// Add navigation entry
$this->assign( 'application', '');
$this->assign( 'appid', $appId );
- $navigation = \OC_App::getNavigation();
+ $navigation = \OC::$server->getNavigationManager()->getAll();
$this->assign( 'navigation', $navigation);
- $settingsNavigation = \OC_App::getSettingsNavigation();
+ $settingsNavigation = \OC::$server->getNavigationManager()->getAll('settings');
$this->assign( 'settingsnavigation', $settingsNavigation);
foreach($navigation as $entry) {
if ($entry['active']) {
@@ -122,13 +122,21 @@ class TemplateLayout extends \OC_Template {
$this->assign('bodyid', 'body-login');
} else if ($renderAs == 'guest') {
parent::__construct('core', 'layout.guest');
+ \OC_Util::addStyle('guest');
$this->assign('bodyid', 'body-login');
+ } else if ($renderAs == 'public') {
+ parent::__construct('core', 'layout.public');
+ $this->assign( 'appid', $appId );
+ $this->assign('bodyid', 'body-public');
} else {
parent::__construct('core', 'layout.base');
}
- // Send the language to our layouts
- $this->assign('language', \OC::$server->getL10NFactory()->findLanguage());
+ // Send the language and the locale to our layouts
+ $lang = \OC::$server->getL10NFactory()->findLanguage();
+ $lang = str_replace('_', '-', $lang);
+ $this->assign('language', $lang);
+ $this->assign('locale', \OC::$server->getL10NFactory()->findLocale($lang));
if(\OC::$server->getSystemConfig()->getValue('installed', false)) {
if (empty(self::$versionHash)) {
@@ -154,7 +162,8 @@ class TemplateLayout extends \OC_Template {
$this->config,
\OC::$server->getGroupManager(),
\OC::$server->getIniWrapper(),
- \OC::$server->getURLGenerator()
+ \OC::$server->getURLGenerator(),
+ \OC::$server->getCapabilitiesManager()
);
$this->assign('inline_ocjs', $jsConfigHelper->getConfig());
} else {
@@ -179,7 +188,7 @@ class TemplateLayout extends \OC_Template {
&& !\OCP\Util::needUpgrade()
&& $pathInfo !== ''
&& !preg_match('/^\/login/', $pathInfo)
- && $renderAs !== 'error' && $renderAs !== 'guest'
+ && $renderAs !== 'error'
) {
$cssFiles = self::findStylesheetFiles(\OC_Util::$styles);
} else {
@@ -299,13 +308,7 @@ class TemplateLayout extends \OC_Template {
$theme,
array( \OC::$SERVERROOT => \OC::$WEBROOT ),
array( \OC::$SERVERROOT => \OC::$WEBROOT ),
- new JSCombiner(
- \OC::$server->getAppDataDir('js'),
- \OC::$server->getURLGenerator(),
- \OC::$server->getMemCacheFactory()->createDistributed('JS'),
- \OC::$server->getSystemConfig(),
- \OC::$server->getLogger()
- )
+ \OC::$server->query(JSCombiner::class)
);
$locator->find($scripts);
return $locator->getResources();
diff --git a/lib/private/URLGenerator.php b/lib/private/URLGenerator.php
index c72c2255179..6f4f869238c 100644
--- a/lib/private/URLGenerator.php
+++ b/lib/private/URLGenerator.php
@@ -35,6 +35,7 @@ declare(strict_types=1);
namespace OC;
+use OCA\Theming\ThemingDefaults;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IRequest;
@@ -168,7 +169,10 @@ class URLGenerator implements IURLGenerator {
$themingEnabled = $this->config->getSystemValue('installed', false) && \OCP\App::isEnabled('theming') && \OC_App::isAppLoaded('theming');
$themingImagePath = false;
if($themingEnabled) {
- $themingImagePath = \OC::$server->getThemingDefaults()->replaceImagePath($app, $image);
+ $themingDefaults = \OC::$server->getThemingDefaults();
+ if ($themingDefaults instanceof ThemingDefaults) {
+ $themingImagePath = $themingDefaults->replaceImagePath($app, $image);
+ }
}
if (file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) {
diff --git a/lib/private/Updater.php b/lib/private/Updater.php
index 43096e7c1f8..4098d1b767d 100644
--- a/lib/private/Updater.php
+++ b/lib/private/Updater.php
@@ -38,6 +38,7 @@ use OC\DB\MigrationService;
use OC\Hooks\BasicEmitter;
use OC\IntegrityCheck\Checker;
use OC_App;
+use OCP\BackgroundJob\IJobList;
use OCP\IConfig;
use OCP\ILogger;
use OCP\Util;
@@ -66,6 +67,9 @@ class Updater extends BasicEmitter {
/** @var Installer */
private $installer;
+ /** @var IJobList */
+ private $jobList;
+
private $logLevelNames = [
0 => 'Debug',
1 => 'Info',
@@ -74,20 +78,16 @@ class Updater extends BasicEmitter {
4 => 'Fatal',
];
- /**
- * @param IConfig $config
- * @param Checker $checker
- * @param ILogger $log
- * @param Installer $installer
- */
public function __construct(IConfig $config,
Checker $checker,
- ILogger $log = null,
- Installer $installer) {
+ ILogger $log,
+ Installer $installer,
+ IJobList $jobList) {
$this->log = $log;
$this->config = $config;
$this->checker = $checker;
$this->installer = $installer;
+ $this->jobList = $jobList;
}
/**
@@ -100,9 +100,9 @@ class Updater extends BasicEmitter {
$this->emitRepairEvents();
$this->logAllEvents();
- $logLevel = $this->config->getSystemValue('loglevel', Util::WARN);
+ $logLevel = $this->config->getSystemValue('loglevel', ILogger::WARN);
$this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
- $this->config->setSystemValue('loglevel', Util::DEBUG);
+ $this->config->setSystemValue('loglevel', ILogger::DEBUG);
$wasMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false);
@@ -113,6 +113,12 @@ class Updater extends BasicEmitter {
$installedVersion = $this->config->getSystemValue('version', '0.0.0');
$currentVersion = implode('.', \OCP\Util::getVersion());
+
+ // see https://github.com/nextcloud/server/issues/9992 for potential problem
+ if (version_compare($installedVersion, '14.0.0.9', '>=')) {
+ $this->waitForCronToFinish();
+ }
+
$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
$success = true;
@@ -250,7 +256,7 @@ class Updater extends BasicEmitter {
$this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps());
// install new shipped apps on upgrade
- OC_App::loadApps('authentication');
+ OC_App::loadApps(['authentication']);
$errors = Installer::installShippedApps(true);
foreach ($errors as $appId => $exception) {
/** @var \Exception $exception */
@@ -346,7 +352,7 @@ class Updater extends BasicEmitter {
if(!isset($stacks[$type])) {
$stacks[$type] = array();
}
- if (\OC_App::isType($appId, $type)) {
+ if (\OC_App::isType($appId, [$type])) {
$stacks[$type][] = $appId;
$priorityType = true;
break;
@@ -385,17 +391,17 @@ class Updater extends BasicEmitter {
private function checkAppsRequirements() {
$isCoreUpgrade = $this->isCodeUpgrade();
$apps = OC_App::getEnabledApps();
- $version = Util::getVersion();
+ $version = implode('.', Util::getVersion());
$disabledApps = [];
$appManager = \OC::$server->getAppManager();
foreach ($apps as $app) {
// check if the app is compatible with this version of ownCloud
$info = OC_App::getAppInfo($app);
- if(!OC_App::isAppCompatible($version, $info)) {
+ if($info === null || !OC_App::isAppCompatible($version, $info)) {
if ($appManager->isShipped($app)) {
throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
}
- OC_App::disable($app);
+ \OC::$server->getAppManager()->disableApp($app);
$this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
}
// no need to disable any app in case this is a non-core upgrade
@@ -604,6 +610,12 @@ class Updater extends BasicEmitter {
});
}
+ private function waitForCronToFinish() {
+ while ($this->jobList->isAnyJobRunning()) {
+ $this->emit('\OC\Updater', 'waitForCronToFinish');
+ sleep(5);
+ }
+ }
}
diff --git a/lib/private/Updater/ChangesCheck.php b/lib/private/Updater/ChangesCheck.php
new file mode 100644
index 00000000000..095cf396e89
--- /dev/null
+++ b/lib/private/Updater/ChangesCheck.php
@@ -0,0 +1,166 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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\Updater;
+
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\Http\Client\IClientService;
+use OCP\Http\Client\IResponse;
+use OCP\ILogger;
+
+class ChangesCheck {
+ /** @var IClientService */
+ protected $clientService;
+ /** @var ChangesMapper */
+ private $mapper;
+ /** @var ILogger */
+ private $logger;
+
+ const RESPONSE_NO_CONTENT = 0;
+ const RESPONSE_USE_CACHE = 1;
+ const RESPONSE_HAS_CONTENT = 2;
+
+ public function __construct(IClientService $clientService, ChangesMapper $mapper, ILogger $logger) {
+ $this->clientService = $clientService;
+ $this->mapper = $mapper;
+ $this->logger = $logger;
+ }
+
+ /**
+ * @throws DoesNotExistException
+ */
+ public function getChangesForVersion(string $version): array {
+ $version = $this->normalizeVersion($version);
+ $changesInfo = $this->mapper->getChanges($version);
+ return json_decode($changesInfo->getData(), true);
+ }
+
+ /**
+ * @throws \Exception
+ */
+ public function check(string $uri, string $version): array {
+ try {
+ $version = $this->normalizeVersion($version);
+ $changesInfo = $this->mapper->getChanges($version);
+ if($changesInfo->getLastCheck() + 1800 > time()) {
+ return json_decode($changesInfo->getData(), true);
+ }
+ } catch (DoesNotExistException $e) {
+ $changesInfo = new ChangesResult();
+ }
+
+ $response = $this->queryChangesServer($uri, $changesInfo);
+
+ switch($this->evaluateResponse($response)) {
+ case self::RESPONSE_NO_CONTENT:
+ return [];
+ case self::RESPONSE_USE_CACHE:
+ return json_decode($changesInfo->getData(), true);
+ case self::RESPONSE_HAS_CONTENT:
+ default:
+ $data = $this->extractData($response->getBody());
+ $changesInfo->setData(json_encode($data));
+ $changesInfo->setEtag($response->getHeader('Etag'));
+ $this->cacheResult($changesInfo, $version);
+
+ return $data;
+ }
+ }
+
+ protected function evaluateResponse(IResponse $response): int {
+ if($response->getStatusCode() === 304) {
+ return self::RESPONSE_USE_CACHE;
+ } else if($response->getStatusCode() === 404) {
+ return self::RESPONSE_NO_CONTENT;
+ } else if($response->getStatusCode() === 200) {
+ return self::RESPONSE_HAS_CONTENT;
+ }
+ $this->logger->debug('Unexpected return code {code} from changelog server', [
+ 'app' => 'core',
+ 'code' => $response->getStatusCode(),
+ ]);
+ return self::RESPONSE_NO_CONTENT;
+ }
+
+ protected function cacheResult(ChangesResult $entry, string $version) {
+ if($entry->getVersion() === $version) {
+ $this->mapper->update($entry);
+ } else {
+ $entry->setVersion($version);
+ $this->mapper->insert($entry);
+ }
+ }
+
+ /**
+ * @throws \Exception
+ */
+ protected function queryChangesServer(string $uri, ChangesResult $entry): IResponse {
+ $headers = [];
+ if($entry->getEtag() !== '') {
+ $headers['If-None-Match'] = [$entry->getEtag()];
+ }
+
+ $entry->setLastCheck(time());
+ $client = $this->clientService->newClient();
+ return $client->get($uri, [
+ 'headers' => $headers,
+ ]);
+ }
+
+ protected function extractData($body):array {
+ $data = [];
+ if ($body) {
+ $loadEntities = libxml_disable_entity_loader(true);
+ $xml = @simplexml_load_string($body);
+ libxml_disable_entity_loader($loadEntities);
+ if ($xml !== false) {
+ $data['changelogURL'] = (string)$xml->changelog['href'];
+ $data['whatsNew'] = [];
+ foreach($xml->whatsNew as $infoSet) {
+ $data['whatsNew'][(string)$infoSet['lang']] = [
+ 'regular' => (array)$infoSet->regular->item,
+ 'admin' => (array)$infoSet->admin->item,
+ ];
+ }
+ } else {
+ libxml_clear_errors();
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * returns a x.y.z form of the provided version. Extra numbers will be
+ * omitted, missing ones added as zeros.
+ */
+ public function normalizeVersion(string $version): string {
+ $versionNumbers = array_slice(explode('.', $version), 0, 3);
+ $versionNumbers[0] = $versionNumbers[0] ?: '0'; // deal with empty input
+ while(count($versionNumbers) < 3) {
+ // changelog server expects x.y.z, pad 0 if it is too short
+ $versionNumbers[] = 0;
+ }
+ return implode('.', $versionNumbers);
+ }
+}
diff --git a/lib/private/Updater/ChangesMapper.php b/lib/private/Updater/ChangesMapper.php
new file mode 100644
index 00000000000..d1548c415ca
--- /dev/null
+++ b/lib/private/Updater/ChangesMapper.php
@@ -0,0 +1,57 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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\Updater;
+
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\QBMapper;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+class ChangesMapper extends QBMapper {
+ const TABLE_NAME = 'whats_new';
+
+ public function __construct(IDBConnection $db) {
+ parent::__construct($db, self::TABLE_NAME);
+ }
+
+ /**
+ * @throws DoesNotExistException
+ */
+ public function getChanges(string $version): ChangesResult {
+ /* @var $qb IQueryBuilder */
+ $qb = $this->db->getQueryBuilder();
+ $result = $qb->select('*')
+ ->from(self::TABLE_NAME)
+ ->where($qb->expr()->eq('version', $qb->createNamedParameter($version)))
+ ->execute();
+
+ $data = $result->fetch();
+ $result->closeCursor();
+ if ($data === false) {
+ throw new DoesNotExistException('Changes info is not present');
+ }
+ return ChangesResult::fromRow($data);
+ }
+}
diff --git a/lib/private/Updater/ChangesResult.php b/lib/private/Updater/ChangesResult.php
new file mode 100644
index 00000000000..95a1af3910c
--- /dev/null
+++ b/lib/private/Updater/ChangesResult.php
@@ -0,0 +1,61 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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\Updater;
+
+use OCP\AppFramework\Db\Entity;
+
+/**
+ * Class ChangesResult
+ *
+ * @package OC\Updater
+ * @method string getVersion()=1
+ * @method void setVersion(string $version)
+ * @method string getEtag()
+ * @method void setEtag(string $etag)
+ * @method int getLastCheck()
+ * @method void setLastCheck(int $lastCheck)
+ * @method string getData()
+ * @method void setData(string $data)
+ */
+class ChangesResult extends Entity {
+ /** @var string */
+ protected $version = '';
+
+ /** @var string */
+ protected $etag = '';
+
+ /** @var int */
+ protected $lastCheck = 0;
+
+ /** @var string */
+ protected $data = '';
+
+ public function __construct() {
+ $this->addType('version', 'string');
+ $this->addType('etag', 'string');
+ $this->addType('lastCheck', 'int');
+ $this->addType('data', 'string');
+ }
+}
diff --git a/lib/private/Updater/VersionCheck.php b/lib/private/Updater/VersionCheck.php
index c7b829c9ec5..3cbd7061fe0 100644
--- a/lib/private/Updater/VersionCheck.php
+++ b/lib/private/Updater/VersionCheck.php
@@ -97,7 +97,9 @@ class VersionCheck {
$tmp['versionstring'] = (string)$data->versionstring;
$tmp['url'] = (string)$data->url;
$tmp['web'] = (string)$data->web;
+ $tmp['changes'] = isset($data->changes) ? (string)$data->changes : '';
$tmp['autoupdater'] = (string)$data->autoupdater;
+ $tmp['eol'] = isset($data->eol) ? (string)$data->eol : '0';
} else {
libxml_clear_errors();
}
diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php
index 471ff1f45ae..532b2f8c03c 100644
--- a/lib/private/User/Database.php
+++ b/lib/private/User/Database.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -40,6 +41,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
+
/*
*
* The following SQL statement is just a help for developers and will not be
@@ -56,7 +58,16 @@
namespace OC\User;
use OC\Cache\CappedMemoryCache;
-use OCP\IUserBackend;
+use OCP\IDBConnection;
+use OCP\ILogger;
+use OCP\User\Backend\ABackend;
+use OCP\User\Backend\ICheckPasswordBackend;
+use OCP\User\Backend\ICountUsersBackend;
+use OCP\User\Backend\ICreateUserBackend;
+use OCP\User\Backend\IGetDisplayNameBackend;
+use OCP\User\Backend\IGetHomeBackend;
+use OCP\User\Backend\ISetDisplayNameBackend;
+use OCP\User\Backend\ISetPasswordBackend;
use OCP\Util;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\GenericEvent;
@@ -64,25 +75,50 @@ use Symfony\Component\EventDispatcher\GenericEvent;
/**
* Class for user management in a SQL Database (e.g. MySQL, SQLite)
*/
-class Database extends Backend implements IUserBackend {
+class Database extends ABackend
+ implements ICreateUserBackend,
+ ISetPasswordBackend,
+ ISetDisplayNameBackend,
+ IGetDisplayNameBackend,
+ ICheckPasswordBackend,
+ IGetHomeBackend,
+ ICountUsersBackend {
/** @var CappedMemoryCache */
private $cache;
/** @var EventDispatcher */
private $eventDispatcher;
+ /** @var IDBConnection */
+ private $dbConn;
+
+ /** @var string */
+ private $table;
+
/**
* \OC\User\Database constructor.
*
* @param EventDispatcher $eventDispatcher
+ * @param string $table
*/
- public function __construct($eventDispatcher = null) {
+ public function __construct($eventDispatcher = null, $table = 'users') {
$this->cache = new CappedMemoryCache();
+ $this->table = $table;
$this->eventDispatcher = $eventDispatcher ? $eventDispatcher : \OC::$server->getEventDispatcher();
}
/**
+ * FIXME: This function should not be required!
+ */
+ private function fixDI() {
+ if ($this->dbConn === null) {
+ $this->dbConn = \OC::$server->getDatabaseConnection();
+ }
+ }
+
+ /**
* Create a new user
+ *
* @param string $uid The username of the user to create
* @param string $password The password of the new user
* @return bool
@@ -90,16 +126,22 @@ class Database extends Backend implements IUserBackend {
* Creates a new user. Basic checking of username is done in OC_User
* itself, not in its subclasses.
*/
- public function createUser($uid, $password) {
+ public function createUser(string $uid, string $password): bool {
+ $this->fixDI();
+
if (!$this->userExists($uid)) {
$event = new GenericEvent($password);
$this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event);
- $query = \OC_DB::prepare('INSERT INTO `*PREFIX*users` ( `uid`, `password` ) VALUES( ?, ? )');
- try {
- $result = $query->execute(array($uid, \OC::$server->getHasher()->hash($password)));
- } catch (\Exception $e) {
- $result = false;
- }
+
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->insert($this->table)
+ ->values([
+ 'uid' => $qb->createNamedParameter($uid),
+ 'password' => $qb->createNamedParameter(\OC::$server->getHasher()->hash($password)),
+ 'uid_lower' => $qb->createNamedParameter(mb_strtolower($uid)),
+ ]);
+
+ $result = $qb->execute();
// Clear cache
unset($this->cache[$uid]);
@@ -112,15 +154,20 @@ class Database extends Backend implements IUserBackend {
/**
* delete a user
+ *
* @param string $uid The username of the user to delete
* @return bool
*
* Deletes a user
*/
public function deleteUser($uid) {
+ $this->fixDI();
+
// Delete user-group-relation
- $query = \OC_DB::prepare('DELETE FROM `*PREFIX*users` WHERE `uid` = ?');
- $result = $query->execute(array($uid));
+ $query = $this->dbConn->getQueryBuilder();
+ $query->delete($this->table)
+ ->where($query->expr()->eq('uid_lower', $query->createNamedParameter(mb_strtolower($uid))));
+ $result = $query->execute();
if (isset($this->cache[$uid])) {
unset($this->cache[$uid]);
@@ -131,18 +178,28 @@ class Database extends Backend implements IUserBackend {
/**
* Set password
+ *
* @param string $uid The username
* @param string $password The new password
* @return bool
*
* Change the password of a user
*/
- public function setPassword($uid, $password) {
+ public function setPassword(string $uid, string $password): bool {
+ $this->fixDI();
+
if ($this->userExists($uid)) {
$event = new GenericEvent($password);
$this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event);
- $query = \OC_DB::prepare('UPDATE `*PREFIX*users` SET `password` = ? WHERE `uid` = ?');
- $result = $query->execute(array(\OC::$server->getHasher()->hash($password), $uid));
+
+ $hasher = \OC::$server->getHasher();
+ $hashedPassword = $hasher->hash($password);
+
+ $query = $this->dbConn->getQueryBuilder();
+ $query->update($this->table)
+ ->set('password', $query->createNamedParameter($hashedPassword))
+ ->where($query->expr()->eq('uid_lower', $query->createNamedParameter(mb_strtolower($uid))));
+ $result = $query->execute();
return $result ? true : false;
}
@@ -152,16 +209,23 @@ class Database extends Backend implements IUserBackend {
/**
* Set display name
+ *
* @param string $uid The username
* @param string $displayName The new display name
* @return bool
*
* Change the display name of a user
*/
- public function setDisplayName($uid, $displayName) {
+ public function setDisplayName(string $uid, string $displayName): bool {
+ $this->fixDI();
+
if ($this->userExists($uid)) {
- $query = \OC_DB::prepare('UPDATE `*PREFIX*users` SET `displayname` = ? WHERE LOWER(`uid`) = LOWER(?)');
- $query->execute(array($displayName, $uid));
+ $query = $this->dbConn->getQueryBuilder();
+ $query->update($this->table)
+ ->set('displayname', $query->createNamedParameter($displayName))
+ ->where($query->expr()->eq('uid_lower', $query->createNamedParameter(mb_strtolower($uid))));
+ $query->execute();
+
$this->cache[$uid]['displayname'] = $displayName;
return true;
@@ -172,10 +236,12 @@ class Database extends Backend implements IUserBackend {
/**
* get display name of the user
+ *
* @param string $uid user ID of the user
* @return string display name
*/
- public function getDisplayName($uid) {
+ public function getDisplayName($uid): string {
+ $uid = (string)$uid;
$this->loadUser($uid);
return empty($this->cache[$uid]['displayname']) ? $uid : $this->cache[$uid]['displayname'];
}
@@ -189,21 +255,30 @@ class Database extends Backend implements IUserBackend {
* @return array an array of all displayNames (value) and the corresponding uids (key)
*/
public function getDisplayNames($search = '', $limit = null, $offset = null) {
- $parameters = [];
- $searchLike = '';
- if ($search !== '') {
- $parameters[] = '%' . \OC::$server->getDatabaseConnection()->escapeLikeParameter($search) . '%';
- $parameters[] = '%' . \OC::$server->getDatabaseConnection()->escapeLikeParameter($search) . '%';
- $searchLike = ' WHERE LOWER(`displayname`) LIKE LOWER(?) OR '
- . 'LOWER(`uid`) LIKE LOWER(?)';
- }
+ $this->fixDI();
+
+ $query = $this->dbConn->getQueryBuilder();
+
+ $query->select('uid', 'displayname')
+ ->from($this->table, 'u')
+ ->leftJoin('u', 'preferences', 'p', $query->expr()->andX(
+ $query->expr()->eq('userid', 'uid'),
+ $query->expr()->eq('appid', $query->expr()->literal('settings')),
+ $query->expr()->eq('configkey', $query->expr()->literal('email')))
+ )
+ // sqlite doesn't like re-using a single named parameter here
+ ->where($query->expr()->iLike('uid', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%')))
+ ->orWhere($query->expr()->iLike('displayname', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%')))
+ ->orWhere($query->expr()->iLike('configvalue', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%')))
+ ->orderBy($query->func()->lower('displayname'), 'ASC')
+ ->orderBy('uid_lower', 'ASC')
+ ->setMaxResults($limit)
+ ->setFirstResult($offset);
- $displayNames = array();
- $query = \OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users`'
- . $searchLike .' ORDER BY LOWER(`displayname`), LOWER(`uid`) ASC', $limit, $offset);
- $result = $query->execute($parameters);
- while ($row = $result->fetchRow()) {
- $displayNames[$row['uid']] = $row['displayname'];
+ $result = $query->execute();
+ $displayNames = [];
+ while ($row = $result->fetch()) {
+ $displayNames[(string)$row['uid']] = (string)$row['displayname'];
}
return $displayNames;
@@ -211,6 +286,7 @@ class Database extends Backend implements IUserBackend {
/**
* Check if the password is correct
+ *
* @param string $uid The username
* @param string $password The password
* @return string
@@ -218,19 +294,29 @@ class Database extends Backend implements IUserBackend {
* Check if the password is correct without logging in the user
* returns the user id or false
*/
- public function checkPassword($uid, $password) {
- $query = \OC_DB::prepare('SELECT `uid`, `password` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)');
- $result = $query->execute(array($uid));
+ public function checkPassword(string $uid, string $password) {
+ $this->fixDI();
+
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->select('uid', 'password')
+ ->from($this->table)
+ ->where(
+ $qb->expr()->eq(
+ 'uid_lower', $qb->createNamedParameter(mb_strtolower($uid))
+ )
+ );
+ $result = $qb->execute();
+ $row = $result->fetch();
+ $result->closeCursor();
- $row = $result->fetchRow();
if ($row) {
$storedHash = $row['password'];
$newHash = '';
- if(\OC::$server->getHasher()->verify($password, $storedHash, $newHash)) {
- if(!empty($newHash)) {
+ if (\OC::$server->getHasher()->verify($password, $storedHash, $newHash)) {
+ if (!empty($newHash)) {
$this->setPassword($uid, $password);
}
- return $row['uid'];
+ return (string)$row['uid'];
}
}
@@ -240,35 +326,40 @@ class Database extends Backend implements IUserBackend {
/**
* Load an user in the cache
+ *
* @param string $uid the username
* @return boolean true if user was found, false otherwise
*/
private function loadUser($uid) {
- $uid = (string) $uid;
+ $this->fixDI();
+
+ $uid = (string)$uid;
if (!isset($this->cache[$uid])) {
//guests $uid could be NULL or ''
if ($uid === '') {
- $this->cache[$uid]=false;
+ $this->cache[$uid] = false;
return true;
}
- $query = \OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)');
- $result = $query->execute(array($uid));
-
- if ($result === false) {
- Util::writeLog('core', \OC_DB::getErrorMessage(), Util::ERROR);
- return false;
- }
+ $qb = $this->dbConn->getQueryBuilder();
+ $qb->select('uid', 'displayname')
+ ->from($this->table)
+ ->where(
+ $qb->expr()->eq(
+ 'uid_lower', $qb->createNamedParameter(mb_strtolower($uid))
+ )
+ );
+ $result = $qb->execute();
+ $row = $result->fetch();
+ $result->closeCursor();
$this->cache[$uid] = false;
// "uid" is primary key, so there can only be a single result
- if ($row = $result->fetchRow()) {
- $this->cache[$uid]['uid'] = $row['uid'];
- $this->cache[$uid]['displayname'] = $row['displayname'];
- $result->closeCursor();
+ if ($row !== false) {
+ $this->cache[$uid]['uid'] = (string)$row['uid'];
+ $this->cache[$uid]['displayname'] = (string)$row['displayname'];
} else {
- $result->closeCursor();
return false;
}
}
@@ -285,26 +376,17 @@ class Database extends Backend implements IUserBackend {
* @return string[] an array of all uids
*/
public function getUsers($search = '', $limit = null, $offset = null) {
- $parameters = [];
- $searchLike = '';
- if ($search !== '') {
- $parameters[] = '%' . \OC::$server->getDatabaseConnection()->escapeLikeParameter($search) . '%';
- $searchLike = ' WHERE LOWER(`uid`) LIKE LOWER(?)';
- $parameters[] = '%' . \OC::$server->getDatabaseConnection()->escapeLikeParameter($search) . '%';
- $searchLike .= ' OR LOWER(`displayname`) LIKE LOWER(?)';
- }
-
- $query = \OC_DB::prepare('SELECT `uid` FROM `*PREFIX*users`' . $searchLike . ' ORDER BY LOWER(`uid`) ASC', $limit, $offset);
- $result = $query->execute($parameters);
- $users = array();
- while ($row = $result->fetchRow()) {
- $users[] = $row['uid'];
- }
- return $users;
+ $users = $this->getDisplayNames($search, $limit, $offset);
+ $userIds = array_map(function ($uid) {
+ return (string)$uid;
+ }, array_keys($users));
+ sort($userIds, SORT_STRING | SORT_FLAG_CASE);
+ return $userIds;
}
/**
* check if a user exists
+ *
* @param string $uid the username
* @return boolean
*/
@@ -315,12 +397,13 @@ class Database extends Backend implements IUserBackend {
/**
* get the user's home directory
+ *
* @param string $uid the username
* @return string|false
*/
- public function getHome($uid) {
+ public function getHome(string $uid) {
if ($this->userExists($uid)) {
- return \OC::$server->getConfig()->getSystemValue("datadirectory", \OC::$SERVERROOT . "/data") . '/' . $uid;
+ return \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $uid;
}
return false;
@@ -339,13 +422,14 @@ class Database extends Backend implements IUserBackend {
* @return int|bool
*/
public function countUsers() {
- $query = \OC_DB::prepare('SELECT COUNT(*) FROM `*PREFIX*users`');
+ $this->fixDI();
+
+ $query = $this->dbConn->getQueryBuilder();
+ $query->select($query->func()->count('uid'))
+ ->from($this->table);
$result = $query->execute();
- if ($result === false) {
- Util::writeLog('core', \OC_DB::getErrorMessage(), Util::ERROR);
- return false;
- }
- return $result->fetchOne();
+
+ return $result->fetchColumn();
}
/**
@@ -364,14 +448,15 @@ class Database extends Backend implements IUserBackend {
/**
* Backend name to be shown in user management
+ *
* @return string the name of the backend to be shown
*/
- public function getBackendName(){
+ public function getBackendName() {
return 'Database';
}
public static function preLoginNameUsedAsUserName($param) {
- if(!isset($param['uid'])) {
+ if (!isset($param['uid'])) {
throw new \Exception('key uid is expected to be set in $param');
}
diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php
index 5f2a010561c..494a345be59 100644
--- a/lib/private/User/Manager.php
+++ b/lib/private/User/Manager.php
@@ -34,6 +34,7 @@ namespace OC\User;
use OC\Hooks\PublicEmitter;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IUser;
+use OCP\IGroup;
use OCP\IUserBackend;
use OCP\IUserManager;
use OCP\IConfig;
@@ -50,6 +51,9 @@ use OCP\UserInterface;
* - preCreateUser(string $uid, string $password)
* - postCreateUser(\OC\User\User $user, string $password)
* - change(\OC\User\User $user)
+ * - assignedUserId(string $uid)
+ * - preUnassignedUserId(string $uid)
+ * - postUnassignedUserId(string $uid)
*
* @package OC\User
*/
@@ -235,7 +239,7 @@ class Manager extends PublicEmitter implements IUserManager {
* @var \OC\User\User $a
* @var \OC\User\User $b
*/
- return strcmp($a->getUID(), $b->getUID());
+ return strcasecmp($a->getUID(), $b->getUID());
});
return $users;
}
@@ -264,7 +268,7 @@ class Manager extends PublicEmitter implements IUserManager {
* @var \OC\User\User $a
* @var \OC\User\User $b
*/
- return strcmp(strtolower($a->getDisplayName()), strtolower($b->getDisplayName()));
+ return strcasecmp($a->getDisplayName(), $b->getDisplayName());
});
return $users;
}
@@ -382,6 +386,24 @@ class Manager extends PublicEmitter implements IUserManager {
}
/**
+ * returns how many users per backend exist in the requested groups (if supported by backend)
+ *
+ * @param IGroup[] $groups an array of gid to search in
+ * @return array|int an array of backend class as key and count number as value
+ * if $hasLoggedIn is true only an int is returned
+ */
+ public function countUsersOfGroups(array $groups) {
+ $users = [];
+ foreach($groups as $group) {
+ $usersIds = array_map(function($user) {
+ return $user->getUID();
+ }, $group->getUsers());
+ $users = array_merge($users, $usersIds);
+ }
+ return count(array_unique($users));
+ }
+
+ /**
* The callback is executed for each user on each backend.
* If the callback returns false no further users will be retrieved.
*
@@ -417,12 +439,12 @@ class Manager extends PublicEmitter implements IUserManager {
}
/**
- * returns how many users have logged in once
+ * returns how many users are disabled
*
* @return int
* @since 12.0.0
*/
- public function countDisabledUsers() {
+ public function countDisabledUsers(): int {
$queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
$queryBuilder->select($queryBuilder->createFunction('COUNT(*)'))
->from('preferences')
@@ -430,12 +452,48 @@ class Manager extends PublicEmitter implements IUserManager {
->andWhere($queryBuilder->expr()->eq('configkey', $queryBuilder->createNamedParameter('enabled')))
->andWhere($queryBuilder->expr()->eq('configvalue', $queryBuilder->createNamedParameter('false'), IQueryBuilder::PARAM_STR));
- $query = $queryBuilder->execute();
+
+ $result = $queryBuilder->execute();
+ $count = $result->fetchColumn();
+ $result->closeCursor();
+
+ if ($count !== false) {
+ $count = (int)$count;
+ } else {
+ $count = 0;
+ }
- $result = (int)$query->fetchColumn();
- $query->closeCursor();
+ return $count;
+ }
- return $result;
+ /**
+ * returns how many users are disabled in the requested groups
+ *
+ * @param array $groups groupids to search
+ * @return int
+ * @since 14.0.0
+ */
+ public function countDisabledUsersOfGroups(array $groups): int {
+ $queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder();
+ $queryBuilder->select($queryBuilder->createFunction('COUNT(Distinct uid)'))
+ ->from('preferences', 'p')
+ ->innerJoin('p', 'group_user', 'g', 'p.userid = g.uid')
+ ->where($queryBuilder->expr()->eq('appid', $queryBuilder->createNamedParameter('core')))
+ ->andWhere($queryBuilder->expr()->eq('configkey', $queryBuilder->createNamedParameter('enabled')))
+ ->andWhere($queryBuilder->expr()->eq('configvalue', $queryBuilder->createNamedParameter('false'), IQueryBuilder::PARAM_STR))
+ ->andWhere($queryBuilder->expr()->in('gid', $queryBuilder->createNamedParameter($groups, IQueryBuilder::PARAM_STR_ARRAY)));
+
+ $result = $queryBuilder->execute();
+ $count = $result->fetchColumn();
+ $result->closeCursor();
+
+ if ($count !== false) {
+ $count = (int)$count;
+ } else {
+ $count = 0;
+ }
+
+ return $count;
}
/**
@@ -478,6 +536,7 @@ class Manager extends PublicEmitter implements IUserManager {
if ($return === false) {
return;
}
+ break;
}
}
}
@@ -488,7 +547,7 @@ class Manager extends PublicEmitter implements IUserManager {
* Getting all userIds that have a listLogin value requires checking the
* value in php because on oracle you cannot use a clob in a where clause,
* preventing us from doing a not null or length(value) > 0 check.
- *
+ *
* @param int $limit
* @param int $offset
* @return string[] with user ids
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index c2b58c37cdb..ee1439b9e20 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -55,7 +55,6 @@ use OCP\ILogger;
use OCP\IRequest;
use OCP\ISession;
use OCP\IUser;
-use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Lockdown\ILockdownManager;
use OCP\Security\ISecureRandom;
@@ -73,6 +72,9 @@ use Symfony\Component\EventDispatcher\GenericEvent;
* - postDelete(\OC\User\User $user)
* - preCreateUser(string $uid, string $password)
* - postCreateUser(\OC\User\User $user)
+ * - assignedUserId(string $uid)
+ * - preUnassignedUserId(string $uid)
+ * - postUnassignedUserId(string $uid)
* - preLogin(string $user, string $password)
* - postLogin(\OC\User\User $user, string $password)
* - preRememberedLogin(string $uid)
@@ -624,6 +626,8 @@ class Session implements IUserSession, Emitter {
try {
$sessionId = $this->session->getId();
$pwd = $this->getPassword($password);
+ // Make sure the current sessionId has no leftover tokens
+ $this->tokenProvider->invalidateToken($sessionId);
$this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name, IToken::TEMPORARY_TOKEN, $remember);
return true;
} catch (SessionNotAvailableException $ex) {
diff --git a/lib/private/User/User.php b/lib/private/User/User.php
index 56c489181de..e171a65f8ce 100644
--- a/lib/private/User/User.php
+++ b/lib/private/User/User.php
@@ -349,13 +349,12 @@ class User implements IUser {
*
* @param bool $enabled
*/
- public function setEnabled($enabled) {
+ public function setEnabled(bool $enabled = true) {
$oldStatus = $this->isEnabled();
$this->enabled = $enabled;
- $enabled = $enabled ? 'true' : 'false';
if ($oldStatus !== $this->enabled) {
$this->triggerChange('enabled', $enabled);
- $this->config->setUserValue($this->uid, 'core', 'enabled', $enabled);
+ $this->config->setUserValue($this->uid, 'core', 'enabled', $enabled ? 'true' : 'false');
}
}
diff --git a/lib/private/legacy/api.php b/lib/private/legacy/api.php
index 7fe84b73c43..40bf6132e28 100644
--- a/lib/private/legacy/api.php
+++ b/lib/private/legacy/api.php
@@ -38,43 +38,9 @@ use OCP\AppFramework\Http;
class OC_API {
/**
- * API authentication levels
- */
-
- /** @deprecated Use \OCP\API::GUEST_AUTH instead */
- const GUEST_AUTH = 0;
-
- /** @deprecated Use \OCP\API::USER_AUTH instead */
- const USER_AUTH = 1;
-
- /** @deprecated Use \OCP\API::SUBADMIN_AUTH instead */
- const SUBADMIN_AUTH = 2;
-
- /** @deprecated Use \OCP\API::ADMIN_AUTH instead */
- const ADMIN_AUTH = 3;
-
- /**
- * API Response Codes
- */
-
- /** @deprecated Use \OCP\API::RESPOND_UNAUTHORISED instead */
- const RESPOND_UNAUTHORISED = 997;
-
- /** @deprecated Use \OCP\API::RESPOND_SERVER_ERROR instead */
- const RESPOND_SERVER_ERROR = 996;
-
- /** @deprecated Use \OCP\API::RESPOND_NOT_FOUND instead */
- const RESPOND_NOT_FOUND = 998;
-
- /** @deprecated Use \OCP\API::RESPOND_UNKNOWN_ERROR instead */
- const RESPOND_UNKNOWN_ERROR = 999;
-
- /**
* api actions
*/
protected static $actions = array();
- private static $logoutRequired = false;
- private static $isLoggedIn = false;
/**
* registers an api call
@@ -107,249 +73,6 @@ class OC_API {
}
/**
- * handles an api call
- * @param array $parameters
- */
- public static function call($parameters) {
- $request = \OC::$server->getRequest();
- $method = $request->getMethod();
-
- // Prepare the request variables
- if($method === 'PUT') {
- $parameters['_put'] = $request->getParams();
- } else if($method === 'DELETE') {
- $parameters['_delete'] = $request->getParams();
- }
- $name = $parameters['_route'];
- // Foreach registered action
- $responses = array();
- $appManager = \OC::$server->getAppManager();
- foreach(self::$actions[$name] as $action) {
- // Check authentication and availability
- if(!self::isAuthorised($action)) {
- $responses[] = array(
- 'app' => $action['app'],
- 'response' => new \OC\OCS\Result(null, API::RESPOND_UNAUTHORISED, 'Unauthorised'),
- 'shipped' => $appManager->isShipped($action['app']),
- );
- continue;
- }
- if(!is_callable($action['action'])) {
- $responses[] = array(
- 'app' => $action['app'],
- 'response' => new \OC\OCS\Result(null, API::RESPOND_NOT_FOUND, 'Api method not found'),
- 'shipped' => $appManager->isShipped($action['app']),
- );
- continue;
- }
- // Run the action
- $responses[] = array(
- 'app' => $action['app'],
- 'response' => call_user_func($action['action'], $parameters),
- 'shipped' => $appManager->isShipped($action['app']),
- );
- }
- $response = self::mergeResponses($responses);
- $format = self::requestedFormat();
- if (self::$logoutRequired) {
- \OC::$server->getUserSession()->logout();
- }
-
- self::respond($response, $format);
- }
-
- /**
- * merge the returned result objects into one response
- * @param array $responses
- * @return \OC\OCS\Result
- */
- public static function mergeResponses($responses) {
- // Sort into shipped and third-party
- $shipped = array(
- 'succeeded' => array(),
- 'failed' => array(),
- );
- $thirdparty = array(
- 'succeeded' => array(),
- 'failed' => array(),
- );
-
- foreach($responses as $response) {
- if($response['shipped'] || ($response['app'] === 'core')) {
- if($response['response']->succeeded()) {
- $shipped['succeeded'][$response['app']] = $response;
- } else {
- $shipped['failed'][$response['app']] = $response;
- }
- } else {
- if($response['response']->succeeded()) {
- $thirdparty['succeeded'][$response['app']] = $response;
- } else {
- $thirdparty['failed'][$response['app']] = $response;
- }
- }
- }
-
- // Remove any error responses if there is one shipped response that succeeded
- if(!empty($shipped['failed'])) {
- // Which shipped response do we use if they all failed?
- // They may have failed for different reasons (different status codes)
- // Which response code should we return?
- // Maybe any that are not \OCP\API::RESPOND_SERVER_ERROR
- // Merge failed responses if more than one
- $data = array();
- foreach($shipped['failed'] as $failure) {
- $data = array_merge_recursive($data, $failure['response']->getData());
- }
- $picked = reset($shipped['failed']);
- $code = $picked['response']->getStatusCode();
- $meta = $picked['response']->getMeta();
- $headers = $picked['response']->getHeaders();
- $response = new \OC\OCS\Result($data, $code, $meta['message'], $headers);
- return $response;
- } elseif(!empty($shipped['succeeded'])) {
- $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']);
- } elseif(!empty($thirdparty['failed'])) {
- // Merge failed responses if more than one
- $data = array();
- foreach($thirdparty['failed'] as $failure) {
- $data = array_merge_recursive($data, $failure['response']->getData());
- }
- $picked = reset($thirdparty['failed']);
- $code = $picked['response']->getStatusCode();
- $meta = $picked['response']->getMeta();
- $headers = $picked['response']->getHeaders();
- $response = new \OC\OCS\Result($data, $code, $meta['message'], $headers);
- return $response;
- } else {
- $responses = $thirdparty['succeeded'];
- }
- // Merge the successful responses
- $data = [];
- $codes = [];
- $header = [];
-
- foreach($responses as $response) {
- if($response['shipped']) {
- $data = array_merge_recursive($response['response']->getData(), $data);
- } else {
- $data = array_merge_recursive($data, $response['response']->getData());
- }
- $header = array_merge_recursive($header, $response['response']->getHeaders());
- $codes[] = ['code' => $response['response']->getStatusCode(),
- 'meta' => $response['response']->getMeta()];
- }
-
- // Use any non 100 status codes
- $statusCode = 100;
- $statusMessage = null;
- foreach($codes as $code) {
- if($code['code'] != 100) {
- $statusCode = $code['code'];
- $statusMessage = $code['meta']['message'];
- break;
- }
- }
-
- return new \OC\OCS\Result($data, $statusCode, $statusMessage, $header);
- }
-
- /**
- * authenticate the api call
- * @param array $action the action details as supplied to OC_API::register()
- * @return bool
- */
- private static function isAuthorised($action) {
- $level = $action['authlevel'];
- switch($level) {
- case API::GUEST_AUTH:
- // Anyone can access
- return true;
- case API::USER_AUTH:
- // User required
- return self::loginUser();
- case API::SUBADMIN_AUTH:
- // Check for subadmin
- $user = self::loginUser();
- if(!$user) {
- return false;
- } else {
- $userObject = \OC::$server->getUserSession()->getUser();
- if($userObject === null) {
- return false;
- }
- $isSubAdmin = \OC::$server->getGroupManager()->getSubAdmin()->isSubAdmin($userObject);
- $admin = OC_User::isAdminUser($user);
- if($isSubAdmin || $admin) {
- return true;
- } else {
- return false;
- }
- }
- case API::ADMIN_AUTH:
- // Check for admin
- $user = self::loginUser();
- if(!$user) {
- return false;
- } else {
- return OC_User::isAdminUser($user);
- }
- default:
- // oops looks like invalid level supplied
- return false;
- }
- }
-
- /**
- * http basic auth
- * @return string|false (username, or false on failure)
- */
- private static function loginUser() {
- if(self::$isLoggedIn === true) {
- return \OC_User::getUser();
- }
-
- // reuse existing login
- $loggedIn = \OC::$server->getUserSession()->isLoggedIn();
- if ($loggedIn === true) {
- if (\OC::$server->getTwoFactorAuthManager()->needsSecondFactor(\OC::$server->getUserSession()->getUser())) {
- // Do not allow access to OCS until the 2FA challenge was solved successfully
- return false;
- }
- $ocsApiRequest = isset($_SERVER['HTTP_OCS_APIREQUEST']) ? $_SERVER['HTTP_OCS_APIREQUEST'] === 'true' : false;
- if ($ocsApiRequest) {
-
- // initialize the user's filesystem
- \OC_Util::setupFS(\OC_User::getUser());
- self::$isLoggedIn = true;
-
- return OC_User::getUser();
- }
- return false;
- }
-
- // basic auth - because OC_User::login will create a new session we shall only try to login
- // if user and pass are set
- $userSession = \OC::$server->getUserSession();
- $request = \OC::$server->getRequest();
- try {
- if ($userSession->tryTokenLogin($request)
- || $userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
- self::$logoutRequired = true;
- } else {
- return false;
- }
- // initialize the user's filesystem
- \OC_Util::setupFS(\OC_User::getUser());
- self::$isLoggedIn = true;
-
- return \OC_User::getUser();
- } catch (\OC\User\LoginException $e) {
- return false;
- }
- }
-
- /**
* respond to a call
* @param \OC\OCS\Result $result
* @param string $format the format xml|json
@@ -365,7 +88,7 @@ class OC_API {
} else {
header('WWW-Authenticate: Basic realm="Authorisation Required"');
}
- header('HTTP/1.0 401 Unauthorized');
+ http_response_code(401);
}
foreach($result->getHeaders() as $name => $value) {
@@ -378,7 +101,7 @@ class OC_API {
$statusCode = self::mapStatusCodes($result->getStatusCode());
if (!is_null($statusCode)) {
$meta['statuscode'] = $statusCode;
- OC_Response::setStatus($statusCode);
+ http_response_code($statusCode);
}
}
diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php
index b19d63f560e..0a5d31a9873 100644
--- a/lib/private/legacy/app.php
+++ b/lib/private/legacy/app.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
* @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
@@ -55,6 +56,7 @@ use OC\DB\MigrationService;
use OC\Installer;
use OC\Repair;
use OCP\App\ManagerEvent;
+use OCP\ILogger;
/**
* This class manages the apps. It allows them to register and integrate in the
@@ -62,21 +64,21 @@ use OCP\App\ManagerEvent;
* upgrading and removing apps.
*/
class OC_App {
- static private $adminForms = array();
- static private $personalForms = array();
- static private $appTypes = array();
- static private $loadedApps = array();
- static private $altLogin = array();
+ static private $adminForms = [];
+ static private $personalForms = [];
+ static private $appTypes = [];
+ static private $loadedApps = [];
+ static private $altLogin = [];
static private $alreadyRegistered = [];
const officialApp = 200;
/**
* clean the appId
*
- * @param string|boolean $app AppId that needs to be cleaned
+ * @param string $app AppId that needs to be cleaned
* @return string
*/
- public static function cleanAppId($app) {
+ public static function cleanAppId(string $app): string {
return str_replace(array('\0', '/', '\\', '..'), '', $app);
}
@@ -86,23 +88,23 @@ class OC_App {
* @param string $app
* @return bool
*/
- public static function isAppLoaded($app) {
+ public static function isAppLoaded(string $app): bool {
return in_array($app, self::$loadedApps, true);
}
/**
* loads all apps
*
- * @param string[] | string | null $types
+ * @param string[] $types
* @return bool
*
* This function walks through the ownCloud directory and loads all apps
* it can find. A directory contains an app if the file /appinfo/info.xml
* exists.
*
- * if $types is set, only apps of those types will be loaded
+ * if $types is set to non-empty array, only apps of those types will be loaded
*/
- public static function loadApps($types = null) {
+ public static function loadApps(array $types = []): bool {
if (\OC::$server->getSystemConfig()->getValue('maintenance', false)) {
return false;
}
@@ -120,7 +122,7 @@ class OC_App {
// prevent app.php from printing output
ob_start();
foreach ($apps as $app) {
- if ((is_null($types) or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) {
+ if (($types === [] or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) {
self::loadApp($app);
}
}
@@ -133,8 +135,9 @@ class OC_App {
* load a single app
*
* @param string $app
+ * @throws Exception
*/
- public static function loadApp($app) {
+ public static function loadApp(string $app) {
self::$loadedApps[] = $app;
$appPath = self::getAppPath($app);
if($appPath === false) {
@@ -146,13 +149,14 @@ class OC_App {
if (is_file($appPath . '/appinfo/app.php')) {
\OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
- self::requireAppFile($app);
- if (self::isType($app, array('authentication'))) {
- // since authentication apps affect the "is app enabled for group" check,
- // the enabled apps cache needs to be cleared to make sure that the
- // next time getEnableApps() is called it will also include apps that were
- // enabled for groups
- self::$enabledAppsCache = array();
+ try {
+ self::requireAppFile($app);
+ } catch (Error $ex) {
+ \OC::$server->getLogger()->logException($ex);
+ if (!\OC::$server->getAppManager()->isShipped($app)) {
+ // Only disable apps which are not shipped
+ \OC::$server->getAppManager()->disableApp($app);
+ }
}
\OC::$server->getEventLogger()->end('load_app_' . $app);
}
@@ -218,7 +222,7 @@ class OC_App {
* @param string $app
* @param string $path
*/
- public static function registerAutoloading($app, $path) {
+ public static function registerAutoloading(string $app, string $path) {
$key = $app . '-' . $path;
if(isset(self::$alreadyRegistered[$key])) {
return;
@@ -248,31 +252,21 @@ class OC_App {
* Load app.php from the given app
*
* @param string $app app name
+ * @throws Error
*/
- private static function requireAppFile($app) {
- try {
- // encapsulated here to avoid variable scope conflicts
- require_once $app . '/appinfo/app.php';
- } catch (Error $ex) {
- \OC::$server->getLogger()->logException($ex);
- if (!\OC::$server->getAppManager()->isShipped($app)) {
- // Only disable apps which are not shipped
- self::disable($app);
- }
- }
+ private static function requireAppFile(string $app) {
+ // encapsulated here to avoid variable scope conflicts
+ require_once $app . '/appinfo/app.php';
}
/**
* check if an app is of a specific type
*
* @param string $app
- * @param string|array $types
+ * @param array $types
* @return bool
*/
- public static function isType($app, $types) {
- if (is_string($types)) {
- $types = array($types);
- }
+ public static function isType(string $app, array $types): bool {
$appTypes = self::getAppTypes($app);
foreach ($types as $type) {
if (array_search($type, $appTypes) !== false) {
@@ -288,7 +282,7 @@ class OC_App {
* @param string $app
* @return array
*/
- private static function getAppTypes($app) {
+ private static function getAppTypes(string $app): array {
//load the cache
if (count(self::$appTypes) == 0) {
self::$appTypes = \OC::$server->getAppConfig()->getValues(false, 'types');
@@ -296,16 +290,17 @@ class OC_App {
if (isset(self::$appTypes[$app])) {
return explode(',', self::$appTypes[$app]);
- } else {
- return array();
}
+
+ return [];
}
/**
* read app types from info.xml and cache them in the database
*/
- public static function setAppTypes($app) {
- $appData = self::getAppInfo($app);
+ public static function setAppTypes(string $app) {
+ $appManager = \OC::$server->getAppManager();
+ $appData = $appManager->getAppInfo($app);
if(!is_array($appData)) {
return;
}
@@ -317,22 +312,18 @@ class OC_App {
$appData['types'] = [];
}
- \OC::$server->getConfig()->setAppValue($app, 'types', $appTypes);
+ $config = \OC::$server->getConfig();
+ $config->setAppValue($app, 'types', $appTypes);
- if (\OC::$server->getAppManager()->hasProtectedAppType($appData['types'])) {
- $enabled = \OC::$server->getConfig()->getAppValue($app, 'enabled', 'yes');
+ if ($appManager->hasProtectedAppType($appData['types'])) {
+ $enabled = $config->getAppValue($app, 'enabled', 'yes');
if ($enabled !== 'yes' && $enabled !== 'no') {
- \OC::$server->getConfig()->setAppValue($app, 'enabled', 'yes');
+ $config->setAppValue($app, 'enabled', 'yes');
}
}
}
/**
- * get all enabled apps
- */
- protected static $enabledAppsCache = array();
-
- /**
* Returns apps enabled for the current user.
*
* @param bool $forceRefresh whether to refresh the cache
@@ -340,9 +331,9 @@ class OC_App {
* currently logged in one
* @return string[]
*/
- public static function getEnabledApps($forceRefresh = false, $all = false) {
+ public static function getEnabledApps(bool $forceRefresh = false, bool $all = false): array {
if (!\OC::$server->getSystemConfig()->getValue('installed', false)) {
- return array();
+ return [];
}
// in incognito mode or when logged out, $user will be false,
// which is also the case during an upgrade
@@ -375,7 +366,7 @@ class OC_App {
*
* This function checks whether or not an app is enabled.
*/
- public static function isEnabled($app) {
+ public static function isEnabled(string $app): bool {
return \OC::$server->getAppManager()->isEnabledForUser($app);
}
@@ -389,11 +380,11 @@ class OC_App {
*
* This function set an app as enabled in appconfig.
*/
- public function enable($appId,
- $groups = null) {
- self::$enabledAppsCache = []; // flush
+ public function enable(string $appId,
+ array $groups = []) {
// Check if app is already downloaded
+ /** @var Installer $installer */
$installer = \OC::$server->query(Installer::class);
$isDownloaded = $installer->isDownloaded($appId);
@@ -404,7 +395,7 @@ class OC_App {
$installer->installApp($appId);
$appManager = \OC::$server->getAppManager();
- if (!is_null($groups)) {
+ if ($groups !== []) {
$groupManager = \OC::$server->getGroupManager();
$groupsList = [];
foreach ($groups as $group) {
@@ -420,55 +411,6 @@ class OC_App {
}
/**
- * This function set an app as disabled in appconfig.
- *
- * @param string $app app
- * @throws Exception
- */
- public static function disable($app) {
- // flush
- self::$enabledAppsCache = array();
-
- // run uninstall steps
- $appData = OC_App::getAppInfo($app);
- if (!is_null($appData)) {
- OC_App::executeRepairSteps($app, $appData['repair-steps']['uninstall']);
- }
-
- // emit disable hook - needed anymore ?
- \OC_Hook::emit('OC_App', 'pre_disable', array('app' => $app));
-
- // finally disable it
- $appManager = \OC::$server->getAppManager();
- $appManager->disableApp($app);
- }
-
- // This is private as well. It simply works, so don't ask for more details
- private static function proceedNavigation($list) {
- usort($list, function($a, $b) {
- if (isset($a['order']) && isset($b['order'])) {
- return ($a['order'] < $b['order']) ? -1 : 1;
- } else if (isset($a['order']) || isset($b['order'])) {
- return isset($a['order']) ? -1 : 1;
- } else {
- return ($a['name'] < $b['name']) ? -1 : 1;
- }
- });
-
- $activeApp = OC::$server->getNavigationManager()->getActiveEntry();
- foreach ($list as $index => &$navEntry) {
- if ($navEntry['id'] == $activeApp) {
- $navEntry['active'] = true;
- } else {
- $navEntry['active'] = false;
- }
- }
- unset($navEntry);
-
- return $list;
- }
-
- /**
* Get the path where to install apps
*
* @return string|false
@@ -484,7 +426,7 @@ class OC_App {
}
}
- \OCP\Util::writeLog('core', 'No application directories are marked as writable.', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'No application directories are marked as writable.', ILogger::ERROR);
return null;
}
@@ -495,18 +437,18 @@ class OC_App {
* @param string $appId
* @return false|string
*/
- public static function findAppInDirectories($appId) {
+ public static function findAppInDirectories(string $appId) {
$sanitizedAppId = self::cleanAppId($appId);
if($sanitizedAppId !== $appId) {
return false;
}
- static $app_dir = array();
+ static $app_dir = [];
if (isset($app_dir[$appId])) {
return $app_dir[$appId];
}
- $possibleApps = array();
+ $possibleApps = [];
foreach (OC::$APPSROOTS as $dir) {
if (file_exists($dir['path'] . '/' . $appId)) {
$possibleApps[] = $dir;
@@ -520,9 +462,9 @@ class OC_App {
$app_dir[$appId] = $dir;
return $dir;
} else {
- $versionToLoad = array();
+ $versionToLoad = [];
foreach ($possibleApps as $possibleApp) {
- $version = self::getAppVersionByPath($possibleApp['path']);
+ $version = self::getAppVersionByPath($possibleApp['path'] . '/' . $appId);
if (empty($versionToLoad) || version_compare($version, $versionToLoad['version'], '>')) {
$versionToLoad = array(
'dir' => $possibleApp,
@@ -543,7 +485,7 @@ class OC_App {
* @param string $appId
* @return string|false
*/
- public static function getAppPath($appId) {
+ public static function getAppPath(string $appId) {
if ($appId === null || trim($appId) === '') {
return false;
}
@@ -561,7 +503,7 @@ class OC_App {
* @param string $appId
* @return string|false
*/
- public static function getAppWebPath($appId) {
+ public static function getAppWebPath(string $appId) {
if (($dir = self::findAppInDirectories($appId)) != false) {
return OC::$WEBROOT . $dir['url'] . '/' . $appId;
}
@@ -576,7 +518,7 @@ class OC_App {
* @return string
* @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppVersion()
*/
- public static function getAppVersion($appId, $useCache = true) {
+ public static function getAppVersion(string $appId, bool $useCache = true): string {
return \OC::$server->getAppManager()->getAppVersion($appId, $useCache);
}
@@ -586,7 +528,7 @@ class OC_App {
* @param string $path
* @return string
*/
- public static function getAppVersionByPath($path) {
+ public static function getAppVersionByPath(string $path): string {
$infoFile = $path . '/appinfo/info.xml';
$appData = \OC::$server->getAppManager()->getAppInfo($infoFile, true);
return isset($appData['version']) ? $appData['version'] : '';
@@ -603,7 +545,7 @@ class OC_App {
* @note all data is read from info.xml, not just pre-defined fields
* @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppInfo()
*/
- public static function getAppInfo($appId, $path = false, $lang = null) {
+ public static function getAppInfo(string $appId, bool $path = false, string $lang = null) {
return \OC::$server->getAppManager()->getAppInfo($appId, $path, $lang);
}
@@ -611,28 +553,28 @@ class OC_App {
* Returns the navigation
*
* @return array
+ * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll()
*
* This function returns an array containing all entries added. The
* entries are sorted by the key 'order' ascending. Additional to the keys
* given for each app the following keys exist:
* - active: boolean, signals if the user is on this navigation entry
*/
- public static function getNavigation() {
- $entries = OC::$server->getNavigationManager()->getAll();
- return self::proceedNavigation($entries);
+ public static function getNavigation(): array {
+ return OC::$server->getNavigationManager()->getAll();
}
/**
* Returns the Settings Navigation
*
* @return string[]
+ * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll('settings')
*
* This function returns an array containing all settings pages added. The
* entries are sorted by the key 'order' ascending.
*/
- public static function getSettingsNavigation() {
- $entries = OC::$server->getNavigationManager()->getAll('settings');
- return self::proceedNavigation($entries);
+ public static function getSettingsNavigation(): array {
+ return OC::$server->getNavigationManager()->getAll('settings');
}
/**
@@ -640,7 +582,7 @@ class OC_App {
*
* @return string
*/
- public static function getCurrentApp() {
+ public static function getCurrentApp(): string {
$request = \OC::$server->getRequest();
$script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1);
$topFolder = substr($script, 0, strpos($script, '/') ?: 0);
@@ -652,7 +594,7 @@ class OC_App {
}
if ($topFolder == 'apps') {
$length = strlen($topFolder);
- return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1);
+ return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1) ?: '';
} else {
return $topFolder;
}
@@ -662,8 +604,8 @@ class OC_App {
* @param string $type
* @return array
*/
- public static function getForms($type) {
- $forms = array();
+ public static function getForms(string $type): array {
+ $forms = [];
switch ($type) {
case 'admin':
$source = self::$adminForms;
@@ -672,7 +614,7 @@ class OC_App {
$source = self::$personalForms;
break;
default:
- return array();
+ return [];
}
foreach ($source as $form) {
$forms[] = include $form;
@@ -686,7 +628,7 @@ class OC_App {
* @param string $app
* @param string $page
*/
- public static function registerAdmin($app, $page) {
+ public static function registerAdmin(string $app, string $page) {
self::$adminForms[] = $app . '/' . $page . '.php';
}
@@ -695,7 +637,7 @@ class OC_App {
* @param string $app
* @param string $page
*/
- public static function registerPersonal($app, $page) {
+ public static function registerPersonal(string $app, string $page) {
self::$personalForms[] = $app . '/' . $page . '.php';
}
@@ -709,7 +651,7 @@ class OC_App {
/**
* @return array
*/
- public static function getAlternativeLogIns() {
+ public static function getAlternativeLogIns(): array {
return self::$altLogin;
}
@@ -719,13 +661,13 @@ class OC_App {
* @return array an array of app names (string IDs)
* @todo: change the name of this method to getInstalledApps, which is more accurate
*/
- public static function getAllApps() {
+ public static function getAllApps(): array {
- $apps = array();
+ $apps = [];
foreach (OC::$APPSROOTS as $apps_dir) {
if (!is_readable($apps_dir['path'])) {
- \OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], \OCP\Util::WARN);
+ \OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], ILogger::WARN);
continue;
}
$dh = opendir($apps_dir['path']);
@@ -751,13 +693,13 @@ class OC_App {
*
* @return array
*/
- public function listAllApps() {
+ public function listAllApps(): array {
$installedApps = OC_App::getAllApps();
$appManager = \OC::$server->getAppManager();
//we don't want to show configuration for these
$blacklist = $appManager->getAlwaysEnabledApps();
- $appList = array();
+ $appList = [];
$langCode = \OC::$server->getL10N('core')->getLanguageCode();
$urlGenerator = \OC::$server->getURLGenerator();
@@ -766,12 +708,12 @@ class OC_App {
$info = OC_App::getAppInfo($app, false, $langCode);
if (!is_array($info)) {
- \OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', ILogger::ERROR);
continue;
}
if (!isset($info['name'])) {
- \OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', ILogger::ERROR);
continue;
}
@@ -832,7 +774,7 @@ class OC_App {
return $appList;
}
- public static function shouldUpgrade($app) {
+ public static function shouldUpgrade(string $app): bool {
$versions = self::getAppVersions();
$currentVersion = OC_App::getAppVersion($app);
if ($currentVersion && isset($versions[$app])) {
@@ -852,7 +794,7 @@ class OC_App {
* @param string $version2 version to take the number of parts from
* @return string shortened $version1
*/
- private static function adjustVersionParts($version1, $version2) {
+ private static function adjustVersionParts(string $version1, string $version2): string {
$version1 = explode('.', $version1);
$version2 = explode('.', $version2);
// reduce $version1 to match the number of parts in $version2
@@ -882,7 +824,7 @@ class OC_App {
*
* @return boolean true if compatible, otherwise false
*/
- public static function isAppCompatible($ocVersion, $appInfo) {
+ public static function isAppCompatible(string $ocVersion, array $appInfo): bool {
$requireMin = '';
$requireMax = '';
if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) {
@@ -903,10 +845,6 @@ class OC_App {
$requireMax = $appInfo['requiremax'];
}
- if (is_array($ocVersion)) {
- $ocVersion = implode('.', $ocVersion);
- }
-
if (!empty($requireMin)
&& version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<')
) {
@@ -942,13 +880,14 @@ class OC_App {
* @param string $appId
* @return bool
*/
- public static function updateApp($appId) {
+ public static function updateApp(string $appId): bool {
$appPath = self::getAppPath($appId);
if($appPath === false) {
return false;
}
self::registerAutoloading($appId, $appPath);
+ \OC::$server->getAppManager()->clearAppsCache();
$appData = self::getAppInfo($appId);
self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
@@ -962,6 +901,7 @@ class OC_App {
self::executeRepairSteps($appId, $appData['repair-steps']['post-migration']);
self::setupLiveMigrations($appId, $appData['repair-steps']['live-migration']);
// update appversion in app manager
+ \OC::$server->getAppManager()->clearAppsCache();
\OC::$server->getAppManager()->getAppVersion($appId, false);
// run upgrade code
@@ -1001,7 +941,7 @@ class OC_App {
* @param string[] $steps
* @throws \OC\NeedsUpdateException
*/
- public static function executeRepairSteps($appId, array $steps) {
+ public static function executeRepairSteps(string $appId, array $steps) {
if (empty($steps)) {
return;
}
@@ -1035,7 +975,7 @@ class OC_App {
* @param string $appId
* @param string[] $steps
*/
- private static function setupLiveMigrations($appId, array $steps) {
+ private static function setupLiveMigrations(string $appId, array $steps) {
$queue = \OC::$server->getJobList();
foreach ($steps as $step) {
$queue->add('OC\Migration\BackgroundRepair', [
@@ -1048,7 +988,7 @@ class OC_App {
* @param string $appId
* @return \OC\Files\View|false
*/
- public static function getStorage($appId) {
+ public static function getStorage(string $appId) {
if (\OC::$server->getAppManager()->isEnabledForUser($appId)) { //sanity check
if (\OC::$server->getUserSession()->isLoggedIn()) {
$view = new \OC\Files\View('/' . OC_User::getUser());
@@ -1057,16 +997,21 @@ class OC_App {
}
return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
} else {
- \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', ILogger::ERROR);
return false;
}
} else {
- \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', ILogger::ERROR);
return false;
}
}
- protected static function findBestL10NOption($options, $lang) {
+ protected static function findBestL10NOption(array $options, string $lang): string {
+ // only a single option
+ if (isset($options['@value'])) {
+ return $options['@value'];
+ }
+
$fallback = $similarLangFallback = $englishFallback = false;
$lang = strtolower($lang);
@@ -1118,7 +1063,7 @@ class OC_App {
* @param string $lang
* @return array improved app data
*/
- public static function parseAppInfo(array $data, $lang = null) {
+ public static function parseAppInfo(array $data, $lang = null): array {
if ($lang && isset($data['name']) && is_array($data['name'])) {
$data['name'] = self::findBestL10NOption($data['name'], $lang);
@@ -1143,7 +1088,7 @@ class OC_App {
* @param array $info
* @throws \Exception
*/
- public static function checkAppDependencies($config, $l, $info) {
+ public static function checkAppDependencies(\OCP\IConfig $config, \OCP\IL10N $l, array $info) {
$dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
$missing = $dependencyAnalyzer->analyze($info);
if (!empty($missing)) {
diff --git a/lib/private/legacy/db.php b/lib/private/legacy/db.php
index 7c556baeaeb..7e18cbe1875 100644
--- a/lib/private/legacy/db.php
+++ b/lib/private/legacy/db.php
@@ -28,6 +28,8 @@
*
*/
+use OCP\ILogger;
+
/**
* This class manages the access to the database. It basically is a wrapper for
* Doctrine with some adaptions.
@@ -185,7 +187,7 @@ class OC_DB {
try {
$result = $schemaManager->updateDbFromStructure($file);
} catch (Exception $e) {
- \OCP\Util::writeLog('core', 'Failed to update database structure ('.$e.')', \OCP\Util::FATAL);
+ \OCP\Util::writeLog('core', 'Failed to update database structure ('.$e.')', ILogger::FATAL);
throw $e;
}
return $result;
diff --git a/lib/private/legacy/defaults.php b/lib/private/legacy/defaults.php
index c541e53a48d..3a22c91a8df 100644
--- a/lib/private/legacy/defaults.php
+++ b/lib/private/legacy/defaults.php
@@ -54,15 +54,16 @@ class OC_Defaults {
public function __construct() {
$this->l = \OC::$server->getL10N('lib');
+ $config = \OC::$server->getConfig();
$this->defaultEntity = 'Nextcloud'; /* e.g. company name, used for footers and copyright notices */
$this->defaultName = 'Nextcloud'; /* short name, used when referring to the software */
$this->defaultTitle = 'Nextcloud'; /* can be a longer name, for titles */
$this->defaultBaseUrl = 'https://nextcloud.com';
- $this->defaultSyncClientUrl = 'https://nextcloud.com/install/#install-clients';
- $this->defaultiOSClientUrl = 'https://geo.itunes.apple.com/us/app/nextcloud/id1125420102?mt=8';
- $this->defaultiTunesAppId = '1125420102';
- $this->defaultAndroidClientUrl = 'https://play.google.com/store/apps/details?id=com.nextcloud.client';
+ $this->defaultSyncClientUrl = $config->getSystemValue('customclient_desktop', 'https://nextcloud.com/install/#install-clients');
+ $this->defaultiOSClientUrl = $config->getSystemValue('customclient_ios', 'https://geo.itunes.apple.com/us/app/nextcloud/id1125420102?mt=8');
+ $this->defaultiTunesAppId = $config->getSystemValue('customclient_ios_appid', '1125420102');
+ $this->defaultAndroidClientUrl = $config->getSystemValue('customclient_android', 'https://play.google.com/store/apps/details?id=com.nextcloud.client');
$this->defaultDocBaseUrl = 'https://docs.nextcloud.com';
$this->defaultDocVersion = '14'; // used to generate doc links
$this->defaultSlogan = $this->l->t('a safe home for all your data');
diff --git a/lib/private/legacy/eventsource.php b/lib/private/legacy/eventsource.php
index 1a8061c0ed2..1e68dd24af0 100644
--- a/lib/private/legacy/eventsource.php
+++ b/lib/private/legacy/eventsource.php
@@ -110,13 +110,13 @@ class OC_EventSource implements \OCP\IEventSource {
}
if ($this->fallback) {
$response = '<script type="text/javascript">window.parent.OC.EventSource.fallBackCallBack('
- . $this->fallBackId . ',"' . $type . '",' . OCP\JSON::encode($data) . ')</script>' . PHP_EOL;
+ . $this->fallBackId . ',"' . $type . '",' . OC_JSON::encode($data) . ')</script>' . PHP_EOL;
echo $response;
} else {
if ($type) {
echo 'event: ' . $type . PHP_EOL;
}
- echo 'data: ' . OCP\JSON::encode($data) . PHP_EOL;
+ echo 'data: ' . OC_JSON::encode($data) . PHP_EOL;
}
echo PHP_EOL;
flush();
diff --git a/lib/private/legacy/files.php b/lib/private/legacy/files.php
index 24324bca095..159e18c7754 100644
--- a/lib/private/legacy/files.php
+++ b/lib/private/legacy/files.php
@@ -41,6 +41,7 @@
use OC\Files\View;
use OC\Streamer;
+use OCP\ILogger;
use OCP\Lock\ILockingProvider;
/**
@@ -75,12 +76,14 @@ class OC_Files {
private static function sendHeaders($filename, $name, array $rangeArray) {
OC_Response::setContentDispositionHeader($name, 'attachment');
header('Content-Transfer-Encoding: binary', true);
- OC_Response::disableCaching();
+ header('Pragma: public');// enable caching in IE
+ header('Expires: 0');
+ header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
$fileSize = \OC\Files\Filesystem::filesize($filename);
$type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename));
if ($fileSize > -1) {
if (!empty($rangeArray)) {
- header('HTTP/1.1 206 Partial Content', true);
+ http_response_code(206);
header('Accept-Ranges: bytes', true);
if (count($rangeArray) > 1) {
$type = 'multipart/byteranges; boundary='.self::getBoundary();
@@ -142,17 +145,34 @@ class OC_Files {
}
}
- $streamer = new Streamer();
- OC_Util::obEnd();
-
self::lockFiles($view, $dir, $files);
+ /* Calculate filesize and number of files */
+ if ($getType === self::ZIP_FILES) {
+ $fileInfos = array();
+ $fileSize = 0;
+ foreach ($files as $file) {
+ $fileInfo = \OC\Files\Filesystem::getFileInfo($dir . '/' . $file);
+ $fileSize += $fileInfo->getSize();
+ $fileInfos[] = $fileInfo;
+ }
+ $numberOfFiles = self::getNumberOfFiles($fileInfos);
+ } elseif ($getType === self::ZIP_DIR) {
+ $fileInfo = \OC\Files\Filesystem::getFileInfo($dir . '/' . $files);
+ $fileSize = $fileInfo->getSize();
+ $numberOfFiles = self::getNumberOfFiles(array($fileInfo));
+ }
+
+ $streamer = new Streamer(\OC::$server->getRequest(), $fileSize, $numberOfFiles);
+ OC_Util::obEnd();
+
$streamer->sendHeaders($name);
$executionTime = (int)OC::$server->getIniWrapper()->getNumeric('max_execution_time');
if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
@set_time_limit(0);
}
ignore_user_abort(true);
+
if ($getType === self::ZIP_FILES) {
foreach ($files as $file) {
$file = $dir . '/' . $file;
@@ -178,18 +198,18 @@ class OC_Files {
OC::$server->getLogger()->logException($ex);
$l = \OC::$server->getL10N('core');
$hint = method_exists($ex, 'getHint') ? $ex->getHint() : '';
- \OC_Template::printErrorPage($l->t('File is currently busy, please try again later'), $hint);
+ \OC_Template::printErrorPage($l->t('File is currently busy, please try again later'), $hint, 200);
} catch (\OCP\Files\ForbiddenException $ex) {
self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
OC::$server->getLogger()->logException($ex);
$l = \OC::$server->getL10N('core');
- \OC_Template::printErrorPage($l->t('Can\'t read file'), $ex->getMessage());
+ \OC_Template::printErrorPage($l->t('Can\'t read file'), $ex->getMessage(), 200);
} catch (\Exception $ex) {
self::unlockAllTheFiles($dir, $files, $getType, $view, $filename);
OC::$server->getLogger()->logException($ex);
$l = \OC::$server->getL10N('core');
$hint = method_exists($ex, 'getHint') ? $ex->getHint() : '';
- \OC_Template::printErrorPage($l->t('Can\'t read file'), $hint);
+ \OC_Template::printErrorPage($l->t('Can\'t read file'), $hint, 200);
}
}
@@ -266,12 +286,12 @@ class OC_Files {
if (\OC\Files\Filesystem::isReadable($filename)) {
self::sendHeaders($filename, $name, $rangeArray);
} elseif (!\OC\Files\Filesystem::file_exists($filename)) {
- header("HTTP/1.1 404 Not Found");
+ http_response_code(404);
$tmpl = new OC_Template('', '404', 'guest');
$tmpl->printPage();
exit();
} else {
- header("HTTP/1.1 403 Forbidden");
+ http_response_code(403);
die('403 Forbidden');
}
if (isset($params['head']) && $params['head']) {
@@ -301,7 +321,7 @@ class OC_Files {
// file is unseekable
header_remove('Accept-Ranges');
header_remove('Content-Range');
- header("HTTP/1.1 200 OK");
+ http_response_code(200);
self::sendHeaders($filename, $name, array());
$view->readfile($filename);
}
@@ -312,6 +332,29 @@ class OC_Files {
}
/**
+ * Returns the total (recursive) number of files and folders in the given
+ * FileInfos.
+ *
+ * @param \OCP\Files\FileInfo[] $fileInfos the FileInfos to count
+ * @return int the total number of files and folders
+ */
+ private static function getNumberOfFiles($fileInfos) {
+ $numberOfFiles = 0;
+
+ $view = new View();
+
+ while ($fileInfo = array_pop($fileInfos)) {
+ $numberOfFiles++;
+
+ if ($fileInfo->getType() === \OCP\Files\FileInfo::TYPE_FOLDER) {
+ $fileInfos = array_merge($fileInfos, $view->getDirectoryContent($fileInfo->getPath()));
+ }
+ }
+
+ return $numberOfFiles;
+ }
+
+ /**
* @param View $view
* @param string $dir
* @param string[]|string $files
@@ -380,7 +423,7 @@ class OC_Files {
if (!$handle) {
\OCP\Util::writeLog('files',
'Can\'t write upload limit to ' . $filename . '. Please check the file permissions',
- \OCP\Util::WARN);
+ ILogger::WARN);
$success = false;
continue; // try to update as many files as possible
}
diff --git a/lib/private/legacy/group/backend.php b/lib/private/legacy/group/backend.php
deleted file mode 100644
index 534004c97e9..00000000000
--- a/lib/private/legacy/group/backend.php
+++ /dev/null
@@ -1,56 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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/>
- *
- */
-
-/**
- * error code for functions not provided by the group backend
- * @deprecated Use \OC_Group_Backend::NOT_IMPLEMENTED instead
- */
-define('OC_GROUP_BACKEND_NOT_IMPLEMENTED', -501);
-
-/**
- * actions that user backends can define
- */
-/** @deprecated Use \OC_Group_Backend::CREATE_GROUP instead */
-define('OC_GROUP_BACKEND_CREATE_GROUP', 0x00000001);
-/** @deprecated Use \OC_Group_Backend::DELETE_GROUP instead */
-define('OC_GROUP_BACKEND_DELETE_GROUP', 0x00000010);
-/** @deprecated Use \OC_Group_Backend::ADD_TO_GROUP instead */
-define('OC_GROUP_BACKEND_ADD_TO_GROUP', 0x00000100);
-/** @deprecated Use \OC_Group_Backend::REMOVE_FROM_GOUP instead */
-define('OC_GROUP_BACKEND_REMOVE_FROM_GOUP', 0x00001000);
-/** @deprecated Obsolete */
-define('OC_GROUP_BACKEND_GET_DISPLAYNAME', 0x00010000); //OBSOLETE
-/** @deprecated Use \OC_Group_Backend::COUNT_USERS instead */
-define('OC_GROUP_BACKEND_COUNT_USERS', 0x00100000);
-
-/**
- * Abstract base class for user management
- * @deprecated Since 9.1.0 use \OC\Group\Backend
- */
-abstract class OC_Group_Backend extends \OC\Group\Backend {
-}
diff --git a/lib/private/legacy/json.php b/lib/private/legacy/json.php
index 0afa179b3d8..9588834e934 100644
--- a/lib/private/legacy/json.php
+++ b/lib/private/legacy/json.php
@@ -37,18 +37,6 @@
* @deprecated Use a AppFramework JSONResponse instead
*/
class OC_JSON{
- static protected $send_content_type_header = false;
- /**
- * set Content-Type header to jsonrequest
- * @deprecated Use a AppFramework JSONResponse instead
- */
- public static function setContentTypeHeader($type='application/json') {
- if (!self::$send_content_type_header) {
- // We send json data
- header( 'Content-Type: '.$type . '; charset=utf-8');
- self::$send_content_type_header = true;
- }
- }
/**
* Check if the app is enabled, send json error msg if not
@@ -112,21 +100,6 @@ class OC_JSON{
}
/**
- * Check is a given user exists - send json error msg if not
- * @param string $user
- * @deprecated Use a AppFramework JSONResponse instead
- * @suppress PhanDeprecatedFunction
- */
- public static function checkUserExists($user) {
- if (!\OC::$server->getUserManager()->userExists($user)) {
- $l = \OC::$server->getL10N('lib');
- OCP\JSON::error(array('data' => array('message' => $l->t('Unknown user'), 'error' => 'unknown_user' )));
- exit;
- }
- }
-
-
- /**
* Check if the user is a subadmin, send json error msg if not
* @deprecated Use annotation based ACLs from the AppFramework instead
* @suppress PhanDeprecatedFunction
@@ -152,7 +125,8 @@ class OC_JSON{
*/
public static function error($data = array()) {
$data['status'] = 'error';
- self::encodedPrint($data);
+ header( 'Content-Type: application/json; charset=utf-8');
+ echo self::encode($data);
}
/**
@@ -162,7 +136,8 @@ class OC_JSON{
*/
public static function success($data = array()) {
$data['status'] = 'success';
- self::encodedPrint($data);
+ header( 'Content-Type: application/json; charset=utf-8');
+ echo self::encode($data);
}
/**
@@ -175,18 +150,6 @@ class OC_JSON{
}
/**
- * Encode and print $data in json format
- * @deprecated Use a AppFramework JSONResponse instead
- * @suppress PhanDeprecatedFunction
- */
- public static function encodedPrint($data, $setContentType=true) {
- if($setContentType) {
- self::setContentTypeHeader();
- }
- echo self::encode($data);
- }
-
- /**
* Encode JSON
* @deprecated Use a AppFramework JSONResponse instead
*/
diff --git a/lib/private/legacy/response.php b/lib/private/legacy/response.php
index 975ff570485..93023f61e99 100644
--- a/lib/private/legacy/response.php
+++ b/lib/private/legacy/response.php
@@ -31,152 +31,6 @@
*/
class OC_Response {
- const STATUS_FOUND = 304;
- const STATUS_NOT_MODIFIED = 304;
- const STATUS_TEMPORARY_REDIRECT = 307;
- const STATUS_BAD_REQUEST = 400;
- const STATUS_FORBIDDEN = 403;
- const STATUS_NOT_FOUND = 404;
- const STATUS_INTERNAL_SERVER_ERROR = 500;
- const STATUS_SERVICE_UNAVAILABLE = 503;
-
- /**
- * Enable response caching by sending correct HTTP headers
- * @param integer $cache_time time to cache the response
- * >0 cache time in seconds
- * 0 and <0 enable default browser caching
- * null cache indefinitely
- */
- static public function enableCaching($cache_time = null) {
- if (is_numeric($cache_time)) {
- header('Pragma: public');// enable caching in IE
- if ($cache_time > 0) {
- self::setExpiresHeader('PT'.$cache_time.'S');
- header('Cache-Control: max-age='.$cache_time.', must-revalidate');
- }
- else {
- self::setExpiresHeader(0);
- header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
- }
- }
- else {
- header('Cache-Control: cache');
- header('Pragma: cache');
- }
-
- }
-
- /**
- * disable browser caching
- * @see enableCaching with cache_time = 0
- */
- static public function disableCaching() {
- self::enableCaching(0);
- }
-
- /**
- * Set response status
- * @param int $status a HTTP status code, see also the STATUS constants
- */
- static public function setStatus($status) {
- $protocol = \OC::$server->getRequest()->getHttpProtocol();
- switch($status) {
- case self::STATUS_NOT_MODIFIED:
- $status = $status . ' Not Modified';
- break;
- case self::STATUS_TEMPORARY_REDIRECT:
- if ($protocol == 'HTTP/1.1') {
- $status = $status . ' Temporary Redirect';
- break;
- } else {
- $status = self::STATUS_FOUND;
- // fallthrough
- }
- case self::STATUS_FOUND;
- $status = $status . ' Found';
- break;
- case self::STATUS_NOT_FOUND;
- $status = $status . ' Not Found';
- break;
- case self::STATUS_INTERNAL_SERVER_ERROR;
- $status = $status . ' Internal Server Error';
- break;
- case self::STATUS_SERVICE_UNAVAILABLE;
- $status = $status . ' Service Unavailable';
- break;
- }
- header($protocol.' '.$status);
- }
-
- /**
- * Send redirect response
- * @param string $location to redirect to
- */
- static public function redirect($location) {
- self::setStatus(self::STATUS_TEMPORARY_REDIRECT);
- header('Location: '.$location);
- }
-
- /**
- * Set response expire time
- * @param string|DateTime|int $expires date-time when the response expires
- * string for DateInterval from now
- * DateTime object when to expire response
- */
- static public function setExpiresHeader($expires) {
- if (is_string($expires) && $expires[0] == 'P') {
- $interval = $expires;
- $expires = new DateTime('now');
- $expires->add(new DateInterval($interval));
- }
- if ($expires instanceof DateTime) {
- $expires->setTimezone(new DateTimeZone('GMT'));
- $expires = $expires->format(DateTime::RFC2822);
- }
- header('Expires: '.$expires);
- }
-
- /**
- * Checks and set ETag header, when the request matches sends a
- * 'not modified' response
- * @param string $etag token to use for modification check
- */
- static public function setETagHeader($etag) {
- if (empty($etag)) {
- return;
- }
- $etag = '"'.$etag.'"';
- if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
- trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
- self::setStatus(self::STATUS_NOT_MODIFIED);
- exit;
- }
- header('ETag: '.$etag);
- }
-
- /**
- * Checks and set Last-Modified header, when the request matches sends a
- * 'not modified' response
- * @param int|DateTime|string $lastModified time when the response was last modified
- */
- static public function setLastModifiedHeader($lastModified) {
- if (empty($lastModified)) {
- return;
- }
- if (is_int($lastModified)) {
- $lastModified = gmdate(DateTime::RFC2822, $lastModified);
- }
- if ($lastModified instanceof DateTime) {
- $lastModified = $lastModified->format(DateTime::RFC2822);
- }
- if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
- trim($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $lastModified) {
- self::setStatus(self::STATUS_NOT_MODIFIED);
- exit;
- }
- header('Last-Modified: '.$lastModified);
- }
-
/**
* Sets the content disposition header (with possible workarounds)
* @param string $filename file name
@@ -218,25 +72,6 @@ class OC_Response {
}
/**
- * Send file as response, checking and setting caching headers
- * @param string $filepath of file to send
- * @deprecated 8.1.0 - Use \OCP\AppFramework\Http\StreamResponse or another AppFramework controller instead
- */
- static public function sendFile($filepath) {
- $fp = fopen($filepath, 'rb');
- if ($fp) {
- self::setLastModifiedHeader(filemtime($filepath));
- self::setETagHeader(md5_file($filepath));
-
- self::setContentLengthHeader(filesize($filepath));
- fpassthru($fp);
- }
- else {
- self::setStatus(self::STATUS_NOT_FOUND);
- }
- }
-
- /**
* This function adds some security related headers to all requests served via base.php
* The implementation of this function has to happen here to ensure that all third-party
* components (e.g. SabreDAV) also benefit from this headers.
diff --git a/lib/private/legacy/template.php b/lib/private/legacy/template.php
index c5279bff6b8..1505089d561 100644
--- a/lib/private/legacy/template.php
+++ b/lib/private/legacy/template.php
@@ -109,13 +109,16 @@ class OC_Template extends \OC\Template\Base {
}
}
+ OC_Util::addStyle('css-variables', null, true);
OC_Util::addStyle('server', null, true);
OC_Util::addStyle('jquery-ui-fixes',null,true);
OC_Util::addVendorStyle('jquery-ui/themes/base/jquery-ui',null,true);
OC_Util::addVendorStyle('select2/select2', null, true);
OC_Util::addStyle('jquery.ocdialog');
OC_Util::addTranslations("core", null, true);
+ OC_Util::addStyle('search', 'results');
OC_Util::addScript('search', 'search', true);
+ OC_Util::addScript('search', 'searchprovider');
OC_Util::addScript('merged-template-prepend', null, true);
OC_Util::addScript('jquery-ui-fixes');
OC_Util::addScript('files/fileinfo');
@@ -206,6 +209,12 @@ class OC_Template extends \OC\Template\Base {
if( $this->renderAs ) {
$page = new TemplateLayout($this->renderAs, $this->app);
+ if(is_array($additionalParams)) {
+ foreach ($additionalParams as $key => $value) {
+ $page->assign($key, $value);
+ }
+ }
+
// Add custom headers
$headers = '';
foreach(OC_Util::$headers as $header) {
@@ -226,7 +235,7 @@ class OC_Template extends \OC\Template\Base {
$page->assign('headers', $headers);
$page->assign('content', $data);
- return $page->fetchPage();
+ return $page->fetchPage($additionalParams);
}
return $data;
@@ -295,9 +304,10 @@ class OC_Template extends \OC\Template\Base {
* Print a fatal error page and terminates the script
* @param string $error_msg The error message to show
* @param string $hint An optional hint message - needs to be properly escape
+ * @param int $statusCode
* @suppress PhanAccessMethodInternal
*/
- public static function printErrorPage( $error_msg, $hint = '' ) {
+ public static function printErrorPage( $error_msg, $hint = '', $statusCode = 500) {
if (\OC::$server->getAppManager()->isEnabledForUser('theming') && !\OC_App::isAppLoaded('theming')) {
\OC_App::loadApp('theming');
}
@@ -308,6 +318,7 @@ class OC_Template extends \OC\Template\Base {
$hint = '';
}
+ http_response_code($statusCode);
try {
$content = new \OC_Template( '', 'error', 'error', false );
$errors = array(array('error' => $error_msg, 'hint' => $hint));
@@ -318,7 +329,6 @@ class OC_Template extends \OC\Template\Base {
$logger->error("$error_msg $hint", ['app' => 'core']);
$logger->logException($e, ['app' => 'core']);
- header(self::getHttpProtocol() . ' 500 Internal Server Error');
header('Content-Type: text/plain; charset=utf-8');
print("$error_msg $hint");
}
@@ -328,11 +338,12 @@ class OC_Template extends \OC\Template\Base {
/**
* print error page using Exception details
* @param Exception|Throwable $exception
- * @param bool $fetchPage
+ * @param int $statusCode
* @return bool|string
* @suppress PhanAccessMethodInternal
*/
- public static function printExceptionErrorPage($exception, $fetchPage = false) {
+ public static function printExceptionErrorPage($exception, $statusCode = 503) {
+ http_response_code($statusCode);
try {
$request = \OC::$server->getRequest();
$content = new \OC_Template('', 'exception', 'error', false);
@@ -345,16 +356,24 @@ class OC_Template extends \OC\Template\Base {
$content->assign('debugMode', \OC::$server->getSystemConfig()->getValue('debug', false));
$content->assign('remoteAddr', $request->getRemoteAddress());
$content->assign('requestID', $request->getId());
- if ($fetchPage) {
- return $content->fetchPage();
- }
$content->printPage();
} catch (\Exception $e) {
- $logger = \OC::$server->getLogger();
- $logger->logException($exception, ['app' => 'core']);
- $logger->logException($e, ['app' => 'core']);
+ try {
+ $logger = \OC::$server->getLogger();
+ $logger->logException($exception, ['app' => 'core']);
+ $logger->logException($e, ['app' => 'core']);
+ } catch (Throwable $e) {
+ // no way to log it properly - but to avoid a white page of death we send some output
+ header('Content-Type: text/plain; charset=utf-8');
+ print("Internal Server Error\n\n");
+ print("The server encountered an internal error and was unable to complete your request.\n");
+ print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n");
+ print("More details can be found in the server log.\n");
+
+ // and then throw it again to log it at least to the web server error log
+ throw $e;
+ }
- header(self::getHttpProtocol() . ' 500 Internal Server Error');
header('Content-Type: text/plain; charset=utf-8');
print("Internal Server Error\n\n");
print("The server encountered an internal error and was unable to complete your request.\n");
@@ -363,26 +382,4 @@ class OC_Template extends \OC\Template\Base {
}
die();
}
-
- /**
- * This is only here to reduce the dependencies in case of an exception to
- * still be able to print a plain error message.
- *
- * Returns the used HTTP protocol.
- *
- * @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0.
- * @internal Don't use this - use AppFramework\Http\Request->getHttpProtocol instead
- */
- protected static function getHttpProtocol() {
- $claimedProtocol = strtoupper($_SERVER['SERVER_PROTOCOL']);
- $validProtocols = [
- 'HTTP/1.0',
- 'HTTP/1.1',
- 'HTTP/2',
- ];
- if(in_array($claimedProtocol, $validProtocols, true)) {
- return $claimedProtocol;
- }
- return 'HTTP/1.1';
- }
}
diff --git a/lib/private/legacy/template/functions.php b/lib/private/legacy/template/functions.php
index 290ffe120a3..55d3a595689 100644
--- a/lib/private/legacy/template/functions.php
+++ b/lib/private/legacy/template/functions.php
@@ -262,7 +262,7 @@ function preview_icon( $path ) {
* @return string
*/
function publicPreview_icon ( $path, $token ) {
- return \OC::$server->getURLGenerator()->linkToRoute('files_sharing.PublicPreview.getPreview', ['x' => 32, 'y' => 32, 'file' => $path, 't' => $token]);
+ return \OC::$server->getURLGenerator()->linkToRoute('files_sharing.PublicPreview.getPreview', ['x' => 32, 'y' => 32, 'file' => $path, 'token' => $token]);
}
/**
diff --git a/lib/private/legacy/user.php b/lib/private/legacy/user.php
index 8f342281adb..ebb1ff2215b 100644
--- a/lib/private/legacy/user.php
+++ b/lib/private/legacy/user.php
@@ -38,6 +38,8 @@
*
*/
+use OCP\ILogger;
+
/**
* This class provides wrapper methods for user management. Multiple backends are
* supported. User management operations are delegated to the configured backend for
@@ -89,7 +91,7 @@ class OC_User {
case 'database':
case 'mysql':
case 'sqlite':
- \OCP\Util::writeLog('core', 'Adding user backend ' . $backend . '.', \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', 'Adding user backend ' . $backend . '.', ILogger::DEBUG);
self::$_usedBackends[$backend] = new \OC\User\Database();
\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
break;
@@ -98,7 +100,7 @@ class OC_User {
\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
break;
default:
- \OCP\Util::writeLog('core', 'Adding default user backend ' . $backend . '.', \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', 'Adding default user backend ' . $backend . '.', ILogger::DEBUG);
$className = 'OC_USER_' . strtoupper($backend);
self::$_usedBackends[$backend] = new $className();
\OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]);
@@ -143,10 +145,10 @@ class OC_User {
self::useBackend($backend);
self::$_setupedBackends[] = $i;
} else {
- \OCP\Util::writeLog('core', 'User backend ' . $class . ' already initialized.', \OCP\Util::DEBUG);
+ \OCP\Util::writeLog('core', 'User backend ' . $class . ' already initialized.', ILogger::DEBUG);
}
} else {
- \OCP\Util::writeLog('core', 'User backend ' . $class . ' not found.', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('core', 'User backend ' . $class . ' not found.', ILogger::ERROR);
}
}
}
@@ -312,6 +314,8 @@ class OC_User {
*
* @param string $uid
* @return string|bool uid or false
+ * @deprecated 8.1.0 fetch \OCP\IUser (has getDisplayName()) by using method
+ * get() of \OCP\IUserManager - \OC::$server->getUserManager()
*/
public static function getDisplayName($uid = null) {
if ($uid) {
@@ -367,25 +371,6 @@ class OC_User {
}
/**
- * Get a list of all users
- *
- * @return array an array of all uids
- *
- * Get a list of all users.
- * @param string $search
- * @param integer $limit
- * @param integer $offset
- */
- public static function getUsers($search = '', $limit = null, $offset = null) {
- $users = \OC::$server->getUserManager()->search($search, $limit, $offset);
- $uids = array();
- foreach ($users as $user) {
- $uids[] = $user->getUID();
- }
- return $uids;
- }
-
- /**
* Get a list of all users display name
*
* @param string $search
diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php
index 15f7b2927f3..b285eb382e7 100644
--- a/lib/private/legacy/util.php
+++ b/lib/private/legacy/util.php
@@ -62,6 +62,7 @@
use OCP\IConfig;
use OCP\IGroupManager;
+use OCP\ILogger;
use OCP\IUser;
class OC_Util {
@@ -100,7 +101,7 @@ class OC_Util {
private static function initObjectStoreRootFS($config) {
// check misconfiguration
if (empty($config['class'])) {
- \OCP\Util::writeLog('files', 'No class given for objectstore', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('files', 'No class given for objectstore', ILogger::ERROR);
}
if (!isset($config['arguments'])) {
$config['arguments'] = array();
@@ -134,7 +135,7 @@ class OC_Util {
private static function initObjectStoreMultibucketRootFS($config) {
// check misconfiguration
if (empty($config['class'])) {
- \OCP\Util::writeLog('files', 'No class given for objectstore', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('files', 'No class given for objectstore', ILogger::ERROR);
}
if (!isset($config['arguments'])) {
$config['arguments'] = array();
@@ -258,6 +259,23 @@ class OC_Util {
return $storage;
});
+ \OC\Files\Filesystem::addStorageWrapper('readonly', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) {
+ /*
+ * Do not allow any operations that modify the storage
+ */
+ if ($mount->getOption('readonly', false)) {
+ return new \OC\Files\Storage\Wrapper\PermissionsMask([
+ 'storage' => $storage,
+ 'mask' => \OCP\Constants::PERMISSION_ALL & ~(
+ \OCP\Constants::PERMISSION_UPDATE |
+ \OCP\Constants::PERMISSION_CREATE |
+ \OCP\Constants::PERMISSION_DELETE
+ ),
+ ]);
+ }
+ return $storage;
+ });
+
OC_Hook::emit('OC_Filesystem', 'preSetup', array('user' => $user));
\OC\Files\Filesystem::logWarningWhenAddingStorageWrapper(true);
@@ -409,7 +427,7 @@ class OC_Util {
\OCP\Util::writeLog(
'files_skeleton',
'copying skeleton for '.$userId.' from '.$skeletonDirectory.' to '.$userDirectory->getFullPath('/'),
- \OCP\Util::DEBUG
+ ILogger::DEBUG
);
self::copyr($skeletonDirectory, $userDirectory);
// update the file cache
@@ -669,36 +687,20 @@ class OC_Util {
* @param string $tag tag name of the element
* @param array $attributes array of attributes for the element
* @param string $text the text content for the element
+ * @param bool $prepend prepend the header to the beginning of the list
*/
- public static function addHeader($tag, $attributes, $text=null) {
- self::$headers[] = array(
+ public static function addHeader($tag, $attributes, $text = null, $prepend = false) {
+ $header = array(
'tag' => $tag,
'attributes' => $attributes,
'text' => $text
);
- }
+ if ($prepend === true) {
+ array_unshift (self::$headers, $header);
- /**
- * formats a timestamp in the "right" way
- *
- * @param int $timestamp
- * @param bool $dateOnly option to omit time from the result
- * @param DateTimeZone|string $timeZone where the given timestamp shall be converted to
- * @return string timestamp
- *
- * @deprecated Use \OC::$server->query('DateTimeFormatter') instead
- */
- public static function formatDate($timestamp, $dateOnly = false, $timeZone = null) {
- if ($timeZone !== null && !$timeZone instanceof \DateTimeZone) {
- $timeZone = new \DateTimeZone($timeZone);
- }
-
- /** @var \OC\DateTimeFormatter $formatter */
- $formatter = \OC::$server->query('DateTimeFormatter');
- if ($dateOnly) {
- return $formatter->formatDate($timestamp, 'long', $timeZone);
+ } else {
+ self::$headers[] = $header;
}
- return $formatter->formatDateTime($timestamp, 'long', 'long', $timeZone);
}
/**
@@ -750,7 +752,9 @@ class OC_Util {
$errors[] = array(
'error' => $l->t('Cannot write into "config" directory'),
'hint' => $l->t('This can usually be fixed by giving the webserver write access to the config directory. See %s',
- [$urlGenerator->linkToDocs('admin-dir_permissions')])
+ [ $urlGenerator->linkToDocs('admin-dir_permissions') ]) . '. '
+ . $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it. See %s',
+ [ $urlGenerator->linkToDocs('admin-config') ] )
);
}
}
@@ -1401,7 +1405,7 @@ class OC_Util {
// XCache
if (function_exists('xcache_clear_cache')) {
if (\OC::$server->getIniWrapper()->getBool('xcache.admin.enable_auth')) {
- \OCP\Util::writeLog('core', 'XCache opcode cache will not be cleared because "xcache.admin.enable_auth" is enabled.', \OCP\Util::WARN);
+ \OCP\Util::writeLog('core', 'XCache opcode cache will not be cleared because "xcache.admin.enable_auth" is enabled.', ILogger::WARN);
} else {
@xcache_clear_cache(XC_TYPE_PHP, 0);
}
diff --git a/lib/public/App/IAppManager.php b/lib/public/App/IAppManager.php
index 0c087b61515..b0d04500f35 100644
--- a/lib/public/App/IAppManager.php
+++ b/lib/public/App/IAppManager.php
@@ -51,10 +51,10 @@ interface IAppManager {
*
* @param string $appId
* @param bool $useCache
- * @return mixed
+ * @return string
* @since 14.0.0
*/
- public function getAppVersion(string $appId, bool $useCache = true);
+ public function getAppVersion(string $appId, bool $useCache = true): string;
/**
* Check if an app is enabled for user
@@ -67,7 +67,9 @@ interface IAppManager {
public function isEnabledForUser($appId, $user = null);
/**
- * Check if an app is installed in the instance
+ * Check if an app is enabled in the instance
+ *
+ * Notice: This actually checks if the app is enabled and not only if it is installed.
*
* @param string $appId
* @return bool
@@ -98,6 +100,7 @@ interface IAppManager {
*
* @param string $appId
* @param \OCP\IGroup[] $groups
+ * @throws \Exception
* @since 8.0.0
*/
public function enableAppForGroups($appId, $groups);
diff --git a/lib/public/AppFramework/App.php b/lib/public/AppFramework/App.php
index d5a9075fa3e..b6ed2da5076 100644
--- a/lib/public/AppFramework/App.php
+++ b/lib/public/AppFramework/App.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -33,6 +34,7 @@
namespace OCP\AppFramework;
use OC\AppFramework\Routing\RouteConfig;
+use OCP\Route\IRouter;
/**
@@ -45,6 +47,8 @@ use OC\AppFramework\Routing\RouteConfig;
*/
class App {
+ /** @var IAppContainer */
+ private $container;
/**
* Turns an app id into a namespace by convetion. The id is split at the
@@ -56,7 +60,7 @@ class App {
* @return string the starting namespace for the app
* @since 8.0.0
*/
- public static function buildAppNamespace($appId, $topNamespace='OCA\\') {
+ public static function buildAppNamespace(string $appId, string $topNamespace='OCA\\'): string {
return \OC\AppFramework\App::buildAppNamespace($appId, $topNamespace);
}
@@ -65,17 +69,15 @@ class App {
* @param array $urlParams an array with variables extracted from the routes
* @since 6.0.0
*/
- public function __construct($appName, $urlParams = array()) {
+ public function __construct(string $appName, array $urlParams = []) {
$this->container = new \OC\AppFramework\DependencyInjection\DIContainer($appName, $urlParams);
}
- private $container;
-
/**
* @return IAppContainer
* @since 6.0.0
*/
- public function getContainer() {
+ public function getContainer(): IAppContainer {
return $this->container;
}
@@ -98,7 +100,7 @@ class App {
* @since 6.0.0
* @suppress PhanAccessMethodInternal
*/
- public function registerRoutes($router, $routes) {
+ public function registerRoutes(IRouter $router, array $routes) {
$routeConfig = new RouteConfig($this->container, $router, $routes);
$routeConfig->register();
}
@@ -134,7 +136,7 @@ class App {
* @param string $methodName the method that you want to call
* @since 6.0.0
*/
- public function dispatch($controllerName, $methodName) {
+ public function dispatch(string $controllerName, string $methodName) {
\OC\AppFramework\App::main($controllerName, $methodName, $this->container);
}
}
diff --git a/lib/public/AppFramework/AuthPublicShareController.php b/lib/public/AppFramework/AuthPublicShareController.php
new file mode 100644
index 00000000000..ffd2bddd24b
--- /dev/null
+++ b/lib/public/AppFramework/AuthPublicShareController.php
@@ -0,0 +1,192 @@
+<?php
+/**
+ * @copyright 2018, 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/>.
+ *
+ */
+declare(strict_types=1);
+
+namespace OCP\AppFramework;
+
+use OCP\AppFramework\Http\RedirectResponse;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IRequest;
+use OCP\ISession;
+use OCP\IURLGenerator;
+
+/**
+ * Base controller for interactive public shares
+ *
+ * It will verify if the user is properly authenticated to the share. If not the
+ * user will be redirected to an authentication page.
+ *
+ * Use this for a controller that is to be called directly by a user. So the
+ * normal public share page for files/calendars etc.
+ *
+ * @since 14.0.0
+ */
+abstract class AuthPublicShareController extends PublicShareController {
+
+ /** @var IURLGenerator */
+ protected $urlGenerator;
+
+ /**
+ * @since 14.0.0
+ */
+ public function __construct(string $appName,
+ IRequest $request,
+ ISession $session,
+ IURLGenerator $urlGenerator) {
+ parent::__construct($appName, $request, $session);
+
+ $this->urlGenerator = $urlGenerator;
+ }
+
+ /**
+ * @PublicPage
+ * @NoCSRFRequired
+ *
+ * Show the authentication page
+ * The form has to submit to the authenticate method route
+ *
+ * @since 14.0.0
+ */
+ public function showAuthenticate(): TemplateResponse {
+ return new TemplateResponse('core', 'publicshareauth', [], 'guest');
+ }
+
+ /**
+ * The template to show when authentication failed
+ *
+ * @since 14.0.0
+ */
+ protected function showAuthFailed(): TemplateResponse {
+ return new TemplateResponse('core', 'publicshareauth', ['wrongpw' => true], 'guest');
+ }
+
+ /**
+ * Verify the password
+ *
+ * @since 14.0.0
+ */
+ abstract protected function verifyPassword(string $password): bool;
+
+ /**
+ * Function called after failed authentication
+ *
+ * You can use this to do some logging for example
+ *
+ * @since 14.0.0
+ */
+ protected function authFailed() {
+ }
+
+ /**
+ * Function called after successfull authentication
+ *
+ * You can use this to do some logging for example
+ *
+ * @since 14.0.0
+ */
+ protected function authSucceeded() {
+ }
+
+ /**
+ * @UseSession
+ * @PublicPage
+ * @BruteForceProtection(action=publicLinkAuth)
+ *
+ * Authenticate the share
+ *
+ * @since 14.0.0
+ */
+ final public function authenticate(string $password = '') {
+ // Already authenticated
+ if ($this->isAuthenticated()) {
+ return $this->getRedirect();
+ }
+
+ if (!$this->verifyPassword($password)) {
+ $this->authFailed();
+ $response = $this->showAuthFailed();
+ $response->throttle();
+ return $response;
+ }
+
+ $this->session->regenerateId(true, true);
+ $response = $this->getRedirect();
+
+ $this->session->set('public_link_authenticated_token', $this->getToken());
+ $this->session->set('public_link_authenticated_password_hash', $this->getPasswordHash());
+
+ $this->authSucceeded();
+
+ return $response;
+ }
+
+ /**
+ * Default landing page
+ *
+ * @since 14.0.0
+ */
+ abstract public function showShare(): TemplateResponse;
+
+ /**
+ * @since 14.0.0
+ */
+ final public function getAuthenticationRedirect(string $redirect): RedirectResponse {
+ return new RedirectResponse(
+ $this->urlGenerator->linkToRoute($this->getRoute('showAuthenticate'), ['token' => $this->getToken(), 'redirect' => $redirect])
+ );
+ }
+
+ /**
+ * @since 14.0.0
+ */
+ private function getRoute(string $function): string {
+ $app = strtolower($this->appName);
+ $class = strtolower((new \ReflectionClass($this))->getShortName());
+
+ return $app . '.' . $class . '.' . $function;
+ }
+
+ /**
+ * @since 14.0.0
+ */
+ private function getRedirect(): RedirectResponse {
+ //Get all the stored redirect parameters:
+ $params = $this->session->get('public_link_authenticate_redirect');
+
+ $route = $this->getRoute('showShare');
+
+ if ($params === null) {
+ $params = [
+ 'token' => $this->getToken(),
+ ];
+ } else {
+ $params = json_decode($params, true);
+ if (isset($params['_route'])) {
+ $route = $params['_route'];
+ unset($params['_route']);
+ }
+ }
+
+ return new RedirectResponse($this->urlGenerator->linkToRoute($route, $params));
+ }
+}
diff --git a/lib/public/AppFramework/Db/Mapper.php b/lib/public/AppFramework/Db/Mapper.php
index b008702ba54..6910757add0 100644
--- a/lib/public/AppFramework/Db/Mapper.php
+++ b/lib/public/AppFramework/Db/Mapper.php
@@ -34,6 +34,7 @@ use OCP\IDBConnection;
* Simple parent class for inheriting your data access layer from. This class
* may be subject to change in the future
* @since 7.0.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
abstract class Mapper {
@@ -47,6 +48,7 @@ abstract class Mapper {
* @param string $entityClass the name of the entity that the sql should be
* mapped to queries without using sql
* @since 7.0.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
public function __construct(IDBConnection $db, $tableName, $entityClass=null){
$this->db = $db;
@@ -65,6 +67,7 @@ abstract class Mapper {
/**
* @return string the table name
* @since 7.0.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
public function getTableName(){
return $this->tableName;
@@ -76,6 +79,7 @@ abstract class Mapper {
* @param Entity $entity the entity that should be deleted
* @return Entity the deleted entity
* @since 7.0.0 - return value added in 8.1.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
public function delete(Entity $entity){
$sql = 'DELETE FROM `' . $this->tableName . '` WHERE `id` = ?';
@@ -90,6 +94,7 @@ abstract class Mapper {
* @param Entity $entity the entity that should be created
* @return Entity the saved entity with the set id
* @since 7.0.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
public function insert(Entity $entity){
// get updated fields to save, fields have to be set using a setter to
@@ -139,6 +144,7 @@ abstract class Mapper {
* @param Entity $entity the entity that should be created
* @return Entity the saved entity with the set id
* @since 7.0.0 - return value was added in 8.0.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
public function update(Entity $entity){
// if entity wasn't changed it makes no sense to run a db query
@@ -195,6 +201,7 @@ abstract class Mapper {
* @param array $array
* @return bool true if associative
* @since 8.1.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
private function isAssocArray(array $array) {
return array_values($array) !== $array;
@@ -205,6 +212,7 @@ abstract class Mapper {
* @param $value
* @return int PDO constant
* @since 8.1.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
private function getPDOType($value) {
switch (gettype($value)) {
@@ -226,6 +234,7 @@ abstract class Mapper {
* @param int $offset from which row we want to start
* @return \PDOStatement the database query result
* @since 7.0.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
protected function execute($sql, array $params=[], $limit=null, $offset=null){
$query = $this->db->prepare($sql, $limit, $offset);
@@ -249,7 +258,6 @@ abstract class Mapper {
return $query;
}
-
/**
* Returns an db result and throws exceptions when there are more or less
* results
@@ -262,6 +270,7 @@ abstract class Mapper {
* @throws MultipleObjectsReturnedException if more than one item exist
* @return array the result as row
* @since 7.0.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
protected function findOneQuery($sql, array $params=[], $limit=null, $offset=null){
$stmt = $this->execute($sql, $params, $limit, $offset);
@@ -297,6 +306,7 @@ abstract class Mapper {
* @param int $offset from which row we want to start
* @return string formatted error message string
* @since 9.1.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
private function buildDebugMessage($msg, $sql, array $params=[], $limit=null, $offset=null) {
return $msg .
@@ -313,6 +323,7 @@ abstract class Mapper {
* @param array $row the row which should be converted to an entity
* @return Entity the entity
* @since 7.0.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
protected function mapRowToEntity($row) {
return call_user_func($this->entityClass .'::fromRow', $row);
@@ -327,6 +338,7 @@ abstract class Mapper {
* @param int $offset from which row we want to start
* @return array all fetched entities
* @since 7.0.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
protected function findEntities($sql, array $params=[], $limit=null, $offset=null) {
$stmt = $this->execute($sql, $params, $limit, $offset);
@@ -354,6 +366,7 @@ abstract class Mapper {
* @throws MultipleObjectsReturnedException if more than one item exist
* @return Entity the entity
* @since 7.0.0
+ * @deprecated 14.0.0 Move over to QBMapper
*/
protected function findEntity($sql, array $params=[], $limit=null, $offset=null){
return $this->mapRowToEntity($this->findOneQuery($sql, $params, $limit, $offset));
diff --git a/lib/public/AppFramework/Db/QBMapper.php b/lib/public/AppFramework/Db/QBMapper.php
new file mode 100644
index 00000000000..a9b38732a30
--- /dev/null
+++ b/lib/public/AppFramework/Db/QBMapper.php
@@ -0,0 +1,272 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright 2018, 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 OCP\AppFramework\Db;
+
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+/**
+ * Simple parent class for inheriting your data access layer from. This class
+ * may be subject to change in the future
+ *
+ * @since 14.0.0
+ */
+abstract class QBMapper {
+
+ /** @var string */
+ protected $tableName;
+
+ /** @var string */
+ protected $entityClass;
+
+ /** @var IDBConnection */
+ protected $db;
+
+ /**
+ * @param IDBConnection $db Instance of the Db abstraction layer
+ * @param string $tableName the name of the table. set this to allow entity
+ * @param string $entityClass the name of the entity that the sql should be
+ * mapped to queries without using sql
+ * @since 14.0.0
+ */
+ public function __construct(IDBConnection $db, string $tableName, string $entityClass=null){
+ $this->db = $db;
+ $this->tableName = $tableName;
+
+ // if not given set the entity name to the class without the mapper part
+ // cache it here for later use since reflection is slow
+ if($entityClass === null) {
+ $this->entityClass = str_replace('Mapper', '', \get_class($this));
+ } else {
+ $this->entityClass = $entityClass;
+ }
+ }
+
+
+ /**
+ * @return string the table name
+ * @since 14.0.0
+ */
+ public function getTableName(): string {
+ return $this->tableName;
+ }
+
+
+ /**
+ * Deletes an entity from the table
+ * @param Entity $entity the entity that should be deleted
+ * @return Entity the deleted entity
+ * @since 14.0.0
+ */
+ public function delete(Entity $entity): Entity {
+ $qb = $this->db->getQueryBuilder();
+
+ $qb->delete($this->tableName)
+ ->where(
+ $qb->expr()->eq('id', $qb->createNamedParameter($entity->getId()))
+ );
+ $qb->execute();
+ return $entity;
+ }
+
+
+ /**
+ * Creates a new entry in the db from an entity
+ * @param Entity $entity the entity that should be created
+ * @return Entity the saved entity with the set id
+ * @since 14.0.0
+ * @suppress SqlInjectionChecker
+ */
+ public function insert(Entity $entity): Entity {
+ // get updated fields to save, fields have to be set using a setter to
+ // be saved
+ $properties = $entity->getUpdatedFields();
+
+ $qb = $this->db->getQueryBuilder();
+ $qb->insert($this->tableName);
+
+ // build the fields
+ foreach($properties as $property => $updated) {
+ $column = $entity->propertyToColumn($property);
+ $getter = 'get' . ucfirst($property);
+ $value = $entity->$getter();
+
+ $qb->setValue($column, $qb->createNamedParameter($value));
+ }
+
+ $qb->execute();
+
+ $entity->setId((int) $qb->getLastInsertId());
+
+ return $entity;
+ }
+
+
+
+ /**
+ * Updates an entry in the db from an entity
+ * @throws \InvalidArgumentException if entity has no id
+ * @param Entity $entity the entity that should be created
+ * @return Entity the saved entity with the set id
+ * @since 14.0.0
+ * @suppress SqlInjectionChecker
+ */
+ public function update(Entity $entity): Entity {
+ // if entity wasn't changed it makes no sense to run a db query
+ $properties = $entity->getUpdatedFields();
+ if(\count($properties) === 0) {
+ return $entity;
+ }
+
+ // entity needs an id
+ $id = $entity->getId();
+ if($id === null){
+ throw new \InvalidArgumentException(
+ 'Entity which should be updated has no id');
+ }
+
+ // get updated fields to save, fields have to be set using a setter to
+ // be saved
+ // do not update the id field
+ unset($properties['id']);
+
+ $qb = $this->db->getQueryBuilder();
+ $qb->update($this->tableName);
+
+ // build the fields
+ foreach($properties as $property => $updated) {
+ $column = $entity->propertyToColumn($property);
+ $getter = 'get' . ucfirst($property);
+ $value = $entity->$getter();
+
+ $qb->set($column, $qb->createNamedParameter($value));
+ }
+
+ $qb->where(
+ $qb->expr()->eq('id', $qb->createNamedParameter($id))
+ );
+ $qb->execute();
+
+ return $entity;
+ }
+
+ /**
+ * Returns an db result and throws exceptions when there are more or less
+ * results
+ *
+ * @see findEntity
+ *
+ * @param IQueryBuilder $query
+ * @throws DoesNotExistException if the item does not exist
+ * @throws MultipleObjectsReturnedException if more than one item exist
+ * @return array the result as row
+ * @since 14.0.0
+ */
+ protected function findOneQuery(IQueryBuilder $query): array {
+ $cursor = $query->execute();
+
+ $row = $cursor->fetch();
+ if($row === false) {
+ $cursor->closeCursor();
+ $msg = $this->buildDebugMessage(
+ 'Did expect one result but found none when executing', $query
+ );
+ throw new DoesNotExistException($msg);
+ }
+
+ $row2 = $cursor->fetch();
+ $cursor->closeCursor();
+ if($row2 !== false ) {
+ $msg = $this->buildDebugMessage(
+ 'Did not expect more than one result when executing', $query
+ );
+ throw new MultipleObjectsReturnedException($msg);
+ }
+
+ return $row;
+ }
+
+ /**
+ * @param string $msg
+ * @param IQueryBuilder $sql
+ * @return string
+ * @since 14.0.0
+ */
+ private function buildDebugMessage(string $msg, IQueryBuilder $sql): string {
+ return $msg .
+ ': query "' . $sql->getSQL() . '"; ';
+ }
+
+
+ /**
+ * Creates an entity from a row. Automatically determines the entity class
+ * from the current mapper name (MyEntityMapper -> MyEntity)
+ *
+ * @param array $row the row which should be converted to an entity
+ * @return Entity the entity
+ * @since 14.0.0
+ */
+ protected function mapRowToEntity(array $row): Entity {
+ return \call_user_func($this->entityClass .'::fromRow', $row);
+ }
+
+
+ /**
+ * Runs a sql query and returns an array of entities
+ *
+ * @param IQueryBuilder $query
+ * @return Entity[] all fetched entities
+ * @since 14.0.0
+ */
+ protected function findEntities(IQueryBuilder $query): array {
+ $cursor = $query->execute();
+
+ $entities = [];
+
+ while($row = $cursor->fetch()){
+ $entities[] = $this->mapRowToEntity($row);
+ }
+
+ $cursor->closeCursor();
+
+ return $entities;
+ }
+
+
+ /**
+ * Returns an db result and throws exceptions when there are more or less
+ * results
+ *
+ * @param IQueryBuilder $query
+ * @throws DoesNotExistException if the item does not exist
+ * @throws MultipleObjectsReturnedException if more than one item exist
+ * @return Entity the entity
+ * @since 14.0.0
+ */
+ protected function findEntity(IQueryBuilder $query): Entity {
+ return $this->mapRowToEntity($this->findOneQuery($query));
+ }
+
+}
diff --git a/lib/public/AppFramework/Http/ContentSecurityPolicy.php b/lib/public/AppFramework/Http/ContentSecurityPolicy.php
index 9438c6ead61..c705955bb8a 100644
--- a/lib/public/AppFramework/Http/ContentSecurityPolicy.php
+++ b/lib/public/AppFramework/Http/ContentSecurityPolicy.php
@@ -27,16 +27,19 @@ namespace OCP\AppFramework\Http;
/**
* Class ContentSecurityPolicy is a simple helper which allows applications to
- * modify the Content-Security-Policy sent by ownCloud. Per default only JavaScript,
+ * modify the Content-Security-Policy sent by Nextcloud. Per default only JavaScript,
* stylesheets, images, fonts, media and connections from the same domain
* ('self') are allowed.
*
* Even if a value gets modified above defaults will still get appended. Please
- * notice that ownCloud ships already with sensible defaults and those policies
+ * notice that Nextcloud ships already with sensible defaults and those policies
* should require no modification at all for most use-cases.
*
+ * This class allows unsafe-eval of javascript and unsafe-inline of CSS.
+ *
* @package OCP\AppFramework\Http
* @since 8.1.0
+ * @deprecated 14.0.0 Use one of our stricter CSP policies
*/
class ContentSecurityPolicy extends EmptyContentSecurityPolicy {
/** @var bool Whether inline JS snippets are allowed */
diff --git a/lib/public/AppFramework/Http/Response.php b/lib/public/AppFramework/Http/Response.php
index e47e01349e7..a6f5afd3c18 100644
--- a/lib/public/AppFramework/Http/Response.php
+++ b/lib/public/AppFramework/Http/Response.php
@@ -35,6 +35,7 @@
namespace OCP\AppFramework\Http;
use OCP\AppFramework\Http;
+use OCP\AppFramework\Utility\ITimeFactory;
/**
* Base class for responses. Also used to just send headers.
@@ -95,12 +96,23 @@ class Response {
* @return $this
* @since 6.0.0 - return value was added in 7.0.0
*/
- public function cacheFor($cacheSeconds) {
-
+ public function cacheFor(int $cacheSeconds) {
if($cacheSeconds > 0) {
$this->addHeader('Cache-Control', 'max-age=' . $cacheSeconds . ', must-revalidate');
+
+ // Old scool prama caching
+ $this->addHeader('Pragma', 'public');
+
+ // Set expires header
+ $expires = new \DateTime();
+ /** @var ITimeFactory $time */
+ $time = \OC::$server->query(ITimeFactory::class);
+ $expires->setTimestamp($time->getTime());
+ $expires->add(new \DateInterval('PT'.$cacheSeconds.'S'));
+ $this->addHeader('Expires', $expires->format(\DateTime::RFC2822));
} else {
$this->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
+ unset($this->headers['Expires'], $this->headers['Pragma']);
}
return $this;
@@ -232,11 +244,11 @@ class Response {
/**
* By default renders no output
- * @return string|null
+ * @return string
* @since 6.0.0
*/
public function render() {
- return null;
+ return '';
}
diff --git a/lib/public/AppFramework/Http/StrictContentSecurityPolicy.php b/lib/public/AppFramework/Http/StrictContentSecurityPolicy.php
new file mode 100644
index 00000000000..6713796bdd3
--- /dev/null
+++ b/lib/public/AppFramework/Http/StrictContentSecurityPolicy.php
@@ -0,0 +1,85 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright 2018, 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 OCP\AppFramework\Http;
+
+/**
+ * Class StrictContentSecurityPolicy is a simple helper which allows applications to
+ * modify the Content-Security-Policy sent by Nextcloud. Per default only JavaScript,
+ * stylesheets, images, fonts, media and connections from the same domain
+ * ('self') are allowed.
+ *
+ * Even if a value gets modified above defaults will still get appended. Please
+ * notice that Nextcloud ships already with sensible defaults and those policies
+ * should require no modification at all for most use-cases.
+ *
+ * This class represents out strictest defaults. They may get change from release
+ * to release if more strict CSP directives become available.
+ *
+ * @package OCP\AppFramework\Http
+ * @since 14.0.0
+ */
+class StrictContentSecurityPolicy extends EmptyContentSecurityPolicy {
+ /** @var bool Whether inline JS snippets are allowed */
+ protected $inlineScriptAllowed = false;
+ /** @var bool Whether eval in JS scripts is allowed */
+ protected $evalScriptAllowed = false;
+ /** @var array Domains from which scripts can get loaded */
+ protected $allowedScriptDomains = [
+ '\'self\'',
+ ];
+ /** @var bool Whether inline CSS is allowed */
+ protected $inlineStyleAllowed = false;
+ /** @var array Domains from which CSS can get loaded */
+ protected $allowedStyleDomains = [
+ '\'self\'',
+ ];
+ /** @var array Domains from which images can get loaded */
+ protected $allowedImageDomains = [
+ '\'self\'',
+ 'data:',
+ 'blob:',
+ ];
+ /** @var array Domains to which connections can be done */
+ protected $allowedConnectDomains = [
+ '\'self\'',
+ ];
+ /** @var array Domains from which media elements can be loaded */
+ protected $allowedMediaDomains = [
+ '\'self\'',
+ ];
+ /** @var array Domains from which object elements can be loaded */
+ protected $allowedObjectDomains = [];
+ /** @var array Domains from which iframes can be loaded */
+ protected $allowedFrameDomains = [];
+ /** @var array Domains from which fonts can be loaded */
+ protected $allowedFontDomains = [
+ '\'self\'',
+ ];
+ /** @var array Domains from which web-workers and nested browsing content can load elements */
+ protected $allowedChildSrcDomains = [];
+
+ /** @var array Domains which can embed this Nextcloud instance */
+ protected $allowedFrameAncestors = [];
+}
diff --git a/lib/public/AppFramework/Http/StrictEvalContentSecurityPolicy.php b/lib/public/AppFramework/Http/StrictEvalContentSecurityPolicy.php
new file mode 100644
index 00000000000..b95d2c65e50
--- /dev/null
+++ b/lib/public/AppFramework/Http/StrictEvalContentSecurityPolicy.php
@@ -0,0 +1,51 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright 2018, 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 OCP\AppFramework\Http;
+
+/**
+ * Class StrictInlineContentSecurityPolicy is a simple helper which allows applications to
+ * modify the Content-Security-Policy sent by Nextcloud. Per default only JavaScript,
+ * stylesheets, images, fonts, media and connections from the same domain
+ * ('self') are allowed.
+ *
+ * Even if a value gets modified above defaults will still get appended. Please
+ * notice that Nextcloud ships already with sensible defaults and those policies
+ * should require no modification at all for most use-cases.
+ *
+ * This is a temp helper class from the default ContentSecurityPolicy to allow slow
+ * migration to a stricter CSP. This does not allow unsafe eval.
+ *
+ * @package OCP\AppFramework\Http
+ * @since 14.0.0
+ */
+class StrictEvalContentSecurityPolicy extends ContentSecurityPolicy {
+
+ /**
+ * @since 14.0.0
+ */
+ public function __construct() {
+ $this->evalScriptAllowed = false;
+ }
+}
diff --git a/lib/public/AppFramework/Http/StrictInlineContentSecurityPolicy.php b/lib/public/AppFramework/Http/StrictInlineContentSecurityPolicy.php
new file mode 100644
index 00000000000..65630de7b76
--- /dev/null
+++ b/lib/public/AppFramework/Http/StrictInlineContentSecurityPolicy.php
@@ -0,0 +1,51 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright 2018, 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 OCP\AppFramework\Http;
+
+/**
+ * Class StrictInlineContentSecurityPolicy is a simple helper which allows applications to
+ * modify the Content-Security-Policy sent by Nextcloud. Per default only JavaScript,
+ * stylesheets, images, fonts, media and connections from the same domain
+ * ('self') are allowed.
+ *
+ * Even if a value gets modified above defaults will still get appended. Please
+ * notice that Nextcloud ships already with sensible defaults and those policies
+ * should require no modification at all for most use-cases.
+ *
+ * This is a temp helper class from the default ContentSecurityPolicy to allow slow
+ * migration to a stricter CSP. This does not allow inline styles.
+ *
+ * @package OCP\AppFramework\Http
+ * @since 14.0.0
+ */
+class StrictInlineContentSecurityPolicy extends ContentSecurityPolicy {
+
+ /**
+ * @since 14.0.0
+ */
+ public function __construct() {
+ $this->inlineStyleAllowed = false;
+ }
+}
diff --git a/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php b/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php
new file mode 100644
index 00000000000..4d455a9a755
--- /dev/null
+++ b/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @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\AppFramework\Http\Template;
+
+use OCP\AppFramework\Http\Template\SimpleMenuAction;
+use OCP\Util;
+/**
+ * Class LinkMenuAction
+ *
+ * @package OCP\AppFramework\Http\Template
+ * @since 14.0.0
+ */
+class ExternalShareMenuAction extends SimpleMenuAction {
+
+ /** @var string */
+ private $owner;
+
+ /** @var string */
+ private $displayname;
+
+ /** @var string */
+ private $shareName;
+
+ /**
+ * ExternalShareMenuAction constructor.
+ *
+ * @param string $label
+ * @param string $icon
+ * @param string $owner
+ * @param string $displayname
+ * @param string $shareName
+ * @since 14.0.0
+ */
+ public function __construct(string $label, string $icon, string $owner, string $displayname, string $shareName) {
+ parent::__construct('save', $label, $icon);
+ $this->owner = $owner;
+ $this->displayname = $displayname;
+ $this->shareName = $shareName;
+ }
+
+ /**
+ * @since 14.0.0
+ */
+ public function render(): string {
+ return '<li>' .
+ '<a id="save-external-share" data-protected="false" data-owner-display-name="' . Util::sanitizeHTML($this->displayname) . '" data-owner="' . Util::sanitizeHTML($this->owner) . '" data-name="' . Util::sanitizeHTML($this->shareName) . '">' .
+ '<span class="icon ' . Util::sanitizeHTML($this->getIcon()) . '"></span>' .
+ '<label for="remote_address">' . Util::sanitizeHTML($this->getLabel()) . '</label>' .
+ '<form class="save-form hidden" action="#">' .
+ '<input type="text" id="remote_address" placeholder="user@yourNextcloud.org">' .
+ '<input type="submit" value=" " id="save-button-confirm" class="icon-confirm" disabled="disabled"></button>' .
+ '</form>' .
+ '</a>' .
+ '</li>';
+ }
+}
diff --git a/lib/public/AppFramework/Http/Template/IMenuAction.php b/lib/public/AppFramework/Http/Template/IMenuAction.php
new file mode 100644
index 00000000000..e42d2057981
--- /dev/null
+++ b/lib/public/AppFramework/Http/Template/IMenuAction.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @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\AppFramework\Http\Template;
+
+/**
+ * Interface IMenuAction
+ *
+ * @package OCP\AppFramework\Http\Template
+ * @since 14.0
+ */
+interface IMenuAction {
+
+ /**
+ * @since 14.0.0
+ * @return string
+ */
+ public function getId(): string;
+
+ /**
+ * @since 14.0.0
+ * @return string
+ */
+ public function getLabel(): string;
+
+ /**
+ * @since 14.0.0
+ * @return string
+ */
+ public function getLink(): string;
+
+ /**
+ * @since 14.0.0
+ * @return int
+ */
+ public function getPriority(): int;
+
+ /**
+ * @since 14.0.0
+ * @return string
+ */
+ public function render(): string;
+
+} \ No newline at end of file
diff --git a/lib/public/AppFramework/Http/Template/LinkMenuAction.php b/lib/public/AppFramework/Http/Template/LinkMenuAction.php
new file mode 100644
index 00000000000..c2b432f7d2a
--- /dev/null
+++ b/lib/public/AppFramework/Http/Template/LinkMenuAction.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @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\AppFramework\Http\Template;
+
+use OCP\AppFramework\Http\Template\SimpleMenuAction;
+use OCP\Util;
+
+/**
+ * Class LinkMenuAction
+ *
+ * @package OCP\AppFramework\Http\Template
+ * @since 14.0.0
+ */
+class LinkMenuAction extends SimpleMenuAction {
+
+ /**
+ * LinkMenuAction constructor.
+ *
+ * @param string $label
+ * @param string $icon
+ * @param string $link
+ * @since 14.0.0
+ */
+ public function __construct(string $label, string $icon, string $link) {
+ parent::__construct('directLink-container', $label, $icon, $link);
+ }
+
+ /**
+ * @return string
+ * @since 14.0.0
+ */
+ public function render(): string {
+ return '<li>' .
+ '<a id="directLink-container">' .
+ '<span class="icon ' . Util::sanitizeHTML($this->getIcon()) . '"></span>' .
+ '<label for="directLink">' . Util::sanitizeHTML($this->getLabel()) . '</label>' .
+ '</a>' .
+ '</li>' .
+ '<li>' .
+ '<span class="menuitem">' .
+ '<input id="directLink" type="text" readonly="" value="' . Util::sanitizeHTML($this->getLink()) . '">' .
+ '</span>' .
+ '</li>';
+ }
+}
diff --git a/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php b/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php
new file mode 100644
index 00000000000..a520748a9ea
--- /dev/null
+++ b/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php
@@ -0,0 +1,158 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @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\AppFramework\Http\Template;
+
+use InvalidArgumentException;
+use OCP\AppFramework\Http\TemplateResponse;
+
+/**
+ * Class PublicTemplateResponse
+ *
+ * @package OCP\AppFramework\Http\Template
+ * @since 14.0.0
+ */
+class PublicTemplateResponse extends TemplateResponse {
+
+ private $headerTitle = '';
+ private $headerDetails = '';
+ private $headerActions = [];
+ private $footerVisible = true;
+
+ /**
+ * PublicTemplateResponse constructor.
+ *
+ * @param string $appName
+ * @param string $templateName
+ * @param array $params
+ * @since 14.0.0
+ */
+ public function __construct(string $appName, string $templateName, array $params = array()) {
+ parent::__construct($appName, $templateName, $params, 'public');
+ \OC_Util::addScript('core', 'public/publicpage');
+ }
+
+ /**
+ * @param string $title
+ * @since 14.0.0
+ */
+ public function setHeaderTitle(string $title) {
+ $this->headerTitle = $title;
+ }
+
+ /**
+ * @return string
+ * @since 14.0.0
+ */
+ public function getHeaderTitle(): string {
+ return $this->headerTitle;
+ }
+
+ /**
+ * @param string $details
+ * @since 14.0.0
+ */
+ public function setHeaderDetails(string $details) {
+ $this->headerDetails = $details;
+ }
+
+ /**
+ * @return string
+ * @since 14.0.0
+ */
+ public function getHeaderDetails(): string {
+ return $this->headerDetails;
+ }
+
+ /**
+ * @param array $actions
+ * @since 14.0.0
+ * @throws InvalidArgumentException
+ */
+ public function setHeaderActions(array $actions) {
+ foreach ($actions as $action) {
+ if ($actions instanceof IMenuAction) {
+ throw new InvalidArgumentException('Actions must be of type IMenuAction');
+ }
+ $this->headerActions[] = $action;
+ }
+ usort($this->headerActions, function(IMenuAction $a, IMenuAction $b) {
+ return $a->getPriority() > $b->getPriority();
+ });
+ }
+
+ /**
+ * @return IMenuAction
+ * @since 14.0.0
+ * @throws \Exception
+ */
+ public function getPrimaryAction(): IMenuAction {
+ if ($this->getActionCount() > 0) {
+ return $this->headerActions[0];
+ }
+ throw new \Exception('No header actions have been set');
+ }
+
+ /**
+ * @return int
+ * @since 14.0.0
+ */
+ public function getActionCount(): int {
+ return count($this->headerActions);
+ }
+
+ /**
+ * @return IMenuAction[]
+ * @since 14.0.0
+ */
+ public function getOtherActions(): array {
+ return array_slice($this->headerActions, 1);
+ }
+
+ /**
+ * @since 14.0.0
+ */
+ public function setFooterVisible(bool $visible = false) {
+ $this->footerVisible = $visible;
+ }
+
+ /**
+ * @since 14.0.0
+ */
+ public function getFooterVisible(): bool {
+ return $this->footerVisible;
+ }
+
+ /**
+ * @return string
+ * @since 14.0.0
+ */
+ public function render(): string {
+ $params = array_merge($this->getParams(), [
+ 'template' => $this,
+ ]);
+ $this->setParams($params);
+ return parent::render();
+ }
+
+} \ No newline at end of file
diff --git a/lib/public/AppFramework/Http/Template/SimpleMenuAction.php b/lib/public/AppFramework/Http/Template/SimpleMenuAction.php
new file mode 100644
index 00000000000..60bb268661c
--- /dev/null
+++ b/lib/public/AppFramework/Http/Template/SimpleMenuAction.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @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\AppFramework\Http\Template;
+
+use OCP\Util;
+
+/**
+ * Class SimpleMenuAction
+ *
+ * @package OCP\AppFramework\Http\Template
+ * @since 14.0.0
+ */
+class SimpleMenuAction implements IMenuAction {
+
+ /** @var string */
+ private $id;
+
+ /** @var string */
+ private $label;
+
+ /** @var string */
+ private $icon;
+
+ /** @var string */
+ private $link;
+
+ /** @var int */
+ private $priority;
+
+ /** @var string */
+ private $detail;
+
+ /**
+ * SimpleMenuAction constructor.
+ *
+ * @param string $id
+ * @param string $label
+ * @param string $icon
+ * @param string $link
+ * @param int $priority
+ * @param string $detail
+ * @since 14.0.0
+ */
+ public function __construct(string $id, string $label, string $icon, string $link = '', int $priority = 100, string $detail = '') {
+ $this->id = $id;
+ $this->label = $label;
+ $this->icon = $icon;
+ $this->link = $link;
+ $this->priority = $priority;
+ $this->detail = $detail;
+ }
+
+ /**
+ * @return string
+ * @since 14.0.0
+ */
+ public function getId(): string {
+ return $this->id;
+ }
+
+ /**
+ * @return string
+ * @since 14.0.0
+ */
+ public function getLabel(): string {
+ return $this->label;
+ }
+
+ /**
+ * @return string
+ * @since 14.0.0
+ */
+ public function getIcon(): string {
+ return $this->icon;
+ }
+
+ /**
+ * @return string
+ * @since 14.0.0
+ */
+ public function getLink(): string {
+ return $this->link;
+ }
+
+ /**
+ * @return int
+ * @since 14.0.0
+ */
+ public function getPriority(): int {
+ return $this->priority;
+ }
+
+ /**
+ * @return string
+ * @since 14.0.0
+ */
+ public function render(): string {
+ $detailContent = ($this->detail !== '') ? '&nbsp;<span class="download-size">(' . Util::sanitizeHTML($this->detail) . ')</span>' : '';
+ return sprintf(
+ '<li id="%s"><a href="%s"><span class="icon %s"></span>%s %s</a></li>',
+ Util::sanitizeHTML($this->id), Util::sanitizeHTML($this->link), Util::sanitizeHTML($this->icon), Util::sanitizeHTML($this->label), $detailContent
+ );
+ }
+
+} \ No newline at end of file
diff --git a/lib/public/AppFramework/Http/TemplateResponse.php b/lib/public/AppFramework/Http/TemplateResponse.php
index ccb0c61bfd4..0e31f780d7a 100644
--- a/lib/public/AppFramework/Http/TemplateResponse.php
+++ b/lib/public/AppFramework/Http/TemplateResponse.php
@@ -154,7 +154,7 @@ class TemplateResponse extends Response {
$template->assign($key, $value);
}
- return $template->fetchPage();
+ return $template->fetchPage($this->params);
}
}
diff --git a/lib/public/AppFramework/PublicShareController.php b/lib/public/AppFramework/PublicShareController.php
new file mode 100644
index 00000000000..d0e54a0295b
--- /dev/null
+++ b/lib/public/AppFramework/PublicShareController.php
@@ -0,0 +1,138 @@
+<?php
+/**
+ * @copyright 2018, 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/>.
+ *
+ */
+declare(strict_types=1);
+
+namespace OCP\AppFramework;
+
+use OCP\IRequest;
+use OCP\ISession;
+
+/**
+ * Base controller for public shares
+ *
+ * It will verify if the user is properly authenticated to the share. If not a 404
+ * is thrown by the PublicShareMiddleware.
+ *
+ * Use this for example for a controller that is not to be called via a webbrowser
+ * directly. For example a PublicPreviewController. As this is not meant to be
+ * called by a user direclty.
+ *
+ * To show an auth page extend the AuthPublicShareController
+ *
+ * @since 14.0.0
+ */
+abstract class PublicShareController extends Controller {
+
+ /** @var ISession */
+ protected $session;
+
+ /** @var string */
+ private $token;
+
+ /**
+ * @since 14.0.0
+ */
+ public function __construct(string $appName,
+ IRequest $request,
+ ISession $session) {
+ parent::__construct($appName, $request);
+
+ $this->session = $session;
+ }
+
+ /**
+ * Middleware set the token for the request
+ *
+ * @since 14.0.0
+ */
+ final public function setToken(string $token) {
+ $this->token = $token;
+ }
+
+ /**
+ * Get the token for this request
+ *
+ * @since 14.0.0
+ */
+ final public function getToken(): string {
+ return $this->token;
+ }
+
+ /**
+ * Get a hash of the password for this share
+ *
+ * To ensure access is blocked when the password to a share is changed we store
+ * a hash of the password for this token.
+ *
+ * @since 14.0.0
+ */
+ abstract protected function getPasswordHash(): string;
+
+ /**
+ * Is the provided token a valid token
+ *
+ * This function is already called from the middleware directly after setting the token.
+ *
+ * @since 14.0.0
+ */
+ abstract public function isValidToken(): bool;
+
+ /**
+ * Is a share with this token password protected
+ *
+ * @since 14.0.0
+ */
+ abstract protected function isPasswordProtected(): bool;
+
+ /**
+ * Check if a share is authenticated or not
+ *
+ * @since 14.0.0
+ */
+ final public function isAuthenticated(): bool {
+ // Always authenticated against non password protected shares
+ if (!$this->isPasswordProtected()) {
+ return true;
+ }
+
+ // If we are authenticated properly
+ if ($this->session->get('public_link_authenticated_token') === $this->getToken() &&
+ $this->session->get('public_link_authenticated_password_hash') === $this->getPasswordHash()) {
+ return true;
+ }
+
+ // Fail by default if nothing matches
+ return false;
+ }
+
+ /**
+ * Function called if the share is not found.
+ *
+ * You can use this to do some logging for example
+ *
+ * @since 14.0.0
+ */
+ public function shareNotFound() {
+
+ }
+}
diff --git a/lib/public/AppFramework/Utility/IControllerMethodReflector.php b/lib/public/AppFramework/Utility/IControllerMethodReflector.php
index e9fb4a5a969..e2074b9fe00 100644
--- a/lib/public/AppFramework/Utility/IControllerMethodReflector.php
+++ b/lib/public/AppFramework/Utility/IControllerMethodReflector.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -40,7 +41,7 @@ interface IControllerMethodReflector {
* @return void
* @since 8.0.0
*/
- public function reflect($object, $method);
+ public function reflect($object, string $method);
/**
* Inspects the PHPDoc parameters for types
@@ -51,13 +52,13 @@ interface IControllerMethodReflector {
* would return int or null if not existing
* @since 8.0.0
*/
- public function getType($parameter);
+ public function getType(string $parameter);
/**
* @return array the arguments of the method with key => default value
* @since 8.0.0
*/
- public function getParameters();
+ public function getParameters(): array;
/**
* Check if a method contains an annotation
@@ -66,6 +67,6 @@ interface IControllerMethodReflector {
* @return bool true if the annotation is found
* @since 8.0.0
*/
- public function hasAnnotation($name);
+ public function hasAnnotation(string $name): bool;
}
diff --git a/lib/public/Authentication/TwoFactorAuth/IProvider.php b/lib/public/Authentication/TwoFactorAuth/IProvider.php
index c4c481a2f32..84752cecc77 100644
--- a/lib/public/Authentication/TwoFactorAuth/IProvider.php
+++ b/lib/public/Authentication/TwoFactorAuth/IProvider.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -43,7 +44,7 @@ interface IProvider {
*
* @return string
*/
- public function getId();
+ public function getId(): string;
/**
* Get the display name for selecting the 2FA provider
@@ -54,7 +55,7 @@ interface IProvider {
*
* @return string
*/
- public function getDisplayName();
+ public function getDisplayName(): string;
/**
* Get the description for selecting the 2FA provider
@@ -65,7 +66,7 @@ interface IProvider {
*
* @return string
*/
- public function getDescription();
+ public function getDescription(): string;
/**
* Get the template for rending the 2FA provider view
@@ -75,7 +76,7 @@ interface IProvider {
* @param IUser $user
* @return Template
*/
- public function getTemplate(IUser $user);
+ public function getTemplate(IUser $user): Template;
/**
* Verify the given challenge
@@ -84,8 +85,9 @@ interface IProvider {
*
* @param IUser $user
* @param string $challenge
+ * @return bool
*/
- public function verifyChallenge(IUser $user, $challenge);
+ public function verifyChallenge(IUser $user, string $challenge): bool;
/**
* Decides whether 2FA is enabled for the given user
@@ -93,7 +95,7 @@ interface IProvider {
* @since 9.1.0
*
* @param IUser $user
- * @return boolean
+ * @return bool
*/
- public function isTwoFactorAuthEnabledForUser(IUser $user);
+ public function isTwoFactorAuthEnabledForUser(IUser $user): bool;
}
diff --git a/lib/public/Authentication/TwoFactorAuth/IProvidesCustomCSP.php b/lib/public/Authentication/TwoFactorAuth/IProvidesCustomCSP.php
index 2a498adc0b8..3b477dc53fe 100644
--- a/lib/public/Authentication/TwoFactorAuth/IProvidesCustomCSP.php
+++ b/lib/public/Authentication/TwoFactorAuth/IProvidesCustomCSP.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
*
*
@@ -35,5 +36,5 @@ interface IProvidesCustomCSP {
*
* @since 13.0.0
*/
- public function getCSP();
+ public function getCSP(): ContentSecurityPolicy;
}
diff --git a/lib/public/Authentication/TwoFactorAuth/IRegistry.php b/lib/public/Authentication/TwoFactorAuth/IRegistry.php
new file mode 100644
index 00000000000..5013892d402
--- /dev/null
+++ b/lib/public/Authentication/TwoFactorAuth/IRegistry.php
@@ -0,0 +1,65 @@
+<?php
+
+declare(strict_types = 1);
+
+/**
+ * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @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\Authentication\TwoFactorAuth;
+
+use OCP\IUser;
+
+/**
+ * Nextcloud 2FA provider registry for stateful 2FA providers
+ *
+ * This service keeps track of which providers are currently active for a specific
+ * user. Stateful 2FA providers (IStatefulProvider) must use this service to save
+ * their enabled/disabled state.
+ *
+ * @since 14.0.0
+ */
+interface IRegistry {
+
+ /**
+ * Get a key-value map of providers and their enabled/disabled state for
+ * the given user.
+ *
+ * @since 14.0.0
+ * @return string[] where the array key is the provider ID (string) and the
+ * value is the enabled state (bool)
+ */
+ public function getProviderStates(IUser $user): array;
+
+ /**
+ * Enable the given 2FA provider for the given user
+ *
+ * @since 14.0.0
+ */
+ public function enableProviderFor(IProvider $provider, IUser $user);
+
+ /**
+ * Disable the given 2FA provider for the given user
+ *
+ * @since 14.0.0
+ */
+ public function disableProviderFor(IProvider $provider, IUser $user);
+}
diff --git a/lib/public/Authentication/TwoFactorAuth/TwoFactorException.php b/lib/public/Authentication/TwoFactorAuth/TwoFactorException.php
index a18b9e8c4a8..d94c3e61465 100644
--- a/lib/public/Authentication/TwoFactorAuth/TwoFactorException.php
+++ b/lib/public/Authentication/TwoFactorAuth/TwoFactorException.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud GmbH.
*
diff --git a/lib/public/BackgroundJob.php b/lib/public/BackgroundJob.php
index 9e37ff30145..58d44231ae3 100644
--- a/lib/public/BackgroundJob.php
+++ b/lib/public/BackgroundJob.php
@@ -46,11 +46,4 @@ class BackgroundJob {
*/
public static function setExecutionType($type) {
}
-
- /**
- * @since 6.0.0
- * @deprecated 8.1.0 Use \OC::$server->getJobList()->add() instead
- */
- public static function registerJob($job, $argument = null) {
- }
}
diff --git a/lib/public/Calendar/BackendTemporarilyUnavailableException.php b/lib/public/Calendar/BackendTemporarilyUnavailableException.php
new file mode 100644
index 00000000000..632a802359c
--- /dev/null
+++ b/lib/public/Calendar/BackendTemporarilyUnavailableException.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
+ *
+ * @author Georg Ehrke <oc.list@georgehrke.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\Calendar;
+
+/**
+ * Class BackendTemporarilyUnavailableException
+ *
+ * @package OCP\Calendar
+ * @since 14.0.0
+ */
+class BackendTemporarilyUnavailableException extends \Exception {}
diff --git a/lib/public/Calendar/Resource/IBackend.php b/lib/public/Calendar/Resource/IBackend.php
new file mode 100644
index 00000000000..24635219fe0
--- /dev/null
+++ b/lib/public/Calendar/Resource/IBackend.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
+ *
+ * @author Georg Ehrke <oc.list@georgehrke.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\Calendar\Resource;
+use OCP\Calendar\BackendTemporarilyUnavailableException;
+
+/**
+ * Interface IBackend
+ *
+ * @package OCP\Calendar\Resource
+ * @since 14.0.0
+ */
+interface IBackend {
+
+ /**
+ * get a list of all resources in this backend
+ *
+ * @throws BackendTemporarilyUnavailableException
+ * @return IResource[]
+ * @since 14.0.0
+ */
+ public function getAllResources():array;
+
+ /**
+ * get a list of all resource identifiers in this backend
+ *
+ * @throws BackendTemporarilyUnavailableException
+ * @return string[]
+ * @since 14.0.0
+ */
+ public function listAllResources():array;
+
+ /**
+ * get a resource by it's id
+ *
+ * @param string $id
+ * @throws BackendTemporarilyUnavailableException
+ * @return IResource|null
+ * @since 14.0.0
+ */
+ public function getResource($id);
+
+ /**
+ * Get unique identifier of the backend
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function getBackendIdentifier():string;
+}
diff --git a/lib/public/Calendar/Resource/IManager.php b/lib/public/Calendar/Resource/IManager.php
new file mode 100644
index 00000000000..8542e13eba7
--- /dev/null
+++ b/lib/public/Calendar/Resource/IManager.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
+ *
+ * @author Georg Ehrke <oc.list@georgehrke.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\Calendar\Resource;
+
+/**
+ * Interface IManager
+ *
+ * @package OCP\Calendar\Resource
+ * @since 14.0.0
+ */
+interface IManager {
+
+ /**
+ * Registers a resource backend
+ *
+ * @param IBackend $backend
+ * @return void
+ * @since 14.0.0
+ */
+ public function registerBackend(IBackend $backend);
+
+ /**
+ * Unregisters a resource backend
+ *
+ * @param IBackend $backend
+ * @return void
+ * @since 14.0.0
+ */
+ public function unregisterBackend(IBackend $backend);
+
+ /**
+ * @return IBackend[]
+ * @since 14.0.0
+ */
+ public function getBackends():array;
+
+ /**
+ * @param string $backendId
+ * @return IBackend
+ * @since 14.0.0
+ */
+ public function getBackend($backendId):IBackend;
+
+ /**
+ * removes all registered backend instances
+ * @return void
+ * @since 14.0.0
+ */
+ public function clear();
+}
diff --git a/lib/public/Calendar/Resource/IResource.php b/lib/public/Calendar/Resource/IResource.php
new file mode 100644
index 00000000000..1f588ccb48d
--- /dev/null
+++ b/lib/public/Calendar/Resource/IResource.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
+ *
+ * @author Georg Ehrke <oc.list@georgehrke.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\Calendar\Resource;
+
+/**
+ * Interface IResource
+ *
+ * @package OCP\Calendar\Resource
+ * @since 14.0.0
+ */
+interface IResource {
+
+ /**
+ * get the resource id
+ *
+ * This id has to be unique within the backend
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function getId():string;
+
+ /**
+ * get the display name for a resource
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function getDisplayName():string;
+
+ /**
+ * Get a list of groupIds that are allowed to access this resource
+ *
+ * If an empty array is returned, no group restrictions are
+ * applied.
+ *
+ * @return string[]
+ * @since 14.0.0
+ */
+ public function getGroupRestrictions():array;
+
+ /**
+ * get email-address for resource
+ *
+ * The email address has to be globally unique
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function getEMail():string;
+
+ /**
+ * Get corresponding backend object
+ *
+ * @return IBackend
+ * @since 14.0.0
+ */
+ public function getBackend():IBackend;
+}
diff --git a/lib/public/Calendar/Room/IBackend.php b/lib/public/Calendar/Room/IBackend.php
new file mode 100644
index 00000000000..f675012ab39
--- /dev/null
+++ b/lib/public/Calendar/Room/IBackend.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
+ *
+ * @author Georg Ehrke <oc.list@georgehrke.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\Calendar\Room;
+use OCP\Calendar\BackendTemporarilyUnavailableException;
+
+/**
+ * Interface IBackend
+ *
+ * @package OCP\Calendar\Room
+ * @since 14.0.0
+ */
+interface IBackend {
+
+ /**
+ * get a list of all rooms in this backend
+ *
+ * @throws BackendTemporarilyUnavailableException
+ * @return IRoom[]
+ * @since 14.0.0
+ */
+ public function getAllRooms():array;
+
+ /**
+ * get a list of all room identifiers in this backend
+ *
+ * @throws BackendTemporarilyUnavailableException
+ * @return string[]
+ * @since 14.0.0
+ */
+ public function listAllRooms():array;
+
+ /**
+ * get a room by it's id
+ *
+ * @param string $id
+ * @throws BackendTemporarilyUnavailableException
+ * @return IRoom|null
+ * @since 14.0.0
+ */
+ public function getRoom($id);
+
+ /**
+ * Get unique identifier of the backend
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function getBackendIdentifier():string;
+}
diff --git a/lib/public/Calendar/Room/IManager.php b/lib/public/Calendar/Room/IManager.php
new file mode 100644
index 00000000000..39e85c43e45
--- /dev/null
+++ b/lib/public/Calendar/Room/IManager.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
+ *
+ * @author Georg Ehrke <oc.list@georgehrke.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\Calendar\Room;
+
+/**
+ * Interface IManager
+ *
+ * @package OCP\Calendar\Room
+ * @since 14.0.0
+ */
+interface IManager {
+
+ /**
+ * Registers a room backend
+ *
+ * @param IBackend $backend
+ * @return void
+ * @since 14.0.0
+ */
+ public function registerBackend(IBackend $backend);
+
+ /**
+ * Unregisters a room backend
+ *
+ * @param IBackend $backend
+ * @return void
+ * @since 14.0.0
+ */
+ public function unregisterBackend(IBackend $backend);
+
+ /**
+ * @return IBackend[]
+ * @since 14.0.0
+ */
+ public function getBackends():array;
+
+ /**
+ * @param string $backendId
+ * @return IBackend
+ * @since 14.0.0
+ */
+ public function getBackend($backendId):IBackend;
+
+ /**
+ * removes all registered backend instances
+ * @return void
+ * @since 14.0.0
+ */
+ public function clear();
+}
diff --git a/lib/public/Calendar/Room/IRoom.php b/lib/public/Calendar/Room/IRoom.php
new file mode 100644
index 00000000000..d860bb6fc57
--- /dev/null
+++ b/lib/public/Calendar/Room/IRoom.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * @copyright 2018, Georg Ehrke <oc.list@georgehrke.com>
+ *
+ * @author Georg Ehrke <oc.list@georgehrke.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\Calendar\Room;
+
+/**
+ * Interface IRoom
+ *
+ * @package OCP\Calendar\Room
+ * @since 14.0.0
+ */
+interface IRoom {
+
+ /**
+ * get the room id
+ *
+ * This id has to be unique within the backend
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function getId():string;
+
+ /**
+ * get the display name for a room
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function getDisplayName():string;
+
+ /**
+ * Get a list of groupIds that are allowed to access this room
+ *
+ * If an empty array is returned, no group restrictions are
+ * applied.
+ *
+ * @return string[]
+ * @since 14.0.0
+ */
+ public function getGroupRestrictions():array;
+
+ /**
+ * get email-address for room
+ *
+ * The email address has to be globally unique
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function getEMail():string;
+
+ /**
+ * Get corresponding backend object
+ *
+ * @return IBackend
+ * @since 14.0.0
+ */
+ public function getBackend():IBackend;
+}
diff --git a/lib/public/Comments/ICommentsManager.php b/lib/public/Comments/ICommentsManager.php
index bd9c4ff5ba6..b3ed176b3b5 100644
--- a/lib/public/Comments/ICommentsManager.php
+++ b/lib/public/Comments/ICommentsManager.php
@@ -121,6 +121,24 @@ interface ICommentsManager {
);
/**
+ * @param string $objectType the object type, e.g. 'files'
+ * @param string $objectId the id of the object
+ * @param int $lastKnownCommentId the last known comment (will be used as offset)
+ * @param string $sortDirection direction of the comments (`asc` or `desc`)
+ * @param int $limit optional, number of maximum comments to be returned. if
+ * set to 0, all comments are returned.
+ * @return IComment[]
+ * @since 14.0.0
+ */
+ public function getForObjectSince(
+ string $objectType,
+ string $objectId,
+ int $lastKnownCommentId,
+ string $sortDirection = 'asc',
+ int $limit = 30
+ ): array;
+
+ /**
* @param $objectType string the object type, e.g. 'files'
* @param $objectId string the id of the object
* @param \DateTime|null $notOlderThan optional, timestamp of the oldest comments
diff --git a/lib/public/Contacts.php b/lib/public/Contacts.php
deleted file mode 100644
index 16cd52d19cf..00000000000
--- a/lib/public/Contacts.php
+++ /dev/null
@@ -1,185 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin McCorkell <robin@mccorkell.me.uk>
- * @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/>
- *
- */
-
-/**
- * Public interface of ownCloud for apps to use.
- * Contacts Class
- *
- */
-
-// use OCP namespace for all classes that are considered public.
-// This means that they should be used by apps instead of the internal ownCloud classes
-namespace OCP {
-
- /**
- * This class provides access to the contacts app. Use this class exclusively if you want to access contacts.
- *
- * Contacts in general will be expressed as an array of key-value-pairs.
- * The keys will match the property names defined in https://tools.ietf.org/html/rfc2426#section-1
- *
- * Proposed workflow for working with contacts:
- * - search for the contacts
- * - manipulate the results array
- * - createOrUpdate will save the given contacts overwriting the existing data
- *
- * For updating it is mandatory to keep the id.
- * Without an id a new contact will be created.
- *
- * @deprecated 8.1.0 use methods of \OCP\Contacts\IManager - \OC::$server->getContactsManager();
- * @since 5.0.0
- */
- class Contacts {
-
- /**
- * This function is used to search and find contacts within the users address books.
- * In case $pattern is empty all contacts will be returned.
- *
- * Example:
- * Following function shows how to search for contacts for the name and the email address.
- *
- * public static function getMatchingRecipient($term) {
- * // The API is not active -> nothing to do
- * if (!\OCP\Contacts::isEnabled()) {
- * return array();
- * }
- *
- * $result = \OCP\Contacts::search($term, array('FN', 'EMAIL'));
- * $receivers = array();
- * foreach ($result as $r) {
- * $id = $r['id'];
- * $fn = $r['FN'];
- * $email = $r['EMAIL'];
- * if (!is_array($email)) {
- * $email = array($email);
- * }
- *
- * // loop through all email addresses of this contact
- * foreach ($email as $e) {
- * $displayName = $fn . " <$e>";
- * $receivers[] = array(
- * 'id' => $id,
- * 'label' => $displayName,
- * 'value' => $displayName);
- * }
- * }
- *
- * return $receivers;
- * }
- *
- *
- * @param string $pattern which should match within the $searchProperties
- * @param array $searchProperties defines the properties within the query pattern should match
- * @param array $options - for future use. One should always have options!
- * @return array an array of contacts which are arrays of key-value-pairs
- * @deprecated 8.1.0 use search() of \OCP\Contacts\IManager - \OC::$server->getContactsManager();
- * @since 5.0.0
- */
- public static function search($pattern, $searchProperties = array(), $options = array()) {
- $cm = \OC::$server->getContactsManager();
- return $cm->search($pattern, $searchProperties, $options);
- }
-
- /**
- * This function can be used to delete the contact identified by the given id
- *
- * @param object $id the unique identifier to a contact
- * @param string $address_book_key
- * @return bool successful or not
- * @deprecated 8.1.0 use delete() of \OCP\Contacts\IManager - \OC::$server->getContactsManager();
- * @since 5.0.0
- */
- public static function delete($id, $address_book_key) {
- $cm = \OC::$server->getContactsManager();
- return $cm->delete($id, $address_book_key);
- }
-
- /**
- * This function is used to create a new contact if 'id' is not given or not present.
- * Otherwise the contact will be updated by replacing the entire data set.
- *
- * @param array $properties this array if key-value-pairs defines a contact
- * @param string $address_book_key identifier of the address book in which the contact shall be created or updated
- * @return array an array representing the contact just created or updated
- * @deprecated 8.1.0 use createOrUpdate() of \OCP\Contacts\IManager - \OC::$server->getContactsManager();
- * @since 5.0.0
- */
- public static function createOrUpdate($properties, $address_book_key) {
- $cm = \OC::$server->getContactsManager();
- return $cm->createOrUpdate($properties, $address_book_key);
- }
-
- /**
- * Check if contacts are available (e.g. contacts app enabled)
- *
- * @return bool true if enabled, false if not
- * @deprecated 8.1.0 use isEnabled() of \OCP\Contacts\IManager - \OC::$server->getContactsManager();
- * @since 5.0.0
- */
- public static function isEnabled() {
- $cm = \OC::$server->getContactsManager();
- return $cm->isEnabled();
- }
-
- /**
- * @param \OCP\IAddressBook $address_book
- * @deprecated 8.1.0 use registerAddressBook() of \OCP\Contacts\IManager - \OC::$server->getContactsManager();
- * @since 5.0.0
- */
- public static function registerAddressBook(\OCP\IAddressBook $address_book) {
- $cm = \OC::$server->getContactsManager();
- $cm->registerAddressBook($address_book);
- }
-
- /**
- * @param \OCP\IAddressBook $address_book
- * @deprecated 8.1.0 use unregisterAddressBook() of \OCP\Contacts\IManager - \OC::$server->getContactsManager();
- * @since 5.0.0
- */
- public static function unregisterAddressBook(\OCP\IAddressBook $address_book) {
- $cm = \OC::$server->getContactsManager();
- $cm->unregisterAddressBook($address_book);
- }
-
- /**
- * @return array
- * @deprecated 8.1.0 use getAddressBooks() of \OCP\Contacts\IManager - \OC::$server->getContactsManager();
- * @since 5.0.0
- */
- public static function getAddressBooks() {
- $cm = \OC::$server->getContactsManager();
- return $cm->getAddressBooks();
- }
-
- /**
- * removes all registered address book instances
- * @deprecated 8.1.0 use clear() of \OCP\Contacts\IManager - \OC::$server->getContactsManager();
- * @since 5.0.0
- */
- public static function clear() {
- $cm = \OC::$server->getContactsManager();
- $cm->clear();
- }
- }
-}
diff --git a/lib/public/DB.php b/lib/public/DB.php
deleted file mode 100644
index e132c5ff2ec..00000000000
--- a/lib/public/DB.php
+++ /dev/null
@@ -1,147 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Dan Bartram <daneybartram@gmail.com>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-/**
- * Public interface of ownCloud for apps to use.
- * DB Class
- *
- */
-
-// use OCP namespace for all classes that are considered public.
-// This means that they should be used by apps instead of the internal ownCloud classes
-namespace OCP;
-
-/**
- * This class provides access to the internal database system. Use this class exlusively if you want to access databases
- * @deprecated 8.1.0 use methods of \OCP\IDBConnection - \OC::$server->getDatabaseConnection()
- * @since 4.5.0
- */
-class DB {
- /**
- * Prepare a SQL query
- * @param string $query Query string
- * @param int $limit Limit of the SQL statement
- * @param int $offset Offset of the SQL statement
- * @return \OC_DB_StatementWrapper prepared SQL query
- *
- * SQL query via Doctrine prepare(), needs to be execute()'d!
- * @deprecated 8.1.0 use prepare() of \OCP\IDBConnection - \OC::$server->getDatabaseConnection()
- * @since 4.5.0
- */
- static public function prepare( $query, $limit=null, $offset=null ) {
- return \OC_DB::prepare($query, $limit, $offset);
- }
-
- /**
- * Insert a row if the matching row does not exists.
- *
- * @param string $table The table name (will replace *PREFIX* with the actual prefix)
- * @param array $input data that should be inserted into the table (column name => value)
- * @param array|null $compare List of values that should be checked for "if not exists"
- * If this is null or an empty array, all keys of $input will be compared
- * @return int number of inserted rows
- * @throws \Doctrine\DBAL\DBALException
- * @deprecated 8.1.0 use insertIfNotExist() of \OCP\IDBConnection - \OC::$server->getDatabaseConnection()
- * @since 5.0.0 - parameter $compare was added in 8.1.0
- *
- */
- public static function insertIfNotExist($table, $input, array $compare = null) {
- return \OC::$server->getDatabaseConnection()->insertIfNotExist($table, $input, $compare);
- }
-
- /**
- * Gets last value of autoincrement
- * @param string $table The optional table name (will replace *PREFIX*) and add sequence suffix
- * @return string
- *
- * \Doctrine\DBAL\Connection lastInsertID()
- *
- * Call this method right after the insert command or other functions may
- * cause trouble!
- * @deprecated 8.1.0 use lastInsertId() of \OCP\IDBConnection - \OC::$server->getDatabaseConnection()
- * @since 4.5.0
- */
- public static function insertid($table=null) {
- return (string)\OC::$server->getDatabaseConnection()->lastInsertId($table);
- }
-
- /**
- * Start a transaction
- * @deprecated 8.1.0 use beginTransaction() of \OCP\IDBConnection - \OC::$server->getDatabaseConnection()
- * @since 4.5.0
- */
- public static function beginTransaction() {
- \OC::$server->getDatabaseConnection()->beginTransaction();
- }
-
- /**
- * Commit the database changes done during a transaction that is in progress
- * @deprecated 8.1.0 use commit() of \OCP\IDBConnection - \OC::$server->getDatabaseConnection()
- * @since 4.5.0
- */
- public static function commit() {
- \OC::$server->getDatabaseConnection()->commit();
- }
-
- /**
- * Rollback the database changes done during a transaction that is in progress
- * @deprecated 8.1.0 use rollback() of \OCP\IDBConnection - \OC::$server->getDatabaseConnection()
- * @since 8.0.0
- */
- public static function rollback() {
- \OC::$server->getDatabaseConnection()->rollBack();
- }
-
- /**
- * Check if a result is an error, works with Doctrine
- * @param mixed $result
- * @return bool
- * @deprecated 8.1.0 Doctrine returns false on error (and throws an exception)
- * @since 4.5.0
- */
- public static function isError($result) {
- // Doctrine returns false on error (and throws an exception)
- return $result === false;
- }
-
- /**
- * returns the error code and message as a string for logging
- * works with DoctrineException
- * @return string
- * @deprecated 8.1.0 use getError() of \OCP\IDBConnection - \OC::$server->getDatabaseConnection()
- * @since 6.0.0
- */
- public static function getErrorMessage() {
- return \OC::$server->getDatabaseConnection()->getError();
- }
-
-}
diff --git a/lib/public/DB/QueryBuilder/IExpressionBuilder.php b/lib/public/DB/QueryBuilder/IExpressionBuilder.php
index eab93b52f8a..0a212e8f828 100644
--- a/lib/public/DB/QueryBuilder/IExpressionBuilder.php
+++ b/lib/public/DB/QueryBuilder/IExpressionBuilder.php
@@ -66,13 +66,13 @@ interface IExpressionBuilder {
* // (u.type = ?) AND (u.role = ?)
* $expr->andX('u.type = ?', 'u.role = ?'));
*
- * @param mixed $x Optional clause. Defaults = null, but requires
+ * @param mixed ...$x Optional clause. Defaults = null, but requires
* at least one defined when converting to string.
*
* @return \OCP\DB\QueryBuilder\ICompositeExpression
* @since 8.2.0
*/
- public function andX($x = null);
+ public function andX(...$x);
/**
* Creates a disjunction of the given boolean expressions.
@@ -83,13 +83,13 @@ interface IExpressionBuilder {
* // (u.type = ?) OR (u.role = ?)
* $qb->where($qb->expr()->orX('u.type = ?', 'u.role = ?'));
*
- * @param mixed $x Optional clause. Defaults = null, but requires
+ * @param mixed ...$x Optional clause. Defaults = null, but requires
* at least one defined when converting to string.
*
* @return \OCP\DB\QueryBuilder\ICompositeExpression
* @since 8.2.0
*/
- public function orX($x = null);
+ public function orX(...$x);
/**
* Creates a comparison expression.
diff --git a/lib/public/DB/QueryBuilder/IFunctionBuilder.php b/lib/public/DB/QueryBuilder/IFunctionBuilder.php
index 478fd879404..51b639028ce 100644
--- a/lib/public/DB/QueryBuilder/IFunctionBuilder.php
+++ b/lib/public/DB/QueryBuilder/IFunctionBuilder.php
@@ -71,4 +71,37 @@ interface IFunctionBuilder {
* @since 12.0.0
*/
public function sum($field);
+
+ /**
+ * Transforms a string field or value to lower case
+ *
+ * @param mixed $field
+ * @return IQueryFunction
+ * @since 14.0.0
+ */
+ public function lower($field);
+
+ /**
+ * @param mixed $x The first input field or number
+ * @param mixed $y The second input field or number
+ * @return IQueryFunction
+ * @since 14.0.0
+ */
+ public function add($x, $y);
+
+ /**
+ * @param mixed $x The first input field or number
+ * @param mixed $y The second input field or number
+ * @return IQueryFunction
+ * @since 14.0.0
+ */
+ public function subtract($x, $y);
+
+ /**
+ * @param mixed $input The input to be counted
+ *
+ * @return IQueryFunction
+ * @since 14.0.0
+ */
+ public function count($input);
}
diff --git a/lib/public/DB/QueryBuilder/IQueryBuilder.php b/lib/public/DB/QueryBuilder/IQueryBuilder.php
index 7f179dd7e26..7fea31f4688 100644
--- a/lib/public/DB/QueryBuilder/IQueryBuilder.php
+++ b/lib/public/DB/QueryBuilder/IQueryBuilder.php
@@ -292,12 +292,12 @@ interface IQueryBuilder {
* ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
* </code>
*
- * @param mixed $select The selection expressions.
+ * @param mixed ...$selects The selection expressions.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
* @since 8.2.0
*/
- public function select($select = null);
+ public function select(...$selects);
/**
* Specifies an item that is to be returned with a different name in the query result.
@@ -344,12 +344,12 @@ interface IQueryBuilder {
* ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id');
* </code>
*
- * @param mixed $select The selection expression.
+ * @param mixed ...$select The selection expression.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
* @since 8.2.0
*/
- public function addSelect($select = null);
+ public function addSelect(...$select);
/**
* Turns the query being built into a bulk delete query that ranges over
@@ -554,7 +554,7 @@ interface IQueryBuilder {
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
* @since 8.2.0
*/
- public function where($predicates);
+ public function where(...$predicates);
/**
* Adds one or more restrictions to the query results, forming a logical
@@ -568,14 +568,14 @@ interface IQueryBuilder {
* ->andWhere('u.is_active = 1');
* </code>
*
- * @param mixed $where The query restrictions.
+ * @param mixed ...$where The query restrictions.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
*
* @see where()
* @since 8.2.0
*/
- public function andWhere($where);
+ public function andWhere(...$where);
/**
* Adds one or more restrictions to the query results, forming a logical
@@ -589,14 +589,14 @@ interface IQueryBuilder {
* ->orWhere('u.id = 2');
* </code>
*
- * @param mixed $where The WHERE statement.
+ * @param mixed ...$where The WHERE statement.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
*
* @see where()
* @since 8.2.0
*/
- public function orWhere($where);
+ public function orWhere(...$where);
/**
* Specifies a grouping over the results of the query.
@@ -609,12 +609,12 @@ interface IQueryBuilder {
* ->groupBy('u.id');
* </code>
*
- * @param mixed $groupBy The grouping expression.
+ * @param mixed ...$groupBys The grouping expression.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
* @since 8.2.0
*/
- public function groupBy($groupBy);
+ public function groupBy(...$groupBys);
/**
* Adds a grouping expression to the query.
@@ -627,12 +627,12 @@ interface IQueryBuilder {
* ->addGroupBy('u.createdAt')
* </code>
*
- * @param mixed $groupBy The grouping expression.
+ * @param mixed ...$groupBy The grouping expression.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
* @since 8.2.0
*/
- public function addGroupBy($groupBy);
+ public function addGroupBy(...$groupBy);
/**
* Sets a value for a column in an insert query.
@@ -682,34 +682,34 @@ interface IQueryBuilder {
* Specifies a restriction over the groups of the query.
* Replaces any previous having restrictions, if any.
*
- * @param mixed $having The restriction over the groups.
+ * @param mixed ...$having The restriction over the groups.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
* @since 8.2.0
*/
- public function having($having);
+ public function having(...$having);
/**
* Adds a restriction over the groups of the query, forming a logical
* conjunction with any existing having restrictions.
*
- * @param mixed $having The restriction to append.
+ * @param mixed ...$having The restriction to append.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
* @since 8.2.0
*/
- public function andHaving($having);
+ public function andHaving(...$having);
/**
* Adds a restriction over the groups of the query, forming a logical
* disjunction with any existing having restrictions.
*
- * @param mixed $having The restriction to add.
+ * @param mixed ...$having The restriction to add.
*
* @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
* @since 8.2.0
*/
- public function orHaving($having);
+ public function orHaving(...$having);
/**
* Specifies an ordering for the query results.
diff --git a/lib/public/Federation/Exceptions/ActionNotSupportedException.php b/lib/public/Federation/Exceptions/ActionNotSupportedException.php
new file mode 100644
index 00000000000..2d295bd9d8b
--- /dev/null
+++ b/lib/public/Federation/Exceptions/ActionNotSupportedException.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation\Exceptions;
+
+use OC\HintException;
+
+/**
+ * Class ActionNotSupportedException
+ *
+ * @package OCP\Federation\Exceptions
+ *
+ * @since 14.0.0
+ */
+class ActionNotSupportedException extends HintException {
+
+ /**
+ * ActionNotSupportedException constructor.
+ *
+ * @since 14.0.0
+ *
+ */
+ public function __construct($action) {
+ $l = \OC::$server->getL10N('federation');
+ $message = 'Action "' . $action . '" not supported or implemented.';
+ $hint = $l->t('Action "%s" not supported or implemented.', [$action]);
+ parent::__construct($message, $hint);
+ }
+
+}
diff --git a/lib/public/Federation/Exceptions/AuthenticationFailedException.php b/lib/public/Federation/Exceptions/AuthenticationFailedException.php
new file mode 100644
index 00000000000..1ea7ec5cd31
--- /dev/null
+++ b/lib/public/Federation/Exceptions/AuthenticationFailedException.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation\Exceptions;
+
+use OC\HintException;
+
+/**
+ * Class AuthenticationFailedException
+ *
+ * @package OCP\Federation\Exceptions
+ *
+ * @since 14.0.0
+ */
+class AuthenticationFailedException extends HintException {
+
+ /**
+ * BadRequestException constructor.
+ *
+ * @since 14.0.0
+ *
+ */
+ public function __construct() {
+ $l = \OC::$server->getL10N('federation');
+ $message = 'Authentication failed, wrong token or provider ID given';
+ $hint = $l->t('Authentication failed, wrong token or provider ID given');
+ parent::__construct($message, $hint);
+ }
+
+}
diff --git a/lib/public/Federation/Exceptions/BadRequestException.php b/lib/public/Federation/Exceptions/BadRequestException.php
new file mode 100644
index 00000000000..9d9e48157a1
--- /dev/null
+++ b/lib/public/Federation/Exceptions/BadRequestException.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation\Exceptions;
+
+use OC\HintException;
+
+/**
+ * Class BadRequestException
+ *
+ * @package OCP\Federation\Exceptions
+ *
+ * @since 14.0.0
+ */
+class BadRequestException extends HintException {
+
+ private $parameterList;
+
+ /**
+ * BadRequestException constructor.
+ *
+ * @since 14.0.0
+ *
+ * @param array $missingParameters
+ */
+ public function __construct(array $missingParameters) {
+ $l = \OC::$server->getL10N('federation');
+ $this->parameterList = $missingParameters;
+ $parameterList = implode(',', $missingParameters);
+ $message = 'Parameters missing in order to complete the request. Missing Parameters: ' . $parameterList;
+ $hint = $l->t('Parameters missing in order to complete the request. Missing Parameters: "%s"', [$parameterList]);
+ parent::__construct($message, $hint);
+ }
+
+ /**
+ * get array with the return message as defined in the OCM API
+ *
+ * @since 14.0.0
+ *
+ * @return array
+ */
+ public function getReturnMessage() {
+ $result = [
+ 'message' => 'RESOURCE_NOT_FOUND',
+ 'validationErrors' =>[
+ ]
+ ];
+
+ foreach ($this->parameterList as $missingParameter) {
+ $result['validationErrors'] = [
+ 'name' => $missingParameter,
+ 'message' => 'NOT_FOUND'
+ ];
+ }
+
+ return $result;
+ }
+
+}
diff --git a/lib/public/Federation/Exceptions/ProviderAlreadyExistsException.php b/lib/public/Federation/Exceptions/ProviderAlreadyExistsException.php
new file mode 100644
index 00000000000..e5022500d1c
--- /dev/null
+++ b/lib/public/Federation/Exceptions/ProviderAlreadyExistsException.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation\Exceptions;
+
+use OC\HintException;
+
+/**
+ * Class ProviderAlreadyExistsException
+ *
+ * @package OCP\Federation\Exceptions
+ *
+ * @since 14.0.0
+ */
+class ProviderAlreadyExistsException extends HintException {
+
+ /**
+ * ProviderAlreadyExistsException constructor.
+ *
+ * @since 14.0.0
+ *
+ * @param string $newProviderId cloud federation provider ID of the new provider
+ * @param string $existingProviderName name of cloud federation provider which already use the same ID
+ */
+ public function __construct($newProviderId, $existingProviderName) {
+ $l = \OC::$server->getL10N('federation');
+ $message = 'Id "' . $newProviderId . '" already used by cloud federation provider "' . $existingProviderName . '"';
+ $hint = $l->t('Id "%s" already used by cloud federation provider "%s"', [$newProviderId, $existingProviderName]);
+ parent::__construct($message, $hint);
+ }
+
+}
diff --git a/lib/public/Federation/Exceptions/ProviderCouldNotAddShareException.php b/lib/public/Federation/Exceptions/ProviderCouldNotAddShareException.php
new file mode 100644
index 00000000000..80613cc29ac
--- /dev/null
+++ b/lib/public/Federation/Exceptions/ProviderCouldNotAddShareException.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation\Exceptions;
+
+use OC\HintException;
+use OCP\AppFramework\Http;
+
+/**
+ * Class ProviderCouldNotAddShareException
+ *
+ * @package OCP\Federation\Exceptions
+ *
+ * @since 14.0.0
+ */
+class ProviderCouldNotAddShareException extends HintException {
+
+ /**
+ * ProviderCouldNotAddShareException constructor.
+ *
+ * @since 14.0.0
+ *
+ * @param string $message
+ * @param string $hint
+ * @param int $code
+ * @param \Exception|null $previous
+ */
+ public function __construct($message, $hint = '', $code = Http::STATUS_BAD_REQUEST, \Exception $previous = null) {
+ parent::__construct($message, $hint, $code, $previous);
+ }
+
+
+}
diff --git a/lib/public/Federation/Exceptions/ProviderDoesNotExistsException.php b/lib/public/Federation/Exceptions/ProviderDoesNotExistsException.php
new file mode 100644
index 00000000000..761fcaf809d
--- /dev/null
+++ b/lib/public/Federation/Exceptions/ProviderDoesNotExistsException.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation\Exceptions;
+
+use OC\HintException;
+
+/**
+ * Class ProviderDoesNotExistsException
+ *
+ * @package OCP\Federation\Exceptions
+ *
+ * @since 14.0.0
+ */
+class ProviderDoesNotExistsException extends HintException {
+
+ /**
+ * ProviderDoesNotExistsException constructor.
+ *
+ * @since 14.0.0
+ *
+ * @param string $providerId cloud federation provider ID
+ */
+ public function __construct($providerId) {
+ $l = \OC::$server->getL10N('federation');
+ $message = 'Cloud Federation Provider with ID: "' . $providerId . '" does not exist.';
+ $hint = $l->t('Cloud Federation Provider with ID: "%s" does not exist.', [$providerId]);
+ parent::__construct($message, $hint);
+ }
+
+}
diff --git a/lib/public/Federation/ICloudFederationFactory.php b/lib/public/Federation/ICloudFederationFactory.php
new file mode 100644
index 00000000000..5cb4dc3106a
--- /dev/null
+++ b/lib/public/Federation/ICloudFederationFactory.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation;
+
+/**
+ * Interface ICloudFederationFactory
+ *
+ * @package OCP\Federation
+ *
+ * @since 14.0.0
+ */
+interface ICloudFederationFactory {
+
+ /**
+ * get a CloudFederationShare Object to prepare a share you want to send
+ *
+ * @param string $shareWith
+ * @param string $name resource name (e.g. document.odt)
+ * @param string $description share description (optional)
+ * @param string $providerId resource UID on the provider side
+ * @param string $owner provider specific UID of the user who owns the resource
+ * @param string $ownerDisplayName display name of the user who shared the item
+ * @param string $sharedBy provider specific UID of the user who shared the resource
+ * @param string $sharedByDisplayName display name of the user who shared the resource
+ * @param string $sharedSecret used to authenticate requests across servers
+ * @param string $shareType ('group' or 'user' share)
+ * @param $resourceType ('file', 'calendar',...)
+ * @return ICloudFederationShare
+ *
+ * @since 14.0.0
+ */
+ public function getCloudFederationShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $sharedSecret, $shareType, $resourceType);
+
+ /**
+ * get a Cloud FederationNotification object to prepare a notification you
+ * want to send
+ *
+ * @return ICloudFederationNotification
+ *
+ * @since 14.0.0
+ */
+ public function getCloudFederationNotification();
+}
diff --git a/lib/public/Federation/ICloudFederationNotification.php b/lib/public/Federation/ICloudFederationNotification.php
new file mode 100644
index 00000000000..c7ceb6d2399
--- /dev/null
+++ b/lib/public/Federation/ICloudFederationNotification.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation;
+
+/**
+ * Interface ICloudFederationNotification
+ *
+ * @package OCP\Federation
+ *
+ * @since 14.0.0
+ */
+interface ICloudFederationNotification {
+
+ /**
+ * add a message to the notification
+ *
+ * @param string $notificationType (e.g. SHARE_ACCEPTED)
+ * @param string $resourceType (e.g. file, calendar, contact,...)
+ * @param $providerId id of the share
+ * @param array $notification , payload of the notification
+ *
+ * @since 14.0.0
+ */
+ public function setMessage($notificationType, $resourceType, $providerId, array $notification);
+
+ /**
+ * get message, ready to send out
+ *
+ * @return array
+ *
+ * @since 14.0.0
+ */
+ public function getMessage();
+}
diff --git a/lib/public/Federation/ICloudFederationProvider.php b/lib/public/Federation/ICloudFederationProvider.php
new file mode 100644
index 00000000000..b3574535cb0
--- /dev/null
+++ b/lib/public/Federation/ICloudFederationProvider.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation;
+
+use OCP\Federation\Exceptions\ActionNotSupportedException;
+use OCP\Federation\Exceptions\AuthenticationFailedException;
+use OCP\Federation\Exceptions\BadRequestException;
+use OCP\Federation\Exceptions\ProviderCouldNotAddShareException;
+use \OCP\Share\Exceptions\ShareNotFound;
+
+/**
+ * Interface ICloudFederationProvider
+ *
+ * Enable apps to create their own cloud federation provider
+ *
+ * @since 14.0.0
+ *
+ * @package OCP\Federation
+ */
+
+interface ICloudFederationProvider {
+
+ /**
+ * get the name of the share type, handled by this provider
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getShareType();
+
+ /**
+ * share received from another server
+ *
+ * @param ICloudFederationShare $share
+ * @return string provider specific unique ID of the share
+ *
+ * @throws ProviderCouldNotAddShareException
+ *
+ * @since 14.0.0
+ */
+ public function shareReceived(ICloudFederationShare $share);
+
+ /**
+ * notification received from another server
+ *
+ * @param string $notificationType (e.g SHARE_ACCEPTED)
+ * @param string $providerId share ID
+ * @param array $notification provider specific notification
+ * @return array $data send back to sender
+ *
+ * @throws ShareNotFound
+ * @throws ActionNotSupportedException
+ * @throws BadRequestException
+ * @throws AuthenticationFailedException
+ *
+ * @since 14.0.0
+ */
+ public function notificationReceived($notificationType, $providerId, array $notification);
+
+ /**
+ * get the supported share types, e.g. "user", "group", etc.
+ *
+ * @return array
+ *
+ * @since 14.0.0
+ */
+ public function getSupportedShareTypes();
+
+}
diff --git a/lib/public/Federation/ICloudFederationProviderManager.php b/lib/public/Federation/ICloudFederationProviderManager.php
new file mode 100644
index 00000000000..f1e932388bf
--- /dev/null
+++ b/lib/public/Federation/ICloudFederationProviderManager.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation;
+
+/**
+ * Class ICloudFederationProviderManager
+ *
+ * Manage cloud federation providers
+ *
+ * @since 14.0.0
+ *
+ * @package OCP\Federation
+ */
+interface ICloudFederationProviderManager {
+
+ /**
+ * Registers an callback function which must return an cloud federation provider
+ *
+ * @param string $resourceType which resource type does the provider handles
+ * @param string $displayName user facing name of the federated share provider
+ * @param callable $callback
+ * @throws Exceptions\ProviderAlreadyExistsException
+ *
+ * @since 14.0.0
+ */
+ public function addCloudFederationProvider($resourceType, $displayName, callable $callback);
+
+ /**
+ * remove cloud federation provider
+ *
+ * @param string $resourceType
+ *
+ * @since 14.0.0
+ */
+ public function removeCloudFederationProvider($resourceType);
+
+ /**
+ * get a list of all cloudFederationProviders
+ *
+ * @return array [resourceType => ['resourceType' => $resourceType, 'displayName' => $displayName, 'callback' => callback]]
+ *
+ * @since 14.0.0
+ */
+ public function getAllCloudFederationProviders();
+
+ /**
+ * get a specific cloud federation provider
+ *
+ * @param string $resourceType
+ * @return ICloudFederationProvider
+ * @throws Exceptions\ProviderDoesNotExistsException;
+ *
+ * @since 14.0.0
+ */
+ public function getCloudFederationProvider($resourceType);
+
+ /**
+ * send federated share
+ *
+ * @param ICloudFederationShare $share
+ * @return mixed
+ *
+ * @since 14.0.0
+ */
+ public function sendShare(ICloudFederationShare $share);
+
+ /**
+ * send notification about existing share
+ *
+ * @param string $url
+ * @param ICloudFederationNotification $notification
+ * @return mixed
+ *
+ * @since 14.0.0
+ */
+ public function sendNotification($url, ICloudFederationNotification $notification);
+
+ /**
+ * check if the new cloud federation API is ready to be used
+ *
+ * @return bool
+ *
+ * @since 14.0.0
+ */
+ public function isReady();
+
+
+}
diff --git a/lib/public/Federation/ICloudFederationShare.php b/lib/public/Federation/ICloudFederationShare.php
new file mode 100644
index 00000000000..fda934d9e8d
--- /dev/null
+++ b/lib/public/Federation/ICloudFederationShare.php
@@ -0,0 +1,250 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
+ *
+ * @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\Federation;
+
+/**
+ * Interface ICloudFederationShare
+ *
+ * @package OCP\Federation
+ *
+ * @since 14.0.0
+ */
+interface ICloudFederationShare {
+
+ /**
+ * set uid of the recipient
+ *
+ * @param string $user
+ *
+ * @since 14.0.0
+ */
+ public function setShareWith($user);
+
+ /**
+ * set resource name (e.g. file, calendar, contact,...)
+ *
+ * @param string $name
+ *
+ * @since 14.0.0
+ */
+ public function setResourceName($name);
+
+ /**
+ * set resource type (e.g. file, calendar, contact,...)
+ *
+ * @param string $resourceType
+ *
+ * @since 14.0.0
+ */
+ public function setResourceType($resourceType);
+
+ /**
+ * set resource description (optional)
+ *
+ * @param string $description
+ *
+ * @since 14.0.0
+ */
+ public function setDescription($description);
+
+ /**
+ * set provider ID (e.g. file ID)
+ *
+ * @param string $providerId
+ *
+ * @since 14.0.0
+ */
+ public function setProviderId($providerId);
+
+ /**
+ * set owner UID
+ *
+ * @param string $owner
+ *
+ * @since 14.0.0
+ */
+ public function setOwner($owner);
+
+ /**
+ * set owner display name
+ *
+ * @param string $ownerDisplayName
+ *
+ * @since 14.0.0
+ */
+ public function setOwnerDisplayName($ownerDisplayName);
+
+ /**
+ * set UID of the user who sends the share
+ *
+ * @param string $sharedBy
+ *
+ * @since 14.0.0
+ */
+ public function setSharedBy($sharedBy);
+
+ /**
+ * set display name of the user who sends the share
+ *
+ * @param $sharedByDisplayName
+ *
+ * @since 14.0.0
+ */
+ public function setSharedByDisplayName($sharedByDisplayName);
+
+ /**
+ * set protocol specification
+ *
+ * @param array $protocol
+ *
+ * @since 14.0.0
+ */
+ public function setProtocol(array $protocol);
+
+ /**
+ * share type (group or user)
+ *
+ * @param string $shareType
+ *
+ * @since 14.0.0
+ */
+ public function setShareType($shareType);
+
+ /**
+ * get the whole share, ready to send out
+ *
+ * @return array
+ *
+ * @since 14.0.0
+ */
+ public function getShare();
+
+ /**
+ * get uid of the recipient
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getShareWith();
+
+ /**
+ * get resource name (e.g. file, calendar, contact,...)
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getResourceName();
+
+ /**
+ * get resource type (e.g. file, calendar, contact,...)
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getResourceType();
+
+ /**
+ * get resource description (optional)
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getDescription();
+
+ /**
+ * get provider ID (e.g. file ID)
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getProviderId();
+
+ /**
+ * get owner UID
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getOwner();
+
+ /**
+ * get owner display name
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getOwnerDisplayName();
+
+ /**
+ * get UID of the user who sends the share
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getSharedBy();
+
+ /**
+ * get display name of the user who sends the share
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getSharedByDisplayName();
+
+ /**
+ * get share type (group or user)
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getShareType();
+
+ /**
+ * get share Secret
+ *
+ * @return string
+ *
+ * @since 14.0.0
+ */
+ public function getShareSecret();
+
+
+ /**
+ * get protocol specification
+ *
+ * @return array
+ *
+ * @since 14.0.0
+ */
+ public function getProtocol();
+
+}
diff --git a/lib/public/Files.php b/lib/public/Files.php
index d66e0f1b645..1cfd73fb288 100644
--- a/lib/public/Files.php
+++ b/lib/public/Files.php
@@ -44,12 +44,14 @@ namespace OCP;
* This class provides access to the internal filesystem abstraction layer. Use
* this class exlusively if you want to access files
* @since 5.0.0
+ * @deprecated 14.0.0
*/
class Files {
/**
* Recusive deletion of folders
* @return bool
* @since 5.0.0
+ * @deprecated 14.0.0
*/
static public function rmdirr( $dir ) {
return \OC_Helper::rmdirr( $dir );
@@ -61,6 +63,7 @@ class Files {
* @return string
* does NOT work for ownClouds filesystem, use OC_FileSystem::getMimeType instead
* @since 5.0.0
+ * @deprecated 14.0.0
*/
static public function getMimeType( $path ) {
return \OC::$server->getMimeTypeDetector()->detect($path);
@@ -71,6 +74,7 @@ class Files {
* @param string $mimetype
* @return array
* @since 6.0.0
+ * @deprecated 14.0.0
*/
static public function searchByMime($mimetype) {
return \OC\Files\Filesystem::searchByMime($mimetype);
@@ -82,6 +86,7 @@ class Files {
* @param resource $target
* @return int the number of bytes copied
* @since 5.0.0
+ * @deprecated 14.0.0
*/
public static function streamCopy( $source, $target ) {
list($count, ) = \OC_Helper::streamCopy( $source, $target );
@@ -89,36 +94,12 @@ class Files {
}
/**
- * Create a temporary file with an unique filename
- * @param string $postfix
- * @return string
- *
- * temporary files are automatically cleaned up after the script is finished
- * @deprecated 8.1.0 use getTemporaryFile() of \OCP\ITempManager - \OC::$server->getTempManager()
- * @since 5.0.0
- */
- public static function tmpFile( $postfix='' ) {
- return \OC::$server->getTempManager()->getTemporaryFile($postfix);
- }
-
- /**
- * Create a temporary folder with an unique filename
- * @return string
- *
- * temporary files are automatically cleaned up after the script is finished
- * @deprecated 8.1.0 use getTemporaryFolder() of \OCP\ITempManager - \OC::$server->getTempManager()
- * @since 5.0.0
- */
- public static function tmpFolder() {
- return \OC::$server->getTempManager()->getTemporaryFolder();
- }
-
- /**
* Adds a suffix to the name in case the file exists
* @param string $path
* @param string $filename
* @return string
* @since 5.0.0
+ * @deprecated 14.0.0 use getNonExistingName of the OCP\Files\Folder object
*/
public static function buildNotExistingFileName($path, $filename) {
return \OC_Helper::buildNotExistingFileName($path, $filename);
@@ -130,6 +111,7 @@ class Files {
* @param string $app
* @return \OC\Files\View
* @since 5.0.0
+ * @deprecated 14.0.0 use IAppData instead
*/
public static function getStorage($app) {
return \OC_App::getStorage( $app );
diff --git a/lib/public/Files/Config/IMountProviderCollection.php b/lib/public/Files/Config/IMountProviderCollection.php
index 93701c326b2..a3f96f37aa6 100644
--- a/lib/public/Files/Config/IMountProviderCollection.php
+++ b/lib/public/Files/Config/IMountProviderCollection.php
@@ -57,6 +57,14 @@ interface IMountProviderCollection {
public function registerProvider(IMountProvider $provider);
/**
+ * Add a filter for mounts
+ *
+ * @param callable $filter (IMountPoint $mountPoint, IUser $user) => boolean
+ * @since 14.0.0
+ */
+ public function registerMountFilter(callable $filter);
+
+ /**
* Add a provider for home mount points
*
* @param \OCP\Files\Config\IHomeMountProvider $provider
diff --git a/lib/public/Files/File.php b/lib/public/Files/File.php
index 8b57b3cfd87..ad2cb7b55c2 100644
--- a/lib/public/Files/File.php
+++ b/lib/public/Files/File.php
@@ -51,9 +51,9 @@ interface File extends Node {
/**
* Write to the file from string data
*
- * @param string $data
+ * @param string|resource $data
* @throws \OCP\Files\NotPermittedException
- * @return void
+ * @throws \OCP\Files\GenericFileException
* @since 6.0.0
*/
public function putContent($data);
diff --git a/lib/public/Files/Folder.php b/lib/public/Files/Folder.php
index 52a4b303196..425813c7e21 100644
--- a/lib/public/Files/Folder.php
+++ b/lib/public/Files/Folder.php
@@ -145,6 +145,9 @@ interface Folder extends Node {
/**
* get a file or folder inside the folder by it's internal id
*
+ * This method could return multiple entries. For example once the file/folder
+ * is shared or mounted (files_external) to the user multiple times.
+ *
* @param int $id
* @return \OCP\Files\Node[]
* @since 6.0.0
diff --git a/lib/public/Files/GenericFileException.php b/lib/public/Files/GenericFileException.php
new file mode 100644
index 00000000000..b5da4aabebd
--- /dev/null
+++ b/lib/public/Files/GenericFileException.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * @copyright 2018, 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 OCP\Files;
+
+/**
+ * Class GenericFileException
+ *
+ * @package OCP\Files
+ * @since 14.0.0
+ */
+class GenericFileException extends \Exception {
+
+}
diff --git a/lib/public/Files/Mount/IMountManager.php b/lib/public/Files/Mount/IMountManager.php
index 2b6458bf7c8..b9ec85bc1d4 100644
--- a/lib/public/Files/Mount/IMountManager.php
+++ b/lib/public/Files/Mount/IMountManager.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -45,7 +46,7 @@ interface IMountManager {
* @param string $mountPoint
* @since 8.2.0
*/
- public function removeMount($mountPoint);
+ public function removeMount(string $mountPoint);
/**
* Change the location of a mount
@@ -54,16 +55,16 @@ interface IMountManager {
* @param string $target
* @since 8.2.0
*/
- public function moveMount($mountPoint, $target);
+ public function moveMount(string $mountPoint, string $target);
/**
* Find the mount for $path
*
* @param string $path
- * @return \OCP\Files\Mount\IMountPoint
+ * @return \OCP\Files\Mount\IMountPoint|null
* @since 8.2.0
*/
- public function find($path);
+ public function find(string $path);
/**
* Find all mounts in $path
@@ -72,7 +73,7 @@ interface IMountManager {
* @return \OCP\Files\Mount\IMountPoint[]
* @since 8.2.0
*/
- public function findIn($path);
+ public function findIn(string $path): array;
/**
* Remove all registered mounts
@@ -88,13 +89,13 @@ interface IMountManager {
* @return \OCP\Files\Mount\IMountPoint[]
* @since 8.2.0
*/
- public function findByStorageId($id);
+ public function findByStorageId(string $id): array;
/**
* @return \OCP\Files\Mount\IMountPoint[]
* @since 8.2.0
*/
- public function getAll();
+ public function getAll(): array;
/**
* Find mounts by numeric storage id
@@ -103,5 +104,5 @@ interface IMountManager {
* @return \OCP\Files\Mount\IMountPoint[]
* @since 8.2.0
*/
- public function findByNumericId($id);
+ public function findByNumericId(int $id): array;
}
diff --git a/lib/public/Files/SimpleFS/ISimpleFile.php b/lib/public/Files/SimpleFS/ISimpleFile.php
index e9182377cb5..a3cd3245cc7 100644
--- a/lib/public/Files/SimpleFS/ISimpleFile.php
+++ b/lib/public/Files/SimpleFS/ISimpleFile.php
@@ -22,6 +22,7 @@
*/
namespace OCP\Files\SimpleFS;
+use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
/**
@@ -67,6 +68,8 @@ interface ISimpleFile {
/**
* Get the content
*
+ * @throws NotPermittedException
+ * @throws NotFoundException
* @return string
* @since 11.0.0
*/
@@ -75,7 +78,7 @@ interface ISimpleFile {
/**
* Overwrite the file
*
- * @param string $data
+ * @param string|resource $data
* @throws NotPermittedException
* @since 11.0.0
*/
@@ -96,4 +99,22 @@ interface ISimpleFile {
* @since 11.0.0
*/
public function getMimeType();
+
+ /**
+ * Open the file as stream for reading, resulting resource can be operated as stream like the result from php's own fopen
+ *
+ * @return resource
+ * @throws \OCP\Files\NotPermittedException
+ * @since 14.0.0
+ */
+ public function read();
+
+ /**
+ * Open the file as stream for writing, resulting resource can be operated as stream like the result from php's own fopen
+ *
+ * @return resource
+ * @throws \OCP\Files\NotPermittedException
+ * @since 14.0.0
+ */
+ public function write();
}
diff --git a/lib/public/Files/SimpleFS/ISimpleRoot.php b/lib/public/Files/SimpleFS/ISimpleRoot.php
index 9b4b8d76947..054106fbaca 100644
--- a/lib/public/Files/SimpleFS/ISimpleRoot.php
+++ b/lib/public/Files/SimpleFS/ISimpleRoot.php
@@ -42,7 +42,7 @@ interface ISimpleRoot {
* @throws \RuntimeException
* @since 11.0.0
*/
- public function getFolder($name);
+ public function getFolder(string $name): ISimpleFolder;
/**
* Get all the Folders
@@ -52,7 +52,7 @@ interface ISimpleRoot {
* @throws \RuntimeException
* @since 11.0.0
*/
- public function getDirectoryListing();
+ public function getDirectoryListing(): array;
/**
* Create a new folder named $name
@@ -63,5 +63,5 @@ interface ISimpleRoot {
* @throws \RuntimeException
* @since 11.0.0
*/
- public function newFolder($name);
+ public function newFolder(string $name): ISimpleFolder;
}
diff --git a/lib/public/Group/Backend/ABackend.php b/lib/public/Group/Backend/ABackend.php
new file mode 100644
index 00000000000..507b9225501
--- /dev/null
+++ b/lib/public/Group/Backend/ABackend.php
@@ -0,0 +1,67 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\Group\Backend;
+
+use OCP\GroupInterface;
+
+/**
+ * @since 14.0.0
+ */
+abstract class ABackend implements GroupInterface {
+
+ /**
+ * @deprecated 14.0.0
+ *
+ * @param int $actions The action to check for
+ * @return bool
+ */
+ public function implementsActions($actions): bool {
+ $implements = 0;
+
+ if ($this instanceof IAddToGroupBackend) {
+ $implements |= GroupInterface::ADD_TO_GROUP;
+ }
+ if ($this instanceof ICountUsersBackend) {
+ $implements |= GroupInterface::COUNT_USERS;
+ }
+ if ($this instanceof ICreateGroupBackend) {
+ $implements |= GroupInterface::CREATE_GROUP;
+ }
+ if ($this instanceof IDeleteGroupBackend) {
+ $implements |= GroupInterface::DELETE_GROUP;
+ }
+ if ($this instanceof IGroupDetailsBackend) {
+ $implements |= GroupInterface::GROUP_DETAILS;
+ }
+ if ($this instanceof IIsAdminBackend) {
+ $implements |= GroupInterface::IS_ADMIN;
+ }
+ if ($this instanceof IRemoveFromGroupBackend) {
+ $implements |= GroupInterface::REMOVE_FROM_GOUP;
+ }
+
+ return (bool)($actions & $implements);
+ }
+}
diff --git a/lib/public/Group/Backend/IAddToGroupBackend.php b/lib/public/Group/Backend/IAddToGroupBackend.php
new file mode 100644
index 00000000000..aba0444e9b6
--- /dev/null
+++ b/lib/public/Group/Backend/IAddToGroupBackend.php
@@ -0,0 +1,36 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\Group\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface IAddToGroupBackend {
+
+ /**
+ * @since 14.0.0
+ */
+ public function addToGroup(string $uid, string $gid): bool;
+}
diff --git a/lib/public/Group/Backend/ICountDisabledInGroup.php b/lib/public/Group/Backend/ICountDisabledInGroup.php
new file mode 100644
index 00000000000..fa07bcf7e5b
--- /dev/null
+++ b/lib/public/Group/Backend/ICountDisabledInGroup.php
@@ -0,0 +1,36 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.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\Group\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface ICountDisabledInGroup {
+
+ /**
+ * @since 14.0.0
+ */
+ public function countDisabledInGroup(string $gid): int;
+}
diff --git a/lib/public/Group/Backend/ICountUsersBackend.php b/lib/public/Group/Backend/ICountUsersBackend.php
new file mode 100644
index 00000000000..1bdf54b4fd8
--- /dev/null
+++ b/lib/public/Group/Backend/ICountUsersBackend.php
@@ -0,0 +1,36 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\Group\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface ICountUsersBackend {
+
+ /**
+ * @since 14.0.0
+ */
+ public function countUsersInGroup(string $gid, string $search = ''): int;
+}
diff --git a/lib/public/Group/Backend/ICreateGroupBackend.php b/lib/public/Group/Backend/ICreateGroupBackend.php
new file mode 100644
index 00000000000..1a49bc221c0
--- /dev/null
+++ b/lib/public/Group/Backend/ICreateGroupBackend.php
@@ -0,0 +1,36 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\Group\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface ICreateGroupBackend {
+
+ /**
+ * @since 14.0.0
+ */
+ public function createGroup(string $gid): bool;
+}
diff --git a/lib/public/Group/Backend/IDeleteGroupBackend.php b/lib/public/Group/Backend/IDeleteGroupBackend.php
new file mode 100644
index 00000000000..09ca789d381
--- /dev/null
+++ b/lib/public/Group/Backend/IDeleteGroupBackend.php
@@ -0,0 +1,36 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\Group\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface IDeleteGroupBackend {
+
+ /**
+ * @since 14.0.0
+ */
+ public function deleteGroup(string $gid): bool;
+}
diff --git a/lib/public/Group/Backend/IGroupDetailsBackend.php b/lib/public/Group/Backend/IGroupDetailsBackend.php
new file mode 100644
index 00000000000..fd43510c6bf
--- /dev/null
+++ b/lib/public/Group/Backend/IGroupDetailsBackend.php
@@ -0,0 +1,36 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\Group\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface IGroupDetailsBackend {
+
+ /**
+ * @since 14.0.0
+ */
+ public function getGroupDetails(string $gid): array;
+}
diff --git a/lib/public/Group/Backend/IIsAdminBackend.php b/lib/public/Group/Backend/IIsAdminBackend.php
new file mode 100644
index 00000000000..e253a293dc9
--- /dev/null
+++ b/lib/public/Group/Backend/IIsAdminBackend.php
@@ -0,0 +1,36 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\Group\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface IIsAdminBackend {
+
+ /**
+ * @since 14.0.0
+ */
+ public function isAdmin(string $uid): bool;
+}
diff --git a/lib/public/Group/Backend/IRemoveFromGroupBackend.php b/lib/public/Group/Backend/IRemoveFromGroupBackend.php
new file mode 100644
index 00000000000..885a5bbcdca
--- /dev/null
+++ b/lib/public/Group/Backend/IRemoveFromGroupBackend.php
@@ -0,0 +1,36 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\Group\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface IRemoveFromGroupBackend {
+
+ /**
+ * @since 14.0.0
+ */
+ public function removeFromGroup(string $uid, string $gid);
+}
diff --git a/lib/public/IAvatar.php b/lib/public/IAvatar.php
index a6731b63be9..85863357069 100644
--- a/lib/public/IAvatar.php
+++ b/lib/public/IAvatar.php
@@ -8,6 +8,7 @@
* @author Robin Appelman <robin@icewind.nl>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0
*
@@ -26,6 +27,7 @@
*/
namespace OCP;
+
use OCP\Files\File;
use OCP\Files\NotFoundException;
@@ -79,6 +81,13 @@ interface IAvatar {
public function getFile($size);
/**
+ * @param string $text
+ * @return Color Object containting r g b int in the range [0, 255]
+ * @since 14.0.0
+ */
+ public function avatarBackgroundColor(string $text);
+
+ /**
* Handle a changed user
* @since 13.0.0
*/
diff --git a/lib/public/ICacheFactory.php b/lib/public/ICacheFactory.php
index 76145fe1f78..a078543b092 100644
--- a/lib/public/ICacheFactory.php
+++ b/lib/public/ICacheFactory.php
@@ -52,6 +52,14 @@ interface ICacheFactory{
public function isAvailable(): bool;
/**
+ * Check if a local memory cache backend is available
+ *
+ * @return bool
+ * @since 14.0.0
+ */
+ public function isLocalCacheAvailable(): bool;
+
+ /**
* create a cache instance for storing locks
*
* @param string $prefix
diff --git a/lib/public/IDBConnection.php b/lib/public/IDBConnection.php
index f0783d5231a..4e450eae736 100644
--- a/lib/public/IDBConnection.php
+++ b/lib/public/IDBConnection.php
@@ -45,6 +45,10 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
* @since 6.0.0
*/
interface IDBConnection {
+
+ const ADD_MISSING_INDEXES_EVENT = self::class . '::ADD_MISSING_INDEXES';
+ const CHECK_MISSING_INDEXES_EVENT = self::class . '::CHECK_MISSING_INDEXES';
+
/**
* Gets the QueryBuilder for the connection.
*
diff --git a/lib/public/IGroup.php b/lib/public/IGroup.php
index da1a4f5dd1e..8fa87e35ce3 100644
--- a/lib/public/IGroup.php
+++ b/lib/public/IGroup.php
@@ -101,6 +101,14 @@ interface IGroup {
public function count($search = '');
/**
+ * returns the number of disabled users
+ *
+ * @return int|bool
+ * @since 14.0.0
+ */
+ public function countDisabled();
+
+ /**
* search for users in the group by displayname
*
* @param string $search
@@ -118,4 +126,16 @@ interface IGroup {
* @since 8.0.0
*/
public function delete();
+
+ /**
+ * @return bool
+ * @since 14.0.0
+ */
+ public function canRemoveUser();
+
+ /**
+ * @return bool
+ * @since 14.0.0
+ */
+ public function canAddUser();
}
diff --git a/lib/public/IHelper.php b/lib/public/IHelper.php
deleted file mode 100644
index 707884b82f8..00000000000
--- a/lib/public/IHelper.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @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/>
- *
- */
-
-/**
- * Public interface of ownCloud for apps to use.
- * Helper interface
- *
- */
-
-// use OCP namespace for all classes that are considered public.
-// This means that they should be used by apps instead of the internal ownCloud classes
-namespace OCP;
-
-/**
- * Functions that don't have any specific interface to place
- * @since 6.0.0
- * @deprecated 8.1.0
- */
-interface IHelper {
- /**
- * Gets the content of an URL by using CURL or a fallback if it is not
- * installed
- * @param string $url the url that should be fetched
- * @return string the content of the webpage
- * @since 6.0.0
- * @deprecated 8.1.0 Use \OCP\IServerContainer::getHTTPClientService
- */
- public function getUrlContent($url);
-}
diff --git a/lib/public/IL10N.php b/lib/public/IL10N.php
index 7af5008b814..53decd78051 100644
--- a/lib/public/IL10N.php
+++ b/lib/public/IL10N.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -7,6 +8,7 @@
* @author Joas Schilling <coding@schilljs.com>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Roeland Jago Douma <roeland@famdouma.nl>
+ * @author Thomas Citharel <tcit@tcit.fr>
*
* @license AGPL-3.0
*
@@ -44,14 +46,14 @@ interface IL10N {
/**
* Translating
* @param string $text The text we need a translation for
- * @param array $parameters default:array() Parameters for sprintf
+ * @param array|string $parameters default:array() Parameters for sprintf
* @return string Translation or the same text
*
* Returns the translation. If no translation is found, $text will be
* returned.
* @since 6.0.0
*/
- public function t($text, $parameters = array());
+ public function t(string $text, $parameters = []): string;
/**
* Translating
@@ -69,7 +71,7 @@ interface IL10N {
* @since 6.0.0
*
*/
- public function n($text_singular, $text_plural, $count, $parameters = array());
+ public function n(string $text_singular, string $text_plural, int $count, array $parameters = []): string;
/**
* Localization
@@ -96,7 +98,7 @@ interface IL10N {
* - params: timestamp (int/string)
* @since 6.0.0 - parameter $options was added in 8.0.0
*/
- public function l($type, $data, $options = array());
+ public function l(string $type, $data, array $options = []);
/**
@@ -105,5 +107,13 @@ interface IL10N {
* @return string language
* @since 7.0.0
*/
- public function getLanguageCode();
+ public function getLanguageCode(): string ;
+
+ /**
+ * * The code (en_US, fr_CA, ...) of the locale that is used for this IL10N object
+ *
+ * @return string locale
+ * @since 14.0.0
+ */
+ public function getLocaleCode(): string;
}
diff --git a/lib/public/ILogger.php b/lib/public/ILogger.php
index 6ee850ee8ae..d3bb67b1b27 100644
--- a/lib/public/ILogger.php
+++ b/lib/public/ILogger.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -36,6 +37,27 @@ namespace OCP;
*/
interface ILogger {
/**
+ * @since 14.0.0
+ */
+ const DEBUG=0;
+ /**
+ * @since 14.0.0
+ */
+ const INFO=1;
+ /**
+ * @since 14.0.0
+ */
+ const WARN=2;
+ /**
+ * @since 14.0.0
+ */
+ const ERROR=3;
+ /**
+ * @since 14.0.0
+ */
+ const FATAL=4;
+
+ /**
* System is unusable.
*
* @param string $message
@@ -43,7 +65,7 @@ interface ILogger {
* @return null
* @since 7.0.0
*/
- public function emergency($message, array $context = array());
+ public function emergency(string $message, array $context = []);
/**
* Action must be taken immediately.
@@ -53,7 +75,7 @@ interface ILogger {
* @return null
* @since 7.0.0
*/
- public function alert($message, array $context = array());
+ public function alert(string $message, array $context = []);
/**
* Critical conditions.
@@ -63,7 +85,7 @@ interface ILogger {
* @return null
* @since 7.0.0
*/
- public function critical($message, array $context = array());
+ public function critical(string $message, array $context = []);
/**
* Runtime errors that do not require immediate action but should typically
@@ -74,7 +96,7 @@ interface ILogger {
* @return null
* @since 7.0.0
*/
- public function error($message, array $context = array());
+ public function error(string $message, array $context = []);
/**
* Exceptional occurrences that are not errors.
@@ -84,7 +106,7 @@ interface ILogger {
* @return null
* @since 7.0.0
*/
- public function warning($message, array $context = array());
+ public function warning(string $message, array $context = []);
/**
* Normal but significant events.
@@ -94,7 +116,7 @@ interface ILogger {
* @return null
* @since 7.0.0
*/
- public function notice($message, array $context = array());
+ public function notice(string $message, array $context = []);
/**
* Interesting events.
@@ -104,7 +126,7 @@ interface ILogger {
* @return null
* @since 7.0.0
*/
- public function info($message, array $context = array());
+ public function info(string $message, array $context = []);
/**
* Detailed debug information.
@@ -114,18 +136,18 @@ interface ILogger {
* @return null
* @since 7.0.0
*/
- public function debug($message, array $context = array());
+ public function debug(string $message, array $context = []);
/**
* Logs with an arbitrary level.
*
- * @param mixed $level
+ * @param int $level
* @param string $message
* @param array $context
* @return mixed
* @since 7.0.0
*/
- public function log($level, $message, array $context = array());
+ public function log(int $level, string $message, array $context = []);
/**
* Logs an exception very detailed
@@ -143,5 +165,5 @@ interface ILogger {
* @return void
* @since 8.2.0
*/
- public function logException($exception, array $context = array());
+ public function logException(\Throwable $exception, array $context = []);
}
diff --git a/lib/public/INavigationManager.php b/lib/public/INavigationManager.php
index 216f8a897d8..77b881b8b15 100644
--- a/lib/public/INavigationManager.php
+++ b/lib/public/INavigationManager.php
@@ -57,4 +57,13 @@ interface INavigationManager {
* @since 6.0.0
*/
public function setActiveEntry($appId);
+
+ /**
+ * Get a list of navigation entries
+ *
+ * @param string $type type of the navigation entries
+ * @return array
+ * @since 14.0.0
+ */
+ public function getAll(string $type = 'link'): array;
}
diff --git a/lib/public/IRequest.php b/lib/public/IRequest.php
index a14b6b5f459..05948cd480f 100644
--- a/lib/public/IRequest.php
+++ b/lib/public/IRequest.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -90,12 +91,22 @@ interface IRequest {
const USER_AGENT_TALK_IOS = '/^Mozilla\/5\.0 \(iOS\) Nextcloud\-Talk v.*$/';
/**
+ * @since 13.0.1
+ */
+ const USER_AGENT_OUTLOOK_ADDON = '/^Mozilla\/5\.0 \([A-Za-z ]+\) Nextcloud\-Outlook v.*$/';
+
+ /**
+ * @since 13.0.1
+ */
+ const USER_AGENT_THUNDERBIRD_ADDON = '/^Mozilla\/5\.0 \([A-Za-z ]+\) Nextcloud\-Thunderbird v.*$/';
+
+ /**
* @param string $name
*
* @return string
* @since 6.0.0
*/
- public function getHeader($name);
+ public function getHeader(string $name): string;
/**
* Lets you access post and get parameters by the index
@@ -111,7 +122,7 @@ interface IRequest {
* @return mixed the content of the array
* @since 6.0.0
*/
- public function getParam($key, $default = null);
+ public function getParam(string $key, $default = null);
/**
@@ -122,7 +133,7 @@ interface IRequest {
* @return array the array with all parameters
* @since 6.0.0
*/
- public function getParams();
+ public function getParams(): array;
/**
* Returns the method of the request
@@ -130,7 +141,7 @@ interface IRequest {
* @return string the method of the request (POST, GET, etc)
* @since 6.0.0
*/
- public function getMethod();
+ public function getMethod(): string;
/**
* Shortcut for accessing an uploaded file through the $_FILES array
@@ -139,7 +150,7 @@ interface IRequest {
* @return array the file in the $_FILES element
* @since 6.0.0
*/
- public function getUploadedFile($key);
+ public function getUploadedFile(string $key);
/**
@@ -149,7 +160,7 @@ interface IRequest {
* @return array the value in the $_ENV element
* @since 6.0.0
*/
- public function getEnv($key);
+ public function getEnv(string $key);
/**
@@ -159,7 +170,7 @@ interface IRequest {
* @return string|null the value in the $_COOKIE element
* @since 6.0.0
*/
- public function getCookie($key);
+ public function getCookie(string $key);
/**
@@ -168,7 +179,7 @@ interface IRequest {
* @return bool true if CSRF check passed
* @since 6.0.0
*/
- public function passesCSRFCheck();
+ public function passesCSRFCheck(): bool;
/**
* Checks if the strict cookie has been sent with the request if the request
@@ -177,7 +188,7 @@ interface IRequest {
* @return bool
* @since 9.0.0
*/
- public function passesStrictCookieCheck();
+ public function passesStrictCookieCheck(): bool;
/**
* Checks if the lax cookie has been sent with the request if the request
@@ -186,7 +197,7 @@ interface IRequest {
* @return bool
* @since 9.0.0
*/
- public function passesLaxCookieCheck();
+ public function passesLaxCookieCheck(): bool;
/**
* Returns an ID for the request, value is not guaranteed to be unique and is mostly meant for logging
@@ -195,7 +206,7 @@ interface IRequest {
* @return string
* @since 8.1.0
*/
- public function getId();
+ public function getId(): string;
/**
* Returns the remote address, if the connection came from a trusted proxy
@@ -206,7 +217,7 @@ interface IRequest {
* @return string IP address
* @since 8.1.0
*/
- public function getRemoteAddress();
+ public function getRemoteAddress(): string;
/**
* Returns the server protocol. It respects reverse proxy servers and load
@@ -215,7 +226,7 @@ interface IRequest {
* @return string Server protocol (http or https)
* @since 8.1.0
*/
- public function getServerProtocol();
+ public function getServerProtocol(): string;
/**
* Returns the used HTTP protocol.
@@ -223,7 +234,7 @@ interface IRequest {
* @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0.
* @since 8.2.0
*/
- public function getHttpProtocol();
+ public function getHttpProtocol(): string;
/**
* Returns the request uri, even if the website uses one or more
@@ -232,7 +243,7 @@ interface IRequest {
* @return string
* @since 8.1.0
*/
- public function getRequestUri();
+ public function getRequestUri(): string;
/**
* Get raw PathInfo from request (not urldecoded)
@@ -241,7 +252,7 @@ interface IRequest {
* @return string Path info
* @since 8.1.0
*/
- public function getRawPathInfo();
+ public function getRawPathInfo(): string;
/**
* Get PathInfo from request
@@ -259,7 +270,7 @@ interface IRequest {
* @return string the script name
* @since 8.1.0
*/
- public function getScriptName();
+ public function getScriptName(): string;
/**
* Checks whether the user agent matches a given regex
@@ -268,7 +279,7 @@ interface IRequest {
* @return bool true if at least one of the given agent matches, false otherwise
* @since 8.1.0
*/
- public function isUserAgent(array $agent);
+ public function isUserAgent(array $agent): bool;
/**
* Returns the unverified server host from the headers without checking
@@ -277,7 +288,7 @@ interface IRequest {
* @return string Server host
* @since 8.1.0
*/
- public function getInsecureServerHost();
+ public function getInsecureServerHost(): string;
/**
* Returns the server host from the headers, or the first configured
@@ -286,5 +297,5 @@ interface IRequest {
* @return string Server host
* @since 8.1.0
*/
- public function getServerHost();
+ public function getServerHost(): string;
}
diff --git a/lib/public/IServerContainer.php b/lib/public/IServerContainer.php
index 851a3c7e2bb..639487660b6 100644
--- a/lib/public/IServerContainer.php
+++ b/lib/public/IServerContainer.php
@@ -44,6 +44,9 @@
// use OCP namespace for all classes that are considered public.
// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP;
+use OCP\Log\ILogFactory;
+use OCP\Federation\ICloudFederationFactory;
+use OCP\Federation\ICloudFederationProviderManager;
use OCP\Security\IContentSecurityPolicyManager;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@@ -67,6 +70,24 @@ interface IServerContainer extends IContainer {
public function getCalendarManager();
/**
+ * The calendar resource backend manager will act as a broker between consumers
+ * for calendar resource information an providers which actual deliver the room information.
+ *
+ * @return \OCP\Calendar\Resource\IBackend
+ * @since 14.0.0
+ */
+ public function getCalendarResourceBackendManager();
+
+ /**
+ * The calendar room backend manager will act as a broker between consumers
+ * for calendar room information an providers which actual deliver the room information.
+ *
+ * @return \OCP\Calendar\Room\IBackend
+ * @since 14.0.0
+ */
+ public function getCalendarRoomBackendManager();
+
+ /**
* The contacts manager will act as a broker between consumers for contacts information and
* providers which actual deliver the contact information.
*
@@ -125,7 +146,7 @@ interface IServerContainer extends IContainer {
*
* @return \OCP\Files\Folder
* @since 6.0.0
- * @deprecated since 9.2.0 use IAppData
+ * @deprecated 9.2.0 use IAppData
*/
public function getAppFolder();
@@ -251,14 +272,6 @@ interface IServerContainer extends IContainer {
public function getURLGenerator();
/**
- * Returns the Helper
- *
- * @return \OCP\IHelper
- * @since 6.0.0
- */
- public function getHelper();
-
- /**
* Returns an ICache instance
*
* @return \OCP\ICache
@@ -323,6 +336,14 @@ interface IServerContainer extends IContainer {
public function getLogger();
/**
+ * returns a log factory instance
+ *
+ * @return ILogFactory
+ * @since 14.0.0
+ */
+ public function getLogFactory();
+
+ /**
* Returns a router for generating and matching urls
*
* @return \OCP\Route\IRouter
@@ -356,14 +377,6 @@ interface IServerContainer extends IContainer {
public function createEventSource();
/**
- * Returns an instance of the HTTP helper class
- * @return \OC\HTTPHelper
- * @deprecated 8.1.0 Use \OCP\Http\Client\IClientService
- * @since 8.0.0
- */
- public function getHTTPHelper();
-
- /**
* Returns an instance of the HTTP client service
*
* @return \OCP\Http\Client\IClientService
@@ -543,6 +556,24 @@ interface IServerContainer extends IContainer {
public function getCloudIdManager();
/**
+ * @return \OCP\GlobalScale\IConfig
+ * @since 14.0.0
+ */
+ public function getGlobalScaleConfig();
+
+ /**
+ * @return ICloudFederationFactory
+ * @since 14.0.0
+ */
+ public function getCloudFederationFactory();
+
+ /**
+ * @return ICloudFederationProviderManager
+ * @since 14.0.0
+ */
+ public function getCloudFederationProviderManager();
+
+ /**
* @return \OCP\Remote\Api\IApiFactory
* @since 13.0.0
*/
diff --git a/lib/public/ISession.php b/lib/public/ISession.php
index 2d234976862..bbf36c86520 100644
--- a/lib/public/ISession.php
+++ b/lib/public/ISession.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -34,6 +35,8 @@
// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP;
+use OCP\Session\Exceptions\SessionNotAvailableException;
+
/**
* Interface ISession
*
@@ -49,7 +52,7 @@ interface ISession {
* @param mixed $value
* @since 6.0.0
*/
- public function set($key, $value);
+ public function set(string $key, $value);
/**
* Get a value from the session
@@ -58,7 +61,7 @@ interface ISession {
* @return mixed should return null if $key does not exist
* @since 6.0.0
*/
- public function get($key);
+ public function get(string $key);
/**
* Check if a named key exists in the session
@@ -67,7 +70,7 @@ interface ISession {
* @return bool
* @since 6.0.0
*/
- public function exists($key);
+ public function exists(string $key): bool;
/**
* Remove a $key/$value pair from the session
@@ -75,7 +78,7 @@ interface ISession {
* @param string $key
* @since 6.0.0
*/
- public function remove($key);
+ public function remove(string $key);
/**
* Reset and recreate the session
@@ -93,10 +96,11 @@ interface ISession {
* Wrapper around session_regenerate_id
*
* @param bool $deleteOldSession Whether to delete the old associated session file or not.
+ * @param bool $updateToken Wheater to update the associated auth token
* @return void
- * @since 9.0.0
+ * @since 9.0.0, $updateToken added in 14.0.0
*/
- public function regenerateId($deleteOldSession = true);
+ public function regenerateId(bool $deleteOldSession = true, bool $updateToken = false);
/**
* Wrapper around session_id
@@ -105,5 +109,5 @@ interface ISession {
* @throws SessionNotAvailableException
* @since 9.1.0
*/
- public function getId();
+ public function getId(): string;
}
diff --git a/lib/public/IUser.php b/lib/public/IUser.php
index 13aa60b3807..3d8515a5e03 100644
--- a/lib/public/IUser.php
+++ b/lib/public/IUser.php
@@ -146,7 +146,7 @@ interface IUser {
* @param bool $enabled
* @since 8.0.0
*/
- public function setEnabled($enabled);
+ public function setEnabled(bool $enabled = true);
/**
* get the users email address
diff --git a/lib/public/IUserManager.php b/lib/public/IUserManager.php
index 163e8b5e73f..d20b4a3fa9a 100644
--- a/lib/public/IUserManager.php
+++ b/lib/public/IUserManager.php
@@ -40,6 +40,9 @@ namespace OCP;
* - postDelete(\OC\User\User $user)
* - preCreateUser(string $uid, string $password)
* - postCreateUser(\OC\User\User $user, string $password)
+ * - assignedUserId(string $uid)
+ * - preUnassignedUserId(string $uid)
+ * - postUnassignedUserId(string $uid)
*
* @package OC\User
* @since 8.0.0
diff --git a/lib/public/JSON.php b/lib/public/JSON.php
deleted file mode 100644
index c56c3b645a9..00000000000
--- a/lib/public/JSON.php
+++ /dev/null
@@ -1,209 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-/**
- * Public interface of ownCloud for apps to use.
- * JSON Class
- */
-
-// use OCP namespace for all classes that are considered public.
-// This means that they should be used by apps instead of the internal ownCloud classes
-namespace OCP;
-
-/**
- * This class provides convenient functions to generate and send JSON data. Useful for Ajax calls
- * @deprecated 8.1.0 Use a AppFramework JSONResponse instead
- */
-class JSON {
- /**
- * Encode and print $data in JSON format
- * @param array $data The data to use
- * @param bool $setContentType the optional content type
- * @deprecated 8.1.0 Use a AppFramework JSONResponse instead
- *
- * @suppress PhanDeprecatedFunction
- */
- public static function encodedPrint( $data, $setContentType=true ) {
- \OC_JSON::encodedPrint($data, $setContentType);
- }
-
- /**
- * Check if the user is logged in, send json error msg if not.
- *
- * This method checks if a user is logged in. If not, a json error
- * response will be return and the method will exit from execution
- * of the script.
- * The returned json will be in the format:
- *
- * {"status":"error","data":{"message":"Authentication error."}}
- *
- * Add this call to the start of all ajax method files that requires
- * an authenticated user.
- * @deprecated 8.1.0 Use annotation based ACLs from the AppFramework instead
- *
- * @suppress PhanDeprecatedFunction
- */
- public static function checkLoggedIn() {
- \OC_JSON::checkLoggedIn();
- }
-
- /**
- * Check an ajax get/post call if the request token is valid.
- *
- * This method checks for a valid variable 'requesttoken' in $_GET,
- * $_POST and $_SERVER. If a valid token is not found, a json error
- * response will be return and the method will exit from execution
- * of the script.
- * The returned json will be in the format:
- *
- * {"status":"error","data":{"message":"Token expired. Please reload page."}}
- *
- * Add this call to the start of all ajax method files that creates,
- * updates or deletes anything.
- * In cases where you e.g. use an ajax call to load a dialog containing
- * a submittable form, you will need to add the requesttoken first as a
- * parameter to the ajax call, then assign it to the template and finally
- * add a hidden input field also named 'requesttoken' containing the value.
- * @deprecated 8.1.0 Use annotation based CSRF checks from the AppFramework instead
- *
- * @suppress PhanDeprecatedFunction
- */
- public static function callCheck() {
- \OC_JSON::callCheck();
- }
-
- /**
- * Send json success msg
- *
- * Return a json success message with optional extra data.
- * @see \OCP\JSON::error() for the format to use.
- *
- * @param array $data The data to use
- * @deprecated 8.1.0 Use a AppFramework JSONResponse instead
- * @suppress PhanDeprecatedFunction
- */
- public static function success( $data = array() ) {
- \OC_JSON::success($data);
- }
-
- /**
- * Send json error msg
- *
- * Return a json error message with optional extra data for
- * error message or app specific data.
- *
- * Example use:
- *
- * $id = [some value]
- * OCP\JSON::error(array('data':array('message':'An error happened', 'id': $id)));
- *
- * Will return the json formatted string:
- *
- * {"status":"error","data":{"message":"An error happened", "id":[some value]}}
- *
- * @param array $data The data to use
- * @deprecated 8.1.0 Use a AppFramework JSONResponse instead
- * @suppress PhanDeprecatedFunction
- */
- public static function error( $data = array() ) {
- \OC_JSON::error($data);
- }
-
- /**
- * Set Content-Type header to jsonrequest
- * @param string $type The content type header
- * @deprecated 8.1.0 Use a AppFramework JSONResponse instead
- * @suppress PhanDeprecatedFunction
- */
- public static function setContentTypeHeader( $type='application/json' ) {
- \OC_JSON::setContentTypeHeader($type);
- }
-
- /**
- * Check if the App is enabled and send JSON error message instead
- *
- * This method checks if a specific app is enabled. If not, a json error
- * response will be return and the method will exit from execution
- * of the script.
- * The returned json will be in the format:
- *
- * {"status":"error","data":{"message":"Application is not enabled."}}
- *
- * Add this call to the start of all ajax method files that requires
- * a specific app to be enabled.
- *
- * @param string $app The app to check
- * @deprecated 8.1.0 Use the AppFramework instead. It will automatically check if the app is enabled.
- * @suppress PhanDeprecatedFunction
- */
- public static function checkAppEnabled( $app ) {
- \OC_JSON::checkAppEnabled($app);
- }
-
- /**
- * Check if the user is a admin, send json error msg if not
- *
- * This method checks if the current user has admin rights. If not, a json error
- * response will be return and the method will exit from execution
- * of the script.
- * The returned json will be in the format:
- *
- * {"status":"error","data":{"message":"Authentication error."}}
- *
- * Add this call to the start of all ajax method files that requires
- * administrative rights.
- *
- * @deprecated 8.1.0 Use annotation based ACLs from the AppFramework instead
- * @suppress PhanDeprecatedFunction
- */
- public static function checkAdminUser() {
- \OC_JSON::checkAdminUser();
- }
-
- /**
- * Encode JSON
- * @param array $data
- * @return string
- * @deprecated 8.1.0 Use a AppFramework JSONResponse instead
- * @suppress PhanDeprecatedFunction
- */
- public static function encode($data) {
- return \OC_JSON::encode($data);
- }
-
- /**
- * Check is a given user exists - send json error msg if not
- * @param string $user
- * @deprecated 8.1.0 Use a AppFramework JSONResponse instead
- * @suppress PhanDeprecatedFunction
- */
- public static function checkUserExists($user) {
- \OC_JSON::checkUserExists($user);
- }
-}
diff --git a/lib/public/L10N/IFactory.php b/lib/public/L10N/IFactory.php
index 9820082c72e..1bc231e4e2e 100644
--- a/lib/public/L10N/IFactory.php
+++ b/lib/public/L10N/IFactory.php
@@ -21,6 +21,8 @@
*/
namespace OCP\L10N;
+use OCP\IUser;
+
/**
* @since 8.2.0
*/
@@ -45,6 +47,13 @@ interface IFactory {
public function findLanguage($app = null);
/**
+ * @param string|null $lang user language as default locale
+ * @return string locale If nothing works it returns 'en_US'
+ * @since 14.0.0
+ */
+ public function findLocale($lang = null);
+
+ /**
* Find all available languages for an app
*
* @param string|null $app App id or null for core
@@ -54,10 +63,48 @@ interface IFactory {
public function findAvailableLanguages($app = null);
/**
+ * @return array an array of available
+ * @since 14.0.0
+ */
+ public function findAvailableLocales();
+
+ /**
* @param string|null $app App id or null for core
* @param string $lang
* @return bool
* @since 9.0.0
*/
public function languageExists($app, $lang);
+
+ /**
+ * @param string $locale
+ * @return bool
+ * @since 14.0.0
+ */
+ public function localeExists($locale);
+
+ /**
+ * Creates a function from the plural string
+ *
+ * @param string $string
+ * @return string Unique function name
+ * @since 14.0.0
+ */
+ public function createPluralFunction($string);
+
+ /**
+ * iterate through language settings (if provided) in this order:
+ * 1. returns the forced language or:
+ * 2. if applicable, the trunk of 1 (e.g. "fu" instead of "fu_BAR"
+ * 3. returns the user language or:
+ * 4. if applicable, the trunk of 3
+ * 5. returns the system default language or:
+ * 6. if applicable, the trunk of 5
+ * 7+∞. returns 'en'
+ *
+ * Hint: in most cases findLanguage() suits you fine
+ *
+ * @since 14.0.0
+ */
+ public function getLanguageIterator(IUser $user = null): ILanguageIterator;
}
diff --git a/lib/public/L10N/ILanguageIterator.php b/lib/public/L10N/ILanguageIterator.php
new file mode 100644
index 00000000000..ef923dfd249
--- /dev/null
+++ b/lib/public/L10N/ILanguageIterator.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 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\L10N;
+
+/**
+ * Interface ILanguageIterator
+ *
+ * iterator across language settings (if provided) in this order:
+ * 1. returns the forced language or:
+ * 2. if applicable, the trunk of 1 (e.g. "fu" instead of "fu_BAR"
+ * 3. returns the user language or:
+ * 4. if applicable, the trunk of 3
+ * 5. returns the system default language or:
+ * 6. if applicable, the trunk of 5
+ * 7+∞. returns 'en'
+ *
+ * if settings are not present or truncating is not applicable, the iterator
+ * skips to the next valid item itself
+ *
+ * @package OCP\L10N
+ *
+ * @since 14.0.0
+ */
+interface ILanguageIterator extends \Iterator {
+
+ /**
+ * Return the current element
+ *
+ * @since 14.0.0
+ */
+ public function current(): string;
+
+ /**
+ * Move forward to next element
+ *
+ * @since 14.0.0
+ */
+ public function next();
+
+ /**
+ * Return the key of the current element
+ *
+ * @since 14.0.0
+ */
+ public function key():int;
+
+ /**
+ * Checks if current position is valid
+ *
+ * @since 14.0.0
+ */
+ public function valid():bool;
+}
diff --git a/lib/public/Lock/LockedException.php b/lib/public/Lock/LockedException.php
index 1378f437c3a..b4038f8dd55 100644
--- a/lib/public/Lock/LockedException.php
+++ b/lib/public/Lock/LockedException.php
@@ -46,11 +46,15 @@ class LockedException extends \Exception {
*
* @param string $path locked path
* @param \Exception|null $previous previous exception for cascading
- *
+ * @param string $existingLock since 14.0.0
* @since 8.1.0
*/
- public function __construct(string $path, \Exception $previous = null) {
- parent::__construct('"' . $path . '" is locked', 0, $previous);
+ public function __construct(string $path, \Exception $previous = null, string $existingLock = null) {
+ $message = '"' . $path . '" is locked';
+ if ($existingLock) {
+ $message .= ', existing lock on file: ' . $existingLock;
+ }
+ parent::__construct($message, 0, $previous);
$this->path = $path;
}
diff --git a/lib/public/Log/IFileBased.php b/lib/public/Log/IFileBased.php
new file mode 100644
index 00000000000..c0eef472975
--- /dev/null
+++ b/lib/public/Log/IFileBased.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 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\Log;
+
+/**
+ * Interface IFileBased
+ *
+ * @package OCP\Log
+ *
+ * @since 14.0.0
+ */
+interface IFileBased {
+ /**
+ * @since 14.0.0
+ */
+ public function getLogFilePath():string;
+
+ /**
+ * @since 14.0.0
+ */
+ public function getEntries(int $limit=50, int $offset=0): array;
+}
diff --git a/lib/public/Log/ILogFactory.php b/lib/public/Log/ILogFactory.php
new file mode 100644
index 00000000000..6f843d12687
--- /dev/null
+++ b/lib/public/Log/ILogFactory.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ * @author Johannes Ernst <jernst@indiecomputing.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\Log;
+
+use OCP\ILogger;
+
+/**
+ * Interface ILogFactory
+ *
+ * @package OCP\Log
+ * @since 14.0.0
+ */
+interface ILogFactory {
+ /**
+ * @param string $type - one of: file, errorlog, syslog, systemd
+ * @return IWriter
+ * @since 14.0.0
+ */
+ public function get(string $type): IWriter;
+
+ /**
+ * @param string $path
+ * @return ILogger
+ * @since 14.0.0
+ */
+ public function getCustomLogger(string $path): ILogger;
+}
diff --git a/lib/public/Log/IWriter.php b/lib/public/Log/IWriter.php
new file mode 100644
index 00000000000..c9b906bf4a3
--- /dev/null
+++ b/lib/public/Log/IWriter.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 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\Log;
+
+/**
+ * Interface IWriter
+ *
+ * @package OCP\Log
+ * @since 14.0.0
+ */
+interface IWriter {
+ /**
+ * @since 14.0.0
+ */
+ public function write(string $app, $message, int $level);
+}
diff --git a/lib/public/Log/RotationTrait.php b/lib/public/Log/RotationTrait.php
new file mode 100644
index 00000000000..df42bfeff1f
--- /dev/null
+++ b/lib/public/Log/RotationTrait.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 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\Log;
+
+/**
+ * Trait RotationTrait
+ *
+ * @package OCP\Log
+ *
+ * @since 14.0.0
+ */
+trait RotationTrait {
+
+ /**
+ * @var string
+ * @since 14.0.0
+ */
+ protected $filePath;
+
+ /**
+ * @var int
+ * @since 14.0.0
+ */
+ protected $maxSize;
+
+ /**
+ * @return string the resulting new filepath
+ * @since 14.0.0
+ */
+ protected function rotate():string {
+ $rotatedFile = $this->filePath.'.1';
+ rename($this->filePath, $rotatedFile);
+ return $rotatedFile;
+ }
+
+ /**
+ * @return bool
+ * @since 14.0.0
+ */
+ protected function shouldRotateBySize():bool {
+ if ((int)$this->maxSize > 0) {
+ $filesize = @filesize($this->filePath);
+ if ($filesize >= (int)$this->maxSize) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/lib/public/Mail/IAttachment.php b/lib/public/Mail/IAttachment.php
index 4b617d67f5e..71fa841b26c 100644
--- a/lib/public/Mail/IAttachment.php
+++ b/lib/public/Mail/IAttachment.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
*
@@ -33,23 +34,23 @@ interface IAttachment {
/**
* @param string $filename
- * @return $this
+ * @return IAttachment
* @since 13.0.0
*/
- public function setFilename($filename);
+ public function setFilename(string $filename): IAttachment;
/**
* @param string $contentType
- * @return $this
+ * @return IAttachment
* @since 13.0.0
*/
- public function setContentType($contentType);
+ public function setContentType(string $contentType): IAttachment;
/**
* @param string $body
- * @return $this
+ * @return IAttachment
* @since 13.0.0
*/
- public function setBody($body);
+ public function setBody(string $body): IAttachment;
}
diff --git a/lib/public/Mail/IEMailTemplate.php b/lib/public/Mail/IEMailTemplate.php
index 3248665a7da..1c0ddbe54d4 100644
--- a/lib/public/Mail/IEMailTemplate.php
+++ b/lib/public/Mail/IEMailTemplate.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright 2017, Morris Jobke <hey@morrisjobke.de>
*
@@ -62,7 +63,7 @@ interface IEMailTemplate {
*
* @since 13.0.0
*/
- public function setSubject($subject);
+ public function setSubject(string $subject);
/**
* Adds a header to the email
@@ -80,58 +81,58 @@ interface IEMailTemplate {
*
* @since 12.0.0
*/
- public function addHeading($title, $plainTitle = '');
+ public function addHeading(string $title, $plainTitle = '');
/**
* Adds a paragraph to the body of the email
*
- * @param string $text
+ * @param string $text; Note: When $plainText falls back to this, HTML is automatically escaped in the HTML email
* @param string|bool $plainText Text that is used in the plain text email
* if empty the $text is used, if false none will be used
*
* @since 12.0.0
*/
- public function addBodyText($text, $plainText = '');
+ public function addBodyText(string $text, $plainText = '');
/**
* Adds a list item to the body of the email
*
- * @param string $text
- * @param string $metaInfo
+ * @param string $text; Note: When $plainText falls back to this, HTML is automatically escaped in the HTML email
+ * @param string $metaInfo; Note: When $plainMetaInfo falls back to this, HTML is automatically escaped in the HTML email
* @param string $icon Absolute path, must be 16*16 pixels
- * @param string $plainText Text that is used in the plain text email
+ * @param string|bool $plainText Text that is used in the plain text email
* if empty the $text is used, if false none will be used
- * @param string $plainMetaInfo Meta info that is used in the plain text email
+ * @param string|bool $plainMetaInfo Meta info that is used in the plain text email
* if empty the $metaInfo is used, if false none will be used
* @since 12.0.0
*/
- public function addBodyListItem($text, $metaInfo = '', $icon = '', $plainText = '', $plainMetaInfo = '');
+ public function addBodyListItem(string $text, string $metaInfo = '', string $icon = '', $plainText = '', $plainMetaInfo = '');
/**
* Adds a button group of two buttons to the body of the email
*
- * @param string $textLeft Text of left button
+ * @param string $textLeft Text of left button; Note: When $plainTextLeft falls back to this, HTML is automatically escaped in the HTML email
* @param string $urlLeft URL of left button
- * @param string $textRight Text of right button
+ * @param string $textRight Text of right button; Note: When $plainTextRight falls back to this, HTML is automatically escaped in the HTML email
* @param string $urlRight URL of right button
* @param string $plainTextLeft Text of left button that is used in the plain text version - if empty the $textLeft is used
* @param string $plainTextRight Text of right button that is used in the plain text version - if empty the $textRight is used
*
* @since 12.0.0
*/
- public function addBodyButtonGroup($textLeft, $urlLeft, $textRight, $urlRight, $plainTextLeft = '', $plainTextRight = '');
+ public function addBodyButtonGroup(string $textLeft, string $urlLeft, string $textRight, string $urlRight, string $plainTextLeft = '', string $plainTextRight = '');
/**
* Adds a button to the body of the email
*
- * @param string $text Text of button
+ * @param string $text Text of button; Note: When $plainText falls back to this, HTML is automatically escaped in the HTML email
* @param string $url URL of button
* @param string $plainText Text of button in plain text version
* if empty the $text is used, if false none will be used
*
* @since 12.0.0
*/
- public function addBodyButton($text, $url, $plainText = '');
+ public function addBodyButton(string $text, string $url, $plainText = '');
/**
* Adds a logo and a text to the footer. <br> in the text will be replaced by new lines in the plain text email
@@ -140,7 +141,7 @@ interface IEMailTemplate {
*
* @since 12.0.0
*/
- public function addFooter($text = '');
+ public function addFooter(string $text = '');
/**
* Returns the rendered email subject as string
@@ -149,7 +150,7 @@ interface IEMailTemplate {
*
* @since 13.0.0
*/
- public function renderSubject();
+ public function renderSubject(): string;
/**
* Returns the rendered HTML email as string
@@ -158,7 +159,7 @@ interface IEMailTemplate {
*
* @since 12.0.0
*/
- public function renderHtml();
+ public function renderHtml(): string;
/**
* Returns the rendered plain text email as string
@@ -167,5 +168,5 @@ interface IEMailTemplate {
*
* @since 12.0.0
*/
- public function renderText();
+ public function renderText(): string;
}
diff --git a/lib/public/Mail/IMailer.php b/lib/public/Mail/IMailer.php
index 10096548256..e8f5d6e7d03 100644
--- a/lib/public/Mail/IMailer.php
+++ b/lib/public/Mail/IMailer.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -51,7 +52,7 @@ interface IMailer {
* @return IMessage
* @since 8.1.0
*/
- public function createMessage();
+ public function createMessage(): IMessage;
/**
* @param string|null $data
@@ -60,7 +61,7 @@ interface IMailer {
* @return IAttachment
* @since 13.0.0
*/
- public function createAttachment($data = null, $filename = null, $contentType = null);
+ public function createAttachment($data = null, $filename = null, $contentType = null): IAttachment;
/**
* @param string $path
@@ -68,7 +69,7 @@ interface IMailer {
* @return IAttachment
* @since 13.0.0
*/
- public function createAttachmentFromPath($path, $contentType = null);
+ public function createAttachmentFromPath(string $path, $contentType = null): IAttachment;
/**
* Creates a new email template object
@@ -78,7 +79,7 @@ interface IMailer {
* @return IEMailTemplate
* @since 12.0.0 Parameters added in 12.0.3
*/
- public function createEMailTemplate($emailId, array $data = []);
+ public function createEMailTemplate(string $emailId, array $data = []): IEMailTemplate;
/**
* Send the specified message. Also sets the from address to the value defined in config.php
@@ -91,7 +92,7 @@ interface IMailer {
* has been supplied.)
* @since 8.1.0
*/
- public function send(IMessage $message);
+ public function send(IMessage $message): array;
/**
* Checks if an e-mail address is valid
@@ -100,5 +101,5 @@ interface IMailer {
* @return bool True if the mail address is valid, false otherwise
* @since 8.1.0
*/
- public function validateMailAddress($email);
+ public function validateMailAddress(string $email): bool;
}
diff --git a/lib/public/Mail/IMessage.php b/lib/public/Mail/IMessage.php
index cec47adc19d..638fd9d103f 100644
--- a/lib/public/Mail/IMessage.php
+++ b/lib/public/Mail/IMessage.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
*
@@ -33,10 +34,10 @@ interface IMessage {
/**
* @param IAttachment $attachment
- * @return $this
+ * @return IMessage
* @since 13.0.0
*/
- public function attach(IAttachment $attachment);
+ public function attach(IAttachment $attachment): IMessage;
/**
* Set the from address of this message.
@@ -44,51 +45,51 @@ interface IMessage {
* If no "From" address is used \OC\Mail\Mailer will use mail_from_address and mail_domain from config.php
*
* @param array $addresses Example: array('sender@domain.org', 'other@domain.org' => 'A name')
- * @return $this
+ * @return IMessage
* @since 13.0.0
*/
- public function setFrom(array $addresses);
+ public function setFrom(array $addresses): IMessage;
/**
* Set the Reply-To address of this message
*
* @param array $addresses
- * @return $this
+ * @return IMessage
* @since 13.0.0
*/
- public function setReplyTo(array $addresses);
+ public function setReplyTo(array $addresses): IMessage;
/**
* Set the to addresses of this message.
*
* @param array $recipients Example: array('recipient@domain.org', 'other@domain.org' => 'A name')
- * @return $this
+ * @return IMessage
* @since 13.0.0
*/
- public function setTo(array $recipients);
+ public function setTo(array $recipients): IMessage;
/**
* Set the CC recipients of this message.
*
* @param array $recipients Example: array('recipient@domain.org', 'other@domain.org' => 'A name')
- * @return $this
+ * @return IMessage
* @since 13.0.0
*/
- public function setCc(array $recipients);
+ public function setCc(array $recipients): IMessage;
/**
* Set the BCC recipients of this message.
*
* @param array $recipients Example: array('recipient@domain.org', 'other@domain.org' => 'A name')
- * @return $this
+ * @return IMessage
* @since 13.0.0
*/
- public function setBcc(array $recipients);
+ public function setBcc(array $recipients): IMessage;
/**
* @param IEMailTemplate $emailTemplate
- * @return $this
+ * @return IMessage
* @since 13.0.0
*/
- public function useTemplate(IEMailTemplate $emailTemplate);
+ public function useTemplate(IEMailTemplate $emailTemplate): IMessage;
}
diff --git a/lib/public/Migration/IMigrationStep.php b/lib/public/Migration/IMigrationStep.php
index e12d962683e..6b9da280d78 100644
--- a/lib/public/Migration/IMigrationStep.php
+++ b/lib/public/Migration/IMigrationStep.php
@@ -29,6 +29,21 @@ use OCP\DB\ISchemaWrapper;
* @since 13.0.0
*/
interface IMigrationStep {
+ /**
+ * Human readable name of the migration step
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function name(): string;
+
+ /**
+ * Human readable description of the migration steps
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function description(): string;
/**
* @param IOutput $output
diff --git a/lib/public/Migration/SimpleMigrationStep.php b/lib/public/Migration/SimpleMigrationStep.php
index da46c687644..c776b8b89da 100644
--- a/lib/public/Migration/SimpleMigrationStep.php
+++ b/lib/public/Migration/SimpleMigrationStep.php
@@ -29,6 +29,25 @@ use OCP\DB\ISchemaWrapper;
* @since 13.0.0
*/
abstract class SimpleMigrationStep implements IMigrationStep {
+ /**
+ * Human readable name of the migration step
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function name(): string {
+ return '';
+ }
+
+ /**
+ * Human readable description of the migration step
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function description(): string {
+ return '';
+ }
/**
* @param IOutput $output
diff --git a/lib/public/OCS/IDiscoveryService.php b/lib/public/OCS/IDiscoveryService.php
index 9a86e2a4410..ad1499e75fd 100644
--- a/lib/public/OCS/IDiscoveryService.php
+++ b/lib/public/OCS/IDiscoveryService.php
@@ -44,8 +44,9 @@ interface IDiscoveryService {
*
* @param string $remote
* @param string $service the service you want to discover
+ * @param bool $skipCache We won't check if the data is in the cache. This is useful if a background job is updating the status - Added in 14.0.0
* @return array
*/
- public function discover(string $remote, string $service): array;
+ public function discover(string $remote, string $service, bool $skipCache = false): array;
}
diff --git a/lib/public/Response.php b/lib/public/Response.php
deleted file mode 100644
index dd029e12dbf..00000000000
--- a/lib/public/Response.php
+++ /dev/null
@@ -1,137 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Andreas Fischer <bantu@owncloud.com>
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Frank Karlitschek <frank@karlitschek.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Stefan Weil <sw@weilnetz.de>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-
-/**
- * Public interface of ownCloud for apps to use.
- * Response Class.
- *
- */
-
-// use OCP namespace for all classes that are considered public.
-// This means that they should be used by apps instead of the internal ownCloud classes
-namespace OCP;
-
-/**
- * This class provides convenient functions to send the correct http response headers
- * @since 4.0.0
- * @deprecated 8.1.0 - Use AppFramework controllers instead and modify the response object
- */
-class Response {
- /**
- * Enable response caching by sending correct HTTP headers
- * @param int $cache_time time to cache the response
- * >0 cache time in seconds
- * 0 and <0 enable default browser caching
- * null cache indefinitely
- * @since 4.0.0
- */
- static public function enableCaching( $cache_time = null ) {
- \OC_Response::enableCaching( $cache_time );
- }
-
- /**
- * Checks and set Last-Modified header, when the request matches sends a
- * 'not modified' response
- * @param string $lastModified time when the response was last modified
- * @since 4.0.0
- */
- static public function setLastModifiedHeader( $lastModified ) {
- \OC_Response::setLastModifiedHeader( $lastModified );
- }
-
- /**
- * Sets the content disposition header (with possible workarounds)
- * @param string $filename file name
- * @param string $type disposition type, either 'attachment' or 'inline'
- * @since 7.0.0
- */
- static public function setContentDispositionHeader( $filename, $type = 'attachment' ) {
- \OC_Response::setContentDispositionHeader( $filename, $type );
- }
-
- /**
- * Sets the content length header (with possible workarounds)
- * @param string|int|float $length Length to be sent
- * @since 8.1.0
- */
- static public function setContentLengthHeader($length) {
- \OC_Response::setContentLengthHeader($length);
- }
-
- /**
- * Disable browser caching
- * @see enableCaching with cache_time = 0
- * @since 4.0.0
- */
- static public function disableCaching() {
- \OC_Response::disableCaching();
- }
-
- /**
- * Checks and set ETag header, when the request matches sends a
- * 'not modified' response
- * @param string $etag token to use for modification check
- * @since 4.0.0
- */
- static public function setETagHeader( $etag ) {
- \OC_Response::setETagHeader( $etag );
- }
-
- /**
- * Send file as response, checking and setting caching headers
- * @param string $filepath of file to send
- * @since 4.0.0
- * @deprecated 8.1.0 - Use \OCP\AppFramework\Http\StreamResponse or another AppFramework controller instead
- * @suppress PhanDeprecatedFunction
- */
- static public function sendFile( $filepath ) {
- \OC_Response::sendFile( $filepath );
- }
-
- /**
- * Set response expire time
- * @param string|\DateTime $expires date-time when the response expires
- * string for DateInterval from now
- * DateTime object when to expire response
- * @since 4.0.0
- */
- static public function setExpiresHeader( $expires ) {
- \OC_Response::setExpiresHeader( $expires );
- }
-
- /**
- * Send redirect response
- * @param string $location to redirect to
- * @since 4.0.0
- */
- static public function redirect( $location ) {
- \OC_Response::redirect( $location );
- }
-}
diff --git a/lib/public/Share.php b/lib/public/Share.php
index b7fb7296e49..011d56ab5af 100644
--- a/lib/public/Share.php
+++ b/lib/public/Share.php
@@ -85,16 +85,6 @@ class Share extends \OC\Share\Constants {
return \OC\Share\Share::getShareByToken($token, $checkPasswordProtection);
}
- /**
- * resolves reshares down to the last real share
- * @param array $linkItem
- * @return array file owner
- * @since 6.0.0
- */
- public static function resolveReShare($linkItem) {
- return \OC\Share\Share::resolveReShare($linkItem);
- }
-
/**
* Get the shared items of item type owned by the current user
diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php
index 493db5e5149..302be523327 100644
--- a/lib/public/Share/IManager.php
+++ b/lib/public/Share/IManager.php
@@ -29,6 +29,7 @@ namespace OCP\Share;
use OCP\Files\Folder;
use OCP\Files\Node;
+use OCP\Share\Exceptions\GenericShareException;
use OCP\Share\Exceptions\ShareNotFound;
/**
@@ -84,6 +85,20 @@ interface IManager {
public function deleteFromSelf(IShare $share, $recipientId);
/**
+ * Restore the share when it has been deleted
+ * Certain share types can be restored when they have been deleted
+ * but the provider should properly handle this\
+ *
+ * @param IShare $share The share to restore
+ * @param string $recipientId The user to restore the share for
+ * @return IShare The restored share object
+ * @throws GenericShareException In case restoring the share failed
+ *
+ * @since 14.0.0
+ */
+ public function restoreShare(IShare $share, string $recipientId): IShare;
+
+ /**
* Move the share as a recipient of the share.
* This is updating the share target. So where the recipient has the share mounted.
*
@@ -135,6 +150,20 @@ interface IManager {
public function getSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0);
/**
+ * Get deleted shares shared with $user.
+ * Filter by $node if provided
+ *
+ * @param string $userId
+ * @param int $shareType
+ * @param Node|null $node
+ * @param int $limit The maximum number of shares returned, -1 for all
+ * @param int $offset
+ * @return IShare[]
+ * @since 14.0.0
+ */
+ public function getDeletedSharedWith($userId, $shareType, $node = null, $limit = 50, $offset = 0);
+
+ /**
* Retrieve a share by the share id.
* If the recipient is set make sure to retrieve the file for that user.
* This makes sure that if a user has moved/deleted a group share this
@@ -341,6 +370,14 @@ interface IManager {
public function outgoingServer2ServerSharesAllowed();
/**
+ * Check if outgoing server2server shares are allowed
+ * @return bool
+ * @since 14.0.0
+ */
+ public function outgoingServer2ServerGroupSharesAllowed();
+
+
+ /**
* Check if a given share provider exists
* @param int $shareType
* @return bool
diff --git a/lib/public/Share/IShare.php b/lib/public/Share/IShare.php
index c19364c86c8..870794d6536 100644
--- a/lib/public/Share/IShare.php
+++ b/lib/public/Share/IShare.php
@@ -170,6 +170,40 @@ interface IShare {
public function getSharedWith();
/**
+ * Set the display name of the receiver of this share.
+ *
+ * @param string $displayName
+ * @return \OCP\Share\IShare The modified object
+ * @since 14.0.0
+ */
+ public function setSharedWithDisplayName($displayName);
+
+ /**
+ * Get the display name of the receiver of this share.
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function getSharedWithDisplayName();
+
+ /**
+ * Set the avatar of the receiver of this share.
+ *
+ * @param string $src
+ * @return \OCP\Share\IShare The modified object
+ * @since 14.0.0
+ */
+ public function setSharedWithAvatar($src);
+
+ /**
+ * Get the avatar of the receiver of this share.
+ *
+ * @return string
+ * @since 14.0.0
+ */
+ public function getSharedWithAvatar();
+
+ /**
* Set the permissions.
* See \OCP\Constants::PERMISSION_*
*
diff --git a/lib/public/Share/IShareProvider.php b/lib/public/Share/IShareProvider.php
index 4db43d953cf..6731bf8882b 100644
--- a/lib/public/Share/IShareProvider.php
+++ b/lib/public/Share/IShareProvider.php
@@ -25,6 +25,7 @@
namespace OCP\Share;
use OCP\Files\Folder;
+use OCP\Share\Exceptions\GenericShareException;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Files\Node;
@@ -46,7 +47,7 @@ interface IShareProvider {
/**
* Create a share
- *
+ *
* @param \OCP\Share\IShare $share
* @return \OCP\Share\IShare The share object
* @since 9.0.0
@@ -82,6 +83,18 @@ interface IShareProvider {
public function deleteFromSelf(\OCP\Share\IShare $share, $recipient);
/**
+ * Restore a share for a given recipient. The implementation could be provider independant.
+ *
+ * @param IShare $share
+ * @param string $recipient
+ * @return IShare The restored share object
+ *
+ * @since 14.0.0
+ * @throws GenericShareException In case the share could not be restored
+ */
+ public function restore(IShare $share, string $recipient): IShare;
+
+ /**
* Move a share as a recipient.
* This is updating the share target. Thus the mount point of the recipient.
* This may require special handling. If a user moves a group share
diff --git a/lib/public/SystemTag/ISystemTag.php b/lib/public/SystemTag/ISystemTag.php
index 539c7835fae..da434e8b5a0 100644
--- a/lib/public/SystemTag/ISystemTag.php
+++ b/lib/public/SystemTag/ISystemTag.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -36,7 +37,7 @@ interface ISystemTag {
*
* @since 9.0.0
*/
- public function getId();
+ public function getId(): string;
/**
* Returns the tag display name
@@ -45,7 +46,7 @@ interface ISystemTag {
*
* @since 9.0.0
*/
- public function getName();
+ public function getName(): string;
/**
* Returns whether the tag is visible for regular users
@@ -54,7 +55,7 @@ interface ISystemTag {
*
* @since 9.0.0
*/
- public function isUserVisible();
+ public function isUserVisible(): bool;
/**
* Returns whether the tag can be assigned to objects by regular users
@@ -63,7 +64,7 @@ interface ISystemTag {
*
* @since 9.0.0
*/
- public function isUserAssignable();
+ public function isUserAssignable(): bool;
}
diff --git a/lib/public/SystemTag/ISystemTagManager.php b/lib/public/SystemTag/ISystemTagManager.php
index fff0a439116..4cce106790a 100644
--- a/lib/public/SystemTag/ISystemTagManager.php
+++ b/lib/public/SystemTag/ISystemTagManager.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -37,15 +38,15 @@ interface ISystemTagManager {
*
* @param array|string $tagIds id or array of unique ids of the tag to retrieve
*
- * @return \OCP\SystemTag\ISystemTag[] array of system tags with tag id as key
+ * @return ISystemTag[] array of system tags with tag id as key
*
* @throws \InvalidArgumentException if at least one given tag ids is invalid (string instead of integer, etc.)
- * @throws \OCP\SystemTag\TagNotFoundException if at least one given tag ids did no exist
+ * @throws TagNotFoundException if at least one given tag ids did no exist
* The message contains a json_encoded array of the ids that could not be found
*
* @since 9.0.0
*/
- public function getTagsByIds($tagIds);
+ public function getTagsByIds($tagIds): array;
/**
* Returns the tag object matching the given attributes.
@@ -54,13 +55,13 @@ interface ISystemTagManager {
* @param bool $userVisible whether the tag is visible by users
* @param bool $userAssignable whether the tag is assignable by users
*
- * @return \OCP\SystemTag\ISystemTag system tag
+ * @return ISystemTag system tag
*
- * @throws \OCP\SystemTag\TagNotFoundException if tag does not exist
+ * @throws TagNotFoundException if tag does not exist
*
* @since 9.0.0
*/
- public function getTag($tagName, $userVisible, $userAssignable);
+ public function getTag(string $tagName, bool $userVisible, bool $userAssignable): ISystemTag;
/**
* Creates the tag object using the given attributes.
@@ -69,13 +70,13 @@ interface ISystemTagManager {
* @param bool $userVisible whether the tag is visible by users
* @param bool $userAssignable whether the tag is assignable by users
*
- * @return \OCP\SystemTag\ISystemTag system tag
+ * @return ISystemTag system tag
*
- * @throws \OCP\SystemTag\TagAlreadyExistsException if tag already exists
+ * @throws TagAlreadyExistsException if tag already exists
*
* @since 9.0.0
*/
- public function createTag($tagName, $userVisible, $userAssignable);
+ public function createTag(string $tagName, bool $userVisible, bool $userAssignable): ISystemTag;
/**
* Returns all known tags, optionally filtered by visibility.
@@ -83,11 +84,11 @@ interface ISystemTagManager {
* @param bool|null $visibilityFilter filter by visibility if non-null
* @param string $nameSearchPattern optional search pattern for the tag name
*
- * @return \OCP\SystemTag\ISystemTag[] array of system tags or empty array if none found
+ * @return ISystemTag[] array of system tags or empty array if none found
*
* @since 9.0.0
*/
- public function getAllTags($visibilityFilter = null, $nameSearchPattern = null);
+ public function getAllTags($visibilityFilter = null, $nameSearchPattern = null): array;
/**
* Updates the given tag
@@ -97,20 +98,20 @@ interface ISystemTagManager {
* @param bool $userVisible whether the tag is visible by users
* @param bool $userAssignable whether the tag is assignable by users
*
- * @throws \OCP\SystemTag\TagNotFoundException if tag with the given id does not exist
- * @throws \OCP\SystemTag\TagAlreadyExistsException if there is already another tag
+ * @throws TagNotFoundException if tag with the given id does not exist
+ * @throws TagAlreadyExistsException if there is already another tag
* with the same attributes
*
* @since 9.0.0
*/
- public function updateTag($tagId, $newName, $userVisible, $userAssignable);
+ public function updateTag(string $tagId, string $newName, bool $userVisible, bool $userAssignable);
/**
* Delete the given tags from the database and all their relationships.
*
* @param string|array $tagIds array of tag ids
*
- * @throws \OCP\SystemTag\TagNotFoundException if at least one tag did not exist
+ * @throws TagNotFoundException if at least one tag did not exist
*
* @since 9.0.0
*/
@@ -127,7 +128,7 @@ interface ISystemTagManager {
*
* @since 9.1.0
*/
- public function canUserAssignTag(ISystemTag $tag, IUser $user);
+ public function canUserAssignTag(ISystemTag $tag, IUser $user): bool;
/**
* Checks whether the given user is allowed to see the tag with the given id.
@@ -139,7 +140,7 @@ interface ISystemTagManager {
*
* @since 9.1.0
*/
- public function canUserSeeTag(ISystemTag $tag, IUser $userId);
+ public function canUserSeeTag(ISystemTag $tag, IUser $user): bool;
/**
* Set groups that can assign a given tag.
@@ -149,7 +150,7 @@ interface ISystemTagManager {
*
* @since 9.1.0
*/
- public function setTagGroups(ISystemTag $tag, $groupIds);
+ public function setTagGroups(ISystemTag $tag, array $groupIds);
/**
* Get groups that can assign a given tag.
@@ -160,5 +161,5 @@ interface ISystemTagManager {
*
* @since 9.1.0
*/
- public function getTagGroups(ISystemTag $tag);
+ public function getTagGroups(ISystemTag $tag): array;
}
diff --git a/lib/public/SystemTag/ISystemTagManagerFactory.php b/lib/public/SystemTag/ISystemTagManagerFactory.php
index 0d652697490..25956b41df4 100644
--- a/lib/public/SystemTag/ISystemTagManagerFactory.php
+++ b/lib/public/SystemTag/ISystemTagManagerFactory.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -47,7 +48,7 @@ interface ISystemTagManagerFactory {
* @return ISystemTagManager
* @since 9.0.0
*/
- public function getManager();
+ public function getManager(): ISystemTagManager;
/**
* creates and returns an instance of the system tag object
@@ -56,5 +57,5 @@ interface ISystemTagManagerFactory {
* @return ISystemTagObjectMapper
* @since 9.0.0
*/
- public function getObjectMapper();
+ public function getObjectMapper(): ISystemTagObjectMapper;
}
diff --git a/lib/public/SystemTag/ISystemTagObjectMapper.php b/lib/public/SystemTag/ISystemTagObjectMapper.php
index 3e28ab15773..1705bde23c5 100644
--- a/lib/public/SystemTag/ISystemTagObjectMapper.php
+++ b/lib/public/SystemTag/ISystemTagObjectMapper.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -51,7 +52,7 @@ interface ISystemTagObjectMapper {
*
* @since 9.0.0
*/
- public function getTagIdsForObjects($objIds, $objectType);
+ public function getTagIdsForObjects($objIds, string $objectType): array;
/**
* Get a list of objects tagged with $tagIds.
@@ -63,14 +64,14 @@ interface ISystemTagObjectMapper {
*
* @return string[] array of object ids or empty array if none found
*
- * @throws \OCP\SystemTag\TagNotFoundException if at least one of the
+ * @throws TagNotFoundException if at least one of the
* given tags does not exist
* @throws \InvalidArgumentException When a limit is specified together with
* multiple tag ids
*
* @since 9.0.0
*/
- public function getObjectIdsForTags($tagIds, $objectType, $limit = 0, $offset = '');
+ public function getObjectIdsForTags($tagIds, string $objectType, int $limit = 0, string $offset = ''): array;
/**
* Assign the given tags to the given object.
@@ -84,12 +85,12 @@ interface ISystemTagObjectMapper {
* @param string $objectType object type
* @param string|array $tagIds tag id or array of tag ids to assign
*
- * @throws \OCP\SystemTag\TagNotFoundException if at least one of the
+ * @throws TagNotFoundException if at least one of the
* given tags does not exist
*
* @since 9.0.0
*/
- public function assignTags($objId, $objectType, $tagIds);
+ public function assignTags(string $objId, string $objectType, $tagIds);
/**
* Unassign the given tags from the given object.
@@ -103,12 +104,12 @@ interface ISystemTagObjectMapper {
* @param string $objectType object type
* @param string|array $tagIds tag id or array of tag ids to unassign
*
- * @throws \OCP\SystemTag\TagNotFoundException if at least one of the
+ * @throws TagNotFoundException if at least one of the
* given tags does not exist
*
* @since 9.0.0
*/
- public function unassignTags($objId, $objectType, $tagIds);
+ public function unassignTags(string $objId, string $objectType, $tagIds);
/**
* Checks whether the given objects have the given tag.
@@ -122,10 +123,10 @@ interface ISystemTagObjectMapper {
* @return bool true if the condition set by $all is matched, false
* otherwise
*
- * @throws \OCP\SystemTag\TagNotFoundException if the tag does not exist
+ * @throws TagNotFoundException if the tag does not exist
*
* @since 9.0.0
*/
- public function haveTag($objIds, $objectType, $tagId, $all = true);
+ public function haveTag($objIds, string $objectType, string $tagId, bool $all = true): bool;
}
diff --git a/lib/public/SystemTag/ManagerEvent.php b/lib/public/SystemTag/ManagerEvent.php
index bb9fcc01f83..452c0d5da8f 100644
--- a/lib/public/SystemTag/ManagerEvent.php
+++ b/lib/public/SystemTag/ManagerEvent.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -52,7 +53,7 @@ class ManagerEvent extends Event {
* @param ISystemTag|null $beforeTag
* @since 9.0.0
*/
- public function __construct($event, ISystemTag $tag, ISystemTag $beforeTag = null) {
+ public function __construct(string $event, ISystemTag $tag, ISystemTag $beforeTag = null) {
$this->event = $event;
$this->tag = $tag;
$this->beforeTag = $beforeTag;
@@ -62,7 +63,7 @@ class ManagerEvent extends Event {
* @return string
* @since 9.0.0
*/
- public function getEvent() {
+ public function getEvent(): string {
return $this->event;
}
@@ -70,15 +71,16 @@ class ManagerEvent extends Event {
* @return ISystemTag
* @since 9.0.0
*/
- public function getTag() {
+ public function getTag(): ISystemTag {
return $this->tag;
}
/**
* @return ISystemTag
* @since 9.0.0
+ * @throws \BadMethodCallException
*/
- public function getTagBefore() {
+ public function getTagBefore(): ISystemTag {
if ($this->event !== self::EVENT_UPDATE) {
throw new \BadMethodCallException('getTagBefore is only available on the update Event');
}
diff --git a/lib/public/SystemTag/MapperEvent.php b/lib/public/SystemTag/MapperEvent.php
index a86497c8440..d98caf1317b 100644
--- a/lib/public/SystemTag/MapperEvent.php
+++ b/lib/public/SystemTag/MapperEvent.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -53,7 +54,7 @@ class MapperEvent extends Event {
* @param int[] $tags
* @since 9.0.0
*/
- public function __construct($event, $objectType, $objectId, array $tags) {
+ public function __construct(string $event, string $objectType, string $objectId, array $tags) {
$this->event = $event;
$this->objectType = $objectType;
$this->objectId = $objectId;
@@ -64,7 +65,7 @@ class MapperEvent extends Event {
* @return string
* @since 9.0.0
*/
- public function getEvent() {
+ public function getEvent(): string {
return $this->event;
}
@@ -72,7 +73,7 @@ class MapperEvent extends Event {
* @return string
* @since 9.0.0
*/
- public function getObjectType() {
+ public function getObjectType(): string {
return $this->objectType;
}
@@ -80,7 +81,7 @@ class MapperEvent extends Event {
* @return string
* @since 9.0.0
*/
- public function getObjectId() {
+ public function getObjectId(): string {
return $this->objectId;
}
@@ -88,7 +89,7 @@ class MapperEvent extends Event {
* @return int[]
* @since 9.0.0
*/
- public function getTags() {
+ public function getTags(): array {
return $this->tags;
}
}
diff --git a/lib/public/SystemTag/SystemTagsEntityEvent.php b/lib/public/SystemTag/SystemTagsEntityEvent.php
index 15ae4439986..e439c16d9c6 100644
--- a/lib/public/SystemTag/SystemTagsEntityEvent.php
+++ b/lib/public/SystemTag/SystemTagsEntityEvent.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -45,7 +46,7 @@ class SystemTagsEntityEvent extends Event {
* @param string $event
* @since 9.1.0
*/
- public function __construct($event) {
+ public function __construct(string $event) {
$this->event = $event;
$this->collections = [];
}
@@ -59,7 +60,7 @@ class SystemTagsEntityEvent extends Event {
* @throws \OutOfBoundsException when the entity name is already taken
* @since 9.1.0
*/
- public function addEntityCollection($name, \Closure $entityExistsFunction) {
+ public function addEntityCollection(string $name, \Closure $entityExistsFunction) {
if (isset($this->collections[$name])) {
throw new \OutOfBoundsException('Duplicate entity name "' . $name . '"');
}
@@ -71,7 +72,7 @@ class SystemTagsEntityEvent extends Event {
* @return \Closure[]
* @since 9.1.0
*/
- public function getEntityCollections() {
+ public function getEntityCollections(): array {
return $this->collections;
}
}
diff --git a/lib/public/SystemTag/TagAlreadyExistsException.php b/lib/public/SystemTag/TagAlreadyExistsException.php
index caf0d9f08bc..fbe8234d281 100644
--- a/lib/public/SystemTag/TagAlreadyExistsException.php
+++ b/lib/public/SystemTag/TagAlreadyExistsException.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
diff --git a/lib/public/SystemTag/TagNotFoundException.php b/lib/public/SystemTag/TagNotFoundException.php
index 9b06259807f..9f83c20e6c5 100644
--- a/lib/public/SystemTag/TagNotFoundException.php
+++ b/lib/public/SystemTag/TagNotFoundException.php
@@ -1,4 +1,5 @@
<?php
+declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
@@ -43,7 +44,7 @@ class TagNotFoundException extends \RuntimeException {
* @param string[] $tags
* @since 9.0.0
*/
- public function __construct($message = '', $code = 0, \Exception $previous = null, array $tags = []) {
+ public function __construct(string $message = '', int $code = 0, \Exception $previous = null, array $tags = []) {
parent::__construct($message, $code, $previous);
$this->tags = $tags;
}
@@ -52,7 +53,7 @@ class TagNotFoundException extends \RuntimeException {
* @return string[]
* @since 9.0.0
*/
- public function getMissingTags() {
+ public function getMissingTags(): array {
return $this->tags;
}
}
diff --git a/lib/public/User.php b/lib/public/User.php
index 2fdf540b958..a669a3a06fc 100644
--- a/lib/public/User.php
+++ b/lib/public/User.php
@@ -58,45 +58,6 @@ class User {
}
/**
- * Get a list of all users
- * @param string $search search pattern
- * @param int|null $limit
- * @param int|null $offset
- * @return array an array of all uids
- * @deprecated 8.1.0 use method search() of \OCP\IUserManager - \OC::$server->getUserManager()
- * @since 5.0.0
- */
- public static function getUsers( $search = '', $limit = null, $offset = null ) {
- return \OC_User::getUsers( $search, $limit, $offset );
- }
-
- /**
- * Get the user display name of the user currently logged in.
- * @param string|null $user user id or null for current user
- * @return string display name
- * @deprecated 8.1.0 fetch \OCP\IUser (has getDisplayName()) by using method
- * get() of \OCP\IUserManager - \OC::$server->getUserManager()
- * @since 5.0.0
- */
- public static function getDisplayName( $user = null ) {
- return \OC_User::getDisplayName( $user );
- }
-
- /**
- * Get a list of all display names and user ids.
- * @param string $search search pattern
- * @param int|null $limit
- * @param int|null $offset
- * @return array an array of all display names (value) and the correspondig uids (key)
- * @deprecated 8.1.0 use method searchDisplayName() of \OCP\IUserManager - \OC::$server->getUserManager()
- * @since 5.0.0
- * @suppress PhanDeprecatedFunction
- */
- public static function getDisplayNames( $search = '', $limit = null, $offset = null ) {
- return \OC_User::getDisplayNames( $search, $limit, $offset );
- }
-
- /**
* Check if the user is logged in
* @return boolean
* @since 5.0.0
@@ -107,18 +68,6 @@ class User {
}
/**
- * Check if a user exists
- * @param string $uid the username
- * @param string $excludingBackend (default none)
- * @return boolean
- * @deprecated 8.1.0 use method userExists() of \OCP\IUserManager - \OC::$server->getUserManager()
- * @since 5.0.0
- */
- public static function userExists($uid, $excludingBackend = null) {
- return \OC::$server->getUserManager()->userExists($uid);
- }
-
- /**
* Check if the user is a admin, redirects to home if not
* @since 5.0.0
* @deprecated 13.0.0 Use annotation based ACLs from the AppFramework instead
diff --git a/lib/public/User/Backend/ABackend.php b/lib/public/User/Backend/ABackend.php
new file mode 100644
index 00000000000..a110ba5202a
--- /dev/null
+++ b/lib/public/User/Backend/ABackend.php
@@ -0,0 +1,72 @@
+<?php
+declare(strict_types=1);
+/**
+* @copyright Copyright (c) 2018 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 OCP\User\Backend;
+
+use OC\User\Backend;
+use OCP\IUserBackend;
+use OCP\UserInterface;
+
+/**
+ * @since 14.0.0
+ */
+abstract class ABackend implements IUserBackend, UserInterface {
+
+ /**
+ * @deprecated 14.0.0
+ *
+ * @param int $actions The action to check for
+ * @return bool
+ */
+ public function implementsActions($actions): bool {
+ $implements = 0;
+
+ if ($this instanceof ICreateUserBackend) {
+ $implements |= Backend::CREATE_USER;
+ }
+ if ($this instanceof ISetPasswordBackend) {
+ $implements |= Backend::SET_PASSWORD;
+ }
+ if ($this instanceof ICheckPasswordBackend) {
+ $implements |= Backend::CHECK_PASSWORD;
+ }
+ if ($this instanceof IGetHomeBackend) {
+ $implements |= Backend::GET_HOME;
+ }
+ if ($this instanceof IGetDisplayNameBackend) {
+ $implements |= Backend::GET_DISPLAYNAME;
+ }
+ if ($this instanceof ISetDisplayNameBackend) {
+ $implements |= Backend::SET_DISPLAYNAME;
+ }
+ if ($this instanceof IProvideAvatarBackend) {
+ $implements |= Backend::PROVIDE_AVATAR;
+ }
+ if ($this instanceof ICountUsersBackend) {
+ $implements |= Backend::COUNT_USERS;
+ }
+
+ return (bool)($actions & $implements);
+ }
+}
diff --git a/lib/public/User/Backend/ICheckPasswordBackend.php b/lib/public/User/Backend/ICheckPasswordBackend.php
new file mode 100644
index 00000000000..b28c94f1a6c
--- /dev/null
+++ b/lib/public/User/Backend/ICheckPasswordBackend.php
@@ -0,0 +1,39 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\User\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface ICheckPasswordBackend {
+ /**
+ * @since 14.0.0
+ *
+ * @param string $uid The username
+ * @param string $password The password
+ * @return string|bool The uid on success false on failure
+ */
+ public function checkPassword(string $loginName, string $password);
+}
diff --git a/lib/public/User/Backend/ICountUsersBackend.php b/lib/public/User/Backend/ICountUsersBackend.php
new file mode 100644
index 00000000000..1cb46712aa0
--- /dev/null
+++ b/lib/public/User/Backend/ICountUsersBackend.php
@@ -0,0 +1,38 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\User\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface ICountUsersBackend {
+
+ /**
+ * @since 14.0.0
+ *
+ * @return int|bool The number of users on success false on failure
+ */
+ public function countUsers();
+}
diff --git a/lib/public/User/Backend/ICreateUserBackend.php b/lib/public/User/Backend/ICreateUserBackend.php
new file mode 100644
index 00000000000..09a20e12453
--- /dev/null
+++ b/lib/public/User/Backend/ICreateUserBackend.php
@@ -0,0 +1,40 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\User\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface ICreateUserBackend {
+
+ /**
+ * @since 14.0.0
+ *
+ * @param string $uid The username of the user to create
+ * @param string $password The password of the new user
+ * @return bool
+ */
+ public function createUser(string $uid, string $password): bool;
+}
diff --git a/lib/public/User/Backend/IGetDisplayNameBackend.php b/lib/public/User/Backend/IGetDisplayNameBackend.php
new file mode 100644
index 00000000000..6382ddd6eb6
--- /dev/null
+++ b/lib/public/User/Backend/IGetDisplayNameBackend.php
@@ -0,0 +1,39 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\User\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface IGetDisplayNameBackend {
+
+ /**
+ * @since 14.0.0
+ *
+ * @param string $uid user ID of the user
+ * @return string display name
+ */
+ public function getDisplayName($uid): string;
+}
diff --git a/lib/public/User/Backend/IGetHomeBackend.php b/lib/public/User/Backend/IGetHomeBackend.php
new file mode 100644
index 00000000000..20fcd004bba
--- /dev/null
+++ b/lib/public/User/Backend/IGetHomeBackend.php
@@ -0,0 +1,39 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\User\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface IGetHomeBackend {
+
+ /**
+ * @since 14.0.0
+ *
+ * @param string $uid the username
+ * @return string|bool Datadir on success false on failure
+ */
+ public function getHome(string $uid);
+}
diff --git a/lib/public/User/Backend/IProvideAvatarBackend.php b/lib/public/User/Backend/IProvideAvatarBackend.php
new file mode 100644
index 00000000000..328c7450b40
--- /dev/null
+++ b/lib/public/User/Backend/IProvideAvatarBackend.php
@@ -0,0 +1,39 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\User\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface IProvideAvatarBackend {
+
+ /**
+ * @since 14.0.0
+ *
+ * @param string $uid
+ * @return bool
+ */
+ public function canChangeAvatar(string $uid): bool;
+}
diff --git a/lib/public/User/Backend/ISetDisplayNameBackend.php b/lib/public/User/Backend/ISetDisplayNameBackend.php
new file mode 100644
index 00000000000..ac41cd3e2c3
--- /dev/null
+++ b/lib/public/User/Backend/ISetDisplayNameBackend.php
@@ -0,0 +1,40 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\User\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface ISetDisplayNameBackend {
+
+ /**
+ * @since 14.0.0
+ *
+ * @param string $uid The username
+ * @param string $displayName The new display name
+ * @return bool
+ */
+ public function setDisplayName(string $uid, string $displayName): bool;
+}
diff --git a/lib/public/User/Backend/ISetPasswordBackend.php b/lib/public/User/Backend/ISetPasswordBackend.php
new file mode 100644
index 00000000000..687ac5f70bb
--- /dev/null
+++ b/lib/public/User/Backend/ISetPasswordBackend.php
@@ -0,0 +1,40 @@
+<?php
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2018 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 OCP\User\Backend;
+
+/**
+ * @since 14.0.0
+ */
+interface ISetPasswordBackend {
+
+ /**
+ * @since 14.0.0
+ *
+ * @param string $uid The username
+ * @param string $password The new password
+ * @return bool
+ */
+ public function setPassword(string $uid, string $password): bool;
+}
diff --git a/lib/public/UserInterface.php b/lib/public/UserInterface.php
index 61136783b3c..b82fc6ba550 100644
--- a/lib/public/UserInterface.php
+++ b/lib/public/UserInterface.php
@@ -48,6 +48,7 @@ interface UserInterface {
* Returns the supported actions as int to be
* compared with \OC\User\Backend::CREATE_USER etc.
* @since 4.5.0
+ * @deprecated 14.0.0 Switch to the interfaces from OCP\User\Backend
*/
public function implementsActions($actions);
diff --git a/lib/public/Util.php b/lib/public/Util.php
index 2fb6bdf491d..27b703ea2d8 100644
--- a/lib/public/Util.php
+++ b/lib/public/Util.php
@@ -51,25 +51,38 @@
// use OCP namespace for all classes that are considered public.
// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP;
-use DateTimeZone;
/**
* This class provides different helper functions to make the life of a developer easier
* @since 4.0.0
*/
class Util {
- // consts for Logging
+ /**
+ * @deprecated 14.0.0 use \OCP\ILogger::DEBUG
+ */
const DEBUG=0;
+ /**
+ * @deprecated 14.0.0 use \OCP\ILogger::INFO
+ */
const INFO=1;
+ /**
+ * @deprecated 14.0.0 use \OCP\ILogger::WARN
+ */
const WARN=2;
+ /**
+ * @deprecated 14.0.0 use \OCP\ILogger::ERROR
+ */
const ERROR=3;
+ /**
+ * @deprecated 14.0.0 use \OCP\ILogger::FATAL
+ */
const FATAL=4;
/** \OCP\Share\IManager */
private static $shareManager;
/**
- * get the current installed version of ownCloud
+ * get the current installed version of Nextcloud
* @return array
* @since 4.0.0
*/
@@ -96,56 +109,6 @@ class Util {
}
/**
- * send an email
- * @param string $toaddress
- * @param string $toname
- * @param string $subject
- * @param string $mailtext
- * @param string $fromaddress
- * @param string $fromname
- * @param int $html
- * @param string $altbody
- * @param string $ccaddress
- * @param string $ccname
- * @param string $bcc
- * @deprecated 8.1.0 Use \OCP\Mail\IMailer instead
- * @since 4.0.0
- */
- public static function sendMail($toaddress, $toname, $subject, $mailtext, $fromaddress, $fromname,
- $html = 0, $altbody = '', $ccaddress = '', $ccname = '', $bcc = '') {
- $mailer = \OC::$server->getMailer();
- $message = $mailer->createMessage();
- $message->setTo([$toaddress => $toname]);
- $message->setSubject($subject);
- $message->setPlainBody($mailtext);
- $message->setFrom([$fromaddress => $fromname]);
- if($html === 1) {
- $message->setHtmlBody($altbody);
- }
-
- if($altbody === '') {
- $message->setHtmlBody($mailtext);
- $message->setPlainBody('');
- } else {
- $message->setHtmlBody($mailtext);
- $message->setPlainBody($altbody);
- }
-
- if(!empty($ccaddress)) {
- if(!empty($ccname)) {
- $message->setCc([$ccaddress => $ccname]);
- } else {
- $message->setCc([$ccaddress]);
- }
- }
- if(!empty($bcc)) {
- $message->setBcc([$bcc]);
- }
-
- $mailer->send($message);
- }
-
- /**
* write a message in the log
* @param string $app
* @param string $message
@@ -166,7 +129,7 @@ class Util {
* @since ....0.0 - parameter $level was added in 7.0.0
* @deprecated 8.2.0 use logException of \OCP\ILogger
*/
- public static function logException( $app, \Exception $ex, $level = \OCP\Util::FATAL ) {
+ public static function logException( $app, \Exception $ex, $level = ILogger::FATAL) {
\OC::$server->getLogger()->logException($ex, ['app' => $app]);
}
@@ -245,17 +208,6 @@ class Util {
}
/**
- * check if some encrypted files are stored
- * @return bool
- *
- * @deprecated 8.1.0 No longer required
- * @since 6.0.0
- */
- public static function encryptedFiles() {
- return false;
- }
-
- /**
* Creates an absolute url to the given app and file.
* @param string $app app
* @param string $file file
@@ -296,43 +248,6 @@ class Util {
}
/**
- * Creates an url using a defined route
- * @param string $route
- * @param array $parameters
- * @internal param array $args with param=>value, will be appended to the returned url
- * @return string the url
- * @deprecated 8.1.0 Use \OC::$server->getURLGenerator()->linkToRoute($route, $parameters)
- * @since 5.0.0
- */
- public static function linkToRoute( $route, $parameters = array() ) {
- return \OC::$server->getURLGenerator()->linkToRoute($route, $parameters);
- }
-
- /**
- * Creates an url to the given app and file
- * @param string $app app
- * @param string $file file
- * @param array $args array with param=>value, will be appended to the returned url
- * The value of $args will be urlencoded
- * @return string the url
- * @deprecated 8.1.0 Use \OC::$server->getURLGenerator()->linkTo($app, $file, $args)
- * @since 4.0.0 - parameter $args was added in 4.5.0
- */
- public static function linkTo( $app, $file, $args = array() ) {
- return \OC::$server->getURLGenerator()->linkTo($app, $file, $args);
- }
-
- /**
- * Returns the server host, even if the website uses one or more reverse proxy
- * @return string the server host
- * @deprecated 8.1.0 Use \OCP\IRequest::getServerHost
- * @since 4.0.0
- */
- public static function getServerHost() {
- return \OC::$server->getRequest()->getServerHost();
- }
-
- /**
* Returns the server host name without an eventual port number
* @return string the server hostname
* @since 5.0.0
@@ -380,48 +295,6 @@ class Util {
}
/**
- * Returns the server protocol. It respects reverse proxy servers and load balancers
- * @return string the server protocol
- * @deprecated 8.1.0 Use \OCP\IRequest::getServerProtocol
- * @since 4.5.0
- */
- public static function getServerProtocol() {
- return \OC::$server->getRequest()->getServerProtocol();
- }
-
- /**
- * Returns the request uri, even if the website uses one or more reverse proxies
- * @return string the request uri
- * @deprecated 8.1.0 Use \OCP\IRequest::getRequestUri
- * @since 5.0.0
- */
- public static function getRequestUri() {
- return \OC::$server->getRequest()->getRequestUri();
- }
-
- /**
- * Returns the script name, even if the website uses one or more reverse proxies
- * @return string the script name
- * @deprecated 8.1.0 Use \OCP\IRequest::getScriptName
- * @since 5.0.0
- */
- public static function getScriptName() {
- return \OC::$server->getRequest()->getScriptName();
- }
-
- /**
- * Creates path to an image
- * @param string $app app
- * @param string $image image name
- * @return string the url
- * @deprecated 8.1.0 Use \OC::$server->getURLGenerator()->imagePath($app, $image)
- * @since 4.0.0
- */
- public static function imagePath( $app, $image ) {
- return \OC::$server->getURLGenerator()->imagePath($app, $image);
- }
-
- /**
* Make a human file size (2048 to 2 kB)
* @param int $bytes file size in bytes
* @return string a human readable file size