diff options
Diffstat (limited to 'lib')
57 files changed, 2015 insertions, 212 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 9a54c3bf3c6..50730813700 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -170,6 +170,13 @@ return array( 'OCP\\Diagnostics\\IEventLogger' => $baseDir . '/lib/public/Diagnostics/IEventLogger.php', 'OCP\\Diagnostics\\IQuery' => $baseDir . '/lib/public/Diagnostics/IQuery.php', 'OCP\\Diagnostics\\IQueryLogger' => $baseDir . '/lib/public/Diagnostics/IQueryLogger.php', + 'OCP\\DirectEditing\\ACreateEmpty' => $baseDir . '/lib/public/DirectEditing/ACreateEmpty.php', + 'OCP\\DirectEditing\\ACreateFromTemplate' => $baseDir . '/lib/public/DirectEditing/ACreateFromTemplate.php', + 'OCP\\DirectEditing\\ATemplate' => $baseDir . '/lib/public/DirectEditing/ATemplate.php', + 'OCP\\DirectEditing\\IEditor' => $baseDir . '/lib/public/DirectEditing/IEditor.php', + 'OCP\\DirectEditing\\IManager' => $baseDir . '/lib/public/DirectEditing/IManager.php', + 'OCP\\DirectEditing\\IToken' => $baseDir . '/lib/public/DirectEditing/IToken.php', + 'OCP\\DirectEditing\\RegisterDirectEditorEvent' => $baseDir . '/lib/public/DirectEditing/RegisterDirectEditorEvent.php', 'OCP\\Encryption\\Exceptions\\GenericEncryptionException' => $baseDir . '/lib/public/Encryption/Exceptions/GenericEncryptionException.php', 'OCP\\Encryption\\IEncryptionModule' => $baseDir . '/lib/public/Encryption/IEncryptionModule.php', 'OCP\\Encryption\\IFile' => $baseDir . '/lib/public/Encryption/IFile.php', @@ -177,6 +184,7 @@ return array( 'OCP\\Encryption\\Keys\\IStorage' => $baseDir . '/lib/public/Encryption/Keys/IStorage.php', 'OCP\\EventDispatcher\\ABroadcastedEvent' => $baseDir . '/lib/public/EventDispatcher/ABroadcastedEvent.php', 'OCP\\EventDispatcher\\Event' => $baseDir . '/lib/public/EventDispatcher/Event.php', + 'OCP\\EventDispatcher\\GenericEvent' => $baseDir . '/lib/public/EventDispatcher/GenericEvent.php', 'OCP\\EventDispatcher\\IEventDispatcher' => $baseDir . '/lib/public/EventDispatcher/IEventDispatcher.php', 'OCP\\EventDispatcher\\IEventListener' => $baseDir . '/lib/public/EventDispatcher/IEventListener.php', 'OCP\\Federation\\Exceptions\\ActionNotSupportedException' => $baseDir . '/lib/public/Federation/Exceptions/ActionNotSupportedException.php', @@ -385,6 +393,8 @@ return array( 'OCP\\Search\\Provider' => $baseDir . '/lib/public/Search/Provider.php', 'OCP\\Search\\Result' => $baseDir . '/lib/public/Search/Result.php', 'OCP\\Security\\CSP\\AddContentSecurityPolicyEvent' => $baseDir . '/lib/public/Security/CSP/AddContentSecurityPolicyEvent.php', + 'OCP\\Security\\Events\\GenerateSecurePasswordEvent' => $baseDir . '/lib/public/Security/Events/GenerateSecurePasswordEvent.php', + 'OCP\\Security\\Events\\ValidatePasswordPolicyEvent' => $baseDir . '/lib/public/Security/Events/ValidatePasswordPolicyEvent.php', 'OCP\\Security\\FeaturePolicy\\AddFeaturePolicyEvent' => $baseDir . '/lib/public/Security/FeaturePolicy/AddFeaturePolicyEvent.php', 'OCP\\Security\\IContentSecurityPolicyManager' => $baseDir . '/lib/public/Security/IContentSecurityPolicyManager.php', 'OCP\\Security\\ICredentialsManager' => $baseDir . '/lib/public/Security/ICredentialsManager.php', @@ -440,8 +450,14 @@ return array( '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\\User\\Events\\CreateUserEvent' => $baseDir . '/lib/public/User/Events/CreateUserEvent.php', 'OCP\\User\\Events\\PostLoginEvent' => $baseDir . '/lib/public/User/Events/PostLoginEvent.php', + 'OCP\\User\\Events\\UserCreatedEvent' => $baseDir . '/lib/public/User/Events/UserCreatedEvent.php', 'OCP\\Util' => $baseDir . '/lib/public/Util.php', + 'OCP\\WorkflowEngine\\EntityContext\\IDisplayName' => $baseDir . '/lib/public/WorkflowEngine/EntityContext/IDisplayName.php', + 'OCP\\WorkflowEngine\\EntityContext\\IDisplayText' => $baseDir . '/lib/public/WorkflowEngine/EntityContext/IDisplayText.php', + 'OCP\\WorkflowEngine\\EntityContext\\IIcon' => $baseDir . '/lib/public/WorkflowEngine/EntityContext/IIcon.php', + 'OCP\\WorkflowEngine\\EntityContext\\IUrl' => $baseDir . '/lib/public/WorkflowEngine/EntityContext/IUrl.php', 'OCP\\WorkflowEngine\\GenericEntityEvent' => $baseDir . '/lib/public/WorkflowEngine/GenericEntityEvent.php', 'OCP\\WorkflowEngine\\ICheck' => $baseDir . '/lib/public/WorkflowEngine/ICheck.php', 'OCP\\WorkflowEngine\\IComplexOperation' => $baseDir . '/lib/public/WorkflowEngine/IComplexOperation.php', @@ -545,6 +561,7 @@ return array( 'OC\\Authentication\\Exceptions\\LoginRequiredException' => $baseDir . '/lib/private/Authentication/Exceptions/LoginRequiredException.php', 'OC\\Authentication\\Exceptions\\PasswordLoginForbiddenException' => $baseDir . '/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php', 'OC\\Authentication\\Exceptions\\PasswordlessTokenException' => $baseDir . '/lib/private/Authentication/Exceptions/PasswordlessTokenException.php', + 'OC\\Authentication\\Exceptions\\TokenPasswordExpiredException' => $baseDir . '/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php', 'OC\\Authentication\\Exceptions\\TwoFactorAuthRequiredException' => $baseDir . '/lib/private/Authentication/Exceptions/TwoFactorAuthRequiredException.php', 'OC\\Authentication\\Exceptions\\UserAlreadyLoggedInException' => $baseDir . '/lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php', 'OC\\Authentication\\Exceptions\\WipeTokenException' => $baseDir . '/lib/private/Authentication/Exceptions/WipeTokenException.php', @@ -786,6 +803,7 @@ return array( 'OC\\Core\\Migrations\\Version16000Date20190428150708' => $baseDir . '/core/Migrations/Version16000Date20190428150708.php', 'OC\\Core\\Migrations\\Version17000Date20190514105811' => $baseDir . '/core/Migrations/Version17000Date20190514105811.php', 'OC\\Core\\Migrations\\Version18000Date20190920085628' => $baseDir . '/core/Migrations/Version18000Date20190920085628.php', + 'OC\\Core\\Migrations\\Version18000Date20191014105105' => $baseDir . '/core/Migrations/Version18000Date20191014105105.php', 'OC\\Core\\Notification\\RemoveLinkSharesNotifier' => $baseDir . '/core/Notification/RemoveLinkSharesNotifier.php', 'OC\\Core\\Service\\LoginFlowV2Service' => $baseDir . '/core/Service/LoginFlowV2Service.php', 'OC\\DB\\Adapter' => $baseDir . '/lib/private/DB/Adapter.php', @@ -837,6 +855,8 @@ return array( 'OC\\Diagnostics\\EventLogger' => $baseDir . '/lib/private/Diagnostics/EventLogger.php', 'OC\\Diagnostics\\Query' => $baseDir . '/lib/private/Diagnostics/Query.php', 'OC\\Diagnostics\\QueryLogger' => $baseDir . '/lib/private/Diagnostics/QueryLogger.php', + 'OC\\DirectEditing\\Manager' => $baseDir . '/lib/private/DirectEditing/Manager.php', + 'OC\\DirectEditing\\Token' => $baseDir . '/lib/private/DirectEditing/Token.php', 'OC\\Encryption\\DecryptAll' => $baseDir . '/lib/private/Encryption/DecryptAll.php', 'OC\\Encryption\\EncryptionWrapper' => $baseDir . '/lib/private/Encryption/EncryptionWrapper.php', 'OC\\Encryption\\Exceptions\\DecryptionFailedException' => $baseDir . '/lib/private/Encryption/Exceptions/DecryptionFailedException.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index e06489c4cc0..5f7e8fde989 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -199,6 +199,13 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Diagnostics\\IEventLogger' => __DIR__ . '/../../..' . '/lib/public/Diagnostics/IEventLogger.php', 'OCP\\Diagnostics\\IQuery' => __DIR__ . '/../../..' . '/lib/public/Diagnostics/IQuery.php', 'OCP\\Diagnostics\\IQueryLogger' => __DIR__ . '/../../..' . '/lib/public/Diagnostics/IQueryLogger.php', + 'OCP\\DirectEditing\\ACreateEmpty' => __DIR__ . '/../../..' . '/lib/public/DirectEditing/ACreateEmpty.php', + 'OCP\\DirectEditing\\ACreateFromTemplate' => __DIR__ . '/../../..' . '/lib/public/DirectEditing/ACreateFromTemplate.php', + 'OCP\\DirectEditing\\ATemplate' => __DIR__ . '/../../..' . '/lib/public/DirectEditing/ATemplate.php', + 'OCP\\DirectEditing\\IEditor' => __DIR__ . '/../../..' . '/lib/public/DirectEditing/IEditor.php', + 'OCP\\DirectEditing\\IManager' => __DIR__ . '/../../..' . '/lib/public/DirectEditing/IManager.php', + 'OCP\\DirectEditing\\IToken' => __DIR__ . '/../../..' . '/lib/public/DirectEditing/IToken.php', + 'OCP\\DirectEditing\\RegisterDirectEditorEvent' => __DIR__ . '/../../..' . '/lib/public/DirectEditing/RegisterDirectEditorEvent.php', 'OCP\\Encryption\\Exceptions\\GenericEncryptionException' => __DIR__ . '/../../..' . '/lib/public/Encryption/Exceptions/GenericEncryptionException.php', 'OCP\\Encryption\\IEncryptionModule' => __DIR__ . '/../../..' . '/lib/public/Encryption/IEncryptionModule.php', 'OCP\\Encryption\\IFile' => __DIR__ . '/../../..' . '/lib/public/Encryption/IFile.php', @@ -206,6 +213,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Encryption\\Keys\\IStorage' => __DIR__ . '/../../..' . '/lib/public/Encryption/Keys/IStorage.php', 'OCP\\EventDispatcher\\ABroadcastedEvent' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/ABroadcastedEvent.php', 'OCP\\EventDispatcher\\Event' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/Event.php', + 'OCP\\EventDispatcher\\GenericEvent' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/GenericEvent.php', 'OCP\\EventDispatcher\\IEventDispatcher' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/IEventDispatcher.php', 'OCP\\EventDispatcher\\IEventListener' => __DIR__ . '/../../..' . '/lib/public/EventDispatcher/IEventListener.php', 'OCP\\Federation\\Exceptions\\ActionNotSupportedException' => __DIR__ . '/../../..' . '/lib/public/Federation/Exceptions/ActionNotSupportedException.php', @@ -414,6 +422,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Search\\Provider' => __DIR__ . '/../../..' . '/lib/public/Search/Provider.php', 'OCP\\Search\\Result' => __DIR__ . '/../../..' . '/lib/public/Search/Result.php', 'OCP\\Security\\CSP\\AddContentSecurityPolicyEvent' => __DIR__ . '/../../..' . '/lib/public/Security/CSP/AddContentSecurityPolicyEvent.php', + 'OCP\\Security\\Events\\GenerateSecurePasswordEvent' => __DIR__ . '/../../..' . '/lib/public/Security/Events/GenerateSecurePasswordEvent.php', + 'OCP\\Security\\Events\\ValidatePasswordPolicyEvent' => __DIR__ . '/../../..' . '/lib/public/Security/Events/ValidatePasswordPolicyEvent.php', 'OCP\\Security\\FeaturePolicy\\AddFeaturePolicyEvent' => __DIR__ . '/../../..' . '/lib/public/Security/FeaturePolicy/AddFeaturePolicyEvent.php', 'OCP\\Security\\IContentSecurityPolicyManager' => __DIR__ . '/../../..' . '/lib/public/Security/IContentSecurityPolicyManager.php', 'OCP\\Security\\ICredentialsManager' => __DIR__ . '/../../..' . '/lib/public/Security/ICredentialsManager.php', @@ -469,8 +479,14 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c '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\\User\\Events\\CreateUserEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/CreateUserEvent.php', 'OCP\\User\\Events\\PostLoginEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/PostLoginEvent.php', + 'OCP\\User\\Events\\UserCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserCreatedEvent.php', 'OCP\\Util' => __DIR__ . '/../../..' . '/lib/public/Util.php', + 'OCP\\WorkflowEngine\\EntityContext\\IDisplayName' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/EntityContext/IDisplayName.php', + 'OCP\\WorkflowEngine\\EntityContext\\IDisplayText' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/EntityContext/IDisplayText.php', + 'OCP\\WorkflowEngine\\EntityContext\\IIcon' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/EntityContext/IIcon.php', + 'OCP\\WorkflowEngine\\EntityContext\\IUrl' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/EntityContext/IUrl.php', 'OCP\\WorkflowEngine\\GenericEntityEvent' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/GenericEntityEvent.php', 'OCP\\WorkflowEngine\\ICheck' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/ICheck.php', 'OCP\\WorkflowEngine\\IComplexOperation' => __DIR__ . '/../../..' . '/lib/public/WorkflowEngine/IComplexOperation.php', @@ -574,6 +590,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Authentication\\Exceptions\\LoginRequiredException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/LoginRequiredException.php', 'OC\\Authentication\\Exceptions\\PasswordLoginForbiddenException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/PasswordLoginForbiddenException.php', 'OC\\Authentication\\Exceptions\\PasswordlessTokenException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/PasswordlessTokenException.php', + 'OC\\Authentication\\Exceptions\\TokenPasswordExpiredException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php', 'OC\\Authentication\\Exceptions\\TwoFactorAuthRequiredException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/TwoFactorAuthRequiredException.php', 'OC\\Authentication\\Exceptions\\UserAlreadyLoggedInException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/UserAlreadyLoggedInException.php', 'OC\\Authentication\\Exceptions\\WipeTokenException' => __DIR__ . '/../../..' . '/lib/private/Authentication/Exceptions/WipeTokenException.php', @@ -815,6 +832,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Core\\Migrations\\Version16000Date20190428150708' => __DIR__ . '/../../..' . '/core/Migrations/Version16000Date20190428150708.php', 'OC\\Core\\Migrations\\Version17000Date20190514105811' => __DIR__ . '/../../..' . '/core/Migrations/Version17000Date20190514105811.php', 'OC\\Core\\Migrations\\Version18000Date20190920085628' => __DIR__ . '/../../..' . '/core/Migrations/Version18000Date20190920085628.php', + 'OC\\Core\\Migrations\\Version18000Date20191014105105' => __DIR__ . '/../../..' . '/core/Migrations/Version18000Date20191014105105.php', 'OC\\Core\\Notification\\RemoveLinkSharesNotifier' => __DIR__ . '/../../..' . '/core/Notification/RemoveLinkSharesNotifier.php', 'OC\\Core\\Service\\LoginFlowV2Service' => __DIR__ . '/../../..' . '/core/Service/LoginFlowV2Service.php', 'OC\\DB\\Adapter' => __DIR__ . '/../../..' . '/lib/private/DB/Adapter.php', @@ -866,6 +884,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Diagnostics\\EventLogger' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/EventLogger.php', 'OC\\Diagnostics\\Query' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/Query.php', 'OC\\Diagnostics\\QueryLogger' => __DIR__ . '/../../..' . '/lib/private/Diagnostics/QueryLogger.php', + 'OC\\DirectEditing\\Manager' => __DIR__ . '/../../..' . '/lib/private/DirectEditing/Manager.php', + 'OC\\DirectEditing\\Token' => __DIR__ . '/../../..' . '/lib/private/DirectEditing/Token.php', 'OC\\Encryption\\DecryptAll' => __DIR__ . '/../../..' . '/lib/private/Encryption/DecryptAll.php', 'OC\\Encryption\\EncryptionWrapper' => __DIR__ . '/../../..' . '/lib/private/Encryption/EncryptionWrapper.php', 'OC\\Encryption\\Exceptions\\DecryptionFailedException' => __DIR__ . '/../../..' . '/lib/private/Encryption/Exceptions/DecryptionFailedException.php', diff --git a/lib/l10n/cs.js b/lib/l10n/cs.js index 123a7bb909e..7493f63e6f2 100644 --- a/lib/l10n/cs.js +++ b/lib/l10n/cs.js @@ -7,7 +7,7 @@ OC.L10N.register( "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Nebo, pokud chcete mít soubor config.php pouze pro čtení, nastavte v něm volbu „config_is_read_only“ na hodnotu true.", "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Toto obvykle lze vyřešit udělením oprávnění k zápisu do kořenové složky webu pro účet, pod kterým je provozován webový server. Viz %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" : "Nebo, pokud chcete mít soubor config.php pouze pro čtení, nastavte v něm volbu „config_is_read_only“ na hodnotu true. Viz %s", - "The files of the app %1$s were not replaced correctly. Make sure it is a version compatible with the server." : "Soubory aplikace %1$s nebyly řádně nahrazeny. Ověřte, že je to verze kompatibilní se serverem.", + "The files of the app %1$s were not replaced correctly. Make sure it is a version compatible with the server." : "Soubory aplikace %1$s nebyly nahrazeny řádně. Ověřte, že se jedná o verzi, která je kompatibilní se serverem.", "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 nastavení ze vzorových souborů. Toto není podporováno a může poškodit vaši instalaci. Před prováděním změn v souboru config.php si přečtěte dokumentaci", "%1$s and %2$s" : "%1$s a %2$s", @@ -18,7 +18,7 @@ OC.L10N.register( "Enterprise bundle" : "Sada pro organizace", "Groupware bundle" : "Sada pro podporu spolupráce", "Social sharing bundle" : "Balíček sociálního sdílení", - "PHP %s or higher is required." : "Je vyžadováno PHP %s nebo vyšší.", + "PHP %s or higher is required." : "Je vyžadováno PHP %s nebo novější.", "PHP with a version lower than %s is required." : "Je vyžadováno PHP ve verzi nižší než %s.", "%sbit or higher PHP required." : "Je vyžadováno PHP %sbit nebo vyšší.", "Following databases are supported: %s" : "Jsou podporovány následující databáze: %s", @@ -27,26 +27,26 @@ OC.L10N.register( "Library %1$s with a version higher than %2$s is required - available version %3$s." : "Je vyžadována knihovna %1$s novější verze než %2$s – verze k dispozici je %3$s.", "Library %1$s with a version lower than %2$s is required - available version %3$s." : "Je vyžadována knihovna %1$s verzi nižší než %2$s – dostupná verze %3$s.", "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 or sub admin" : "Je třeba, aby přihlášený uživatel byl správcem či dílčím správcem", + "Server version %s or higher is required." : "Je potřeba verze serveru %s nebo novější.", + "Server version %s or lower is required." : "Je potřeba verze serveru %s nebo starší.", + "Logged in user must be an admin or sub admin" : "Je třeba, aby přihlášený uživatel byl správcem či správcem pro dílčí oblast", "Logged in user must be an admin" : "Je třeba, aby přihlášený uživatel byl správce", "Wiping of device %s has started" : "Vymazávání zařízení %s zahájeno", "Wiping of device »%s« has started" : "Vymazávání zařízení „%s“ zahájeno", - "»%s« started remote wipe" : "»%s« vzdálené vymazání spuštěno", + "»%s« started remote wipe" : "„%s“ zahájilo vymazávání na dálku", "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "Přístroj či aplikace »%s« spustila proces vzdáleného vymazání. Obdržíte další e-mail poté co bude proces ukončen", "Wiping of device %s has finished" : "Vymazávání zařízení %s dokončeno", "Wiping of device »%s« has finished" : "Vymazávání zařízení „%s“ dokončeno", - "»%s« finished remote wipe" : "»%s« vzdálené vymazání dokončeno", - "Device or application »%s« has finished the remote wipe process." : "Přístroj či aplikace »%s« dokončila proces vzdáleného vymazání.", + "»%s« finished remote wipe" : "„%s“ dokončilo vymazání na dálku", + "Device or application »%s« has finished the remote wipe process." : "Přístroj či aplikace „%s“ dokončila proces vymazání na dálku.", "Remote wipe started" : "Vymazání na dálku zahájeno", - "A remote wipe was started on device %s" : "Vzdálené vymazání běží na přístroji %s", + "A remote wipe was started on device %s" : "Na zařízení %s bylo spuštěno vymazání na dálku", "Remote wipe finished" : "Vymazání na dálku dokončeno", - "The remote wipe on %s has finished" : "Vzdálené vymazání přístroje %s dokončeno", + "The remote wipe on %s has finished" : "Vymazání %s na dálku dokončeno", "Authentication" : "Ověření", "Unknown filetype" : "Neznámý typ souboru", "Invalid image" : "Neplatný obrázek", - "Avatar image is not square" : "Avatar není čtvercový", + "Avatar image is not square" : "Obrázek s avatarem není čtvercový", "today" : "dnes", "tomorrow" : "zítra", "yesterday" : "včera", @@ -66,7 +66,7 @@ OC.L10N.register( "_%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.", + "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul s identifikátorem: %s neexistuje. Povolte ho v nastavení aplikací, nebo se obraťte na správce.", "File name is a reserved word" : "Název souboru je rezervované slovo", "File name contains at least one invalid character" : "Název souboru obsahuje nejméně jeden neplatný znak", "File name is too long" : "Název souboru je příliš dlouhý", @@ -102,16 +102,16 @@ OC.L10N.register( "For the best results, please consider using a GNU/Linux server instead." : "Místo toho zvažte pro nejlepší funkčnost použití GNU/Linux serveru.", "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." : "Zdá se, že tato instance %s je provozována v 32-bitovém PHP prostředí a v php.ini je nastavena volba open_basedir. Toto povede k problémům se soubory většími než 4 GB a silně není doporučováno.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Odstraňte z php.ini nastavení volby open_basedir nebo přejděte na 64-bitové PHP.", - "Set an admin username." : "Zadejte uživatelské jméno správce.", + "Set an admin username." : "Nastavte uživatelské jméno správce.", "Set an admin password." : "Zadejte heslo správce.", "Can't create or write into the data directory %s" : "Nedaří se vytvořit nebo zapisovat do datového adresáře %s", "Invalid Federated Cloud ID" : "Neplatné sdružené cloud ID", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Úložiště pro sdílení %s musí implementovat rozhraní OCP\\Share_Backend", "Sharing backend %s not found" : "Úložiště sdílení %s nenalezeno", "Sharing backend for %s not found" : "Úložiště sdílení pro %s nenalezeno", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s sdílí »%2$s« a dodává:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s sdílí »%2$s« a dodává", - "»%s« added a note to a file shared with you" : "»%s« dodává poznámku k nasdílenému souboru ", + "%1$s shared »%2$s« with you and wants to add:" : "%1$s sdílí „%2$s“ a dodává:", + "%1$s shared »%2$s« with you and wants to add" : "%1$s sdílí „%2$s“ a dodává", + "»%s« added a note to a file shared with you" : "„%s“ dodává poznámku k nasdílenému souboru ", "Open »%s«" : "Otevřít „%s“", "%1$s via %2$s" : "%1$s prostřednictvím %2$s", "You are not allowed to share %s" : "Nemáte povoleno sdílet %s", @@ -119,10 +119,10 @@ OC.L10N.register( "Files can’t be shared with delete permissions" : "Soubory nelze sdílet s oprávněními k odstranění", "Files can’t be shared with create permissions" : "Soubory nelze sdílet s oprávněními k vytváření", "Expiration date is in the past" : "Datum skončení platnosti je v minulosti", - "Can’t set expiration date more than %s days in the future" : "Nelze nastavit datum vypršení platnosti více než %s dní v budoucnu", + "Can’t set expiration date more than %s days in the future" : "Nelze nastavit datum skončení platnosti více než %s dní v budoucnu", "%1$s shared »%2$s« with you" : "%1$s s vámi sdílí „%2$s“", "%1$s shared »%2$s« with you." : "%1$s vám nasdílel(a) „%2$s“.", - "Click the button below to open it." : "Pro otevření kliknětena tlačítko níže.", + "Click the button below to open it." : "Pro otevření klikněte na tlačítko níže.", "The requested share does not exist anymore" : "Požadované sdílení už neexistuje", "Could not find category \"%s\"" : "Nedaří se nalézt kategorii „%s“", "Sunday" : "neděle", @@ -132,20 +132,20 @@ OC.L10N.register( "Thursday" : "čtvrtek", "Friday" : "pátek", "Saturday" : "sobota", - "Sun." : "Ne", - "Mon." : "Po", - "Tue." : "Út", - "Wed." : "St", - "Thu." : "Čt", - "Fri." : "Pá", - "Sat." : "So", - "Su" : "Ne", - "Mo" : "Po", - "Tu" : "Út", - "We" : "St", - "Th" : "Čt", - "Fr" : "Pá", - "Sa" : "So", + "Sun." : "ne", + "Mon." : "po", + "Tue." : "út", + "Wed." : "st", + "Thu." : "čt", + "Fri." : "pá", + "Sat." : "so", + "Su" : "ne", + "Mo" : "po", + "Tu" : "út", + "We" : "st", + "Th" : "čt", + "Fr" : "pá", + "Sa" : "so", "January" : "leden", "February" : "únor", "March" : "březen", @@ -158,18 +158,18 @@ OC.L10N.register( "October" : "říjen", "November" : "listopad", "December" : "prosinec", - "Jan." : "leden", - "Feb." : "únor", - "Mar." : "březen", - "Apr." : "duben", - "May." : "květen", - "Jun." : "červen", - "Jul." : "červenec", - "Aug." : "srpen", - "Sep." : "září", - "Oct." : "říjen", + "Jan." : "led.", + "Feb." : "úno.", + "Mar." : "bře.", + "Apr." : "dub.", + "May." : "kvě.", + "Jun." : "čvn.", + "Jul." : "čvc.", + "Aug." : "srp.", + "Sep." : "zář.", + "Oct." : "říj.", "Nov." : "list.", - "Dec." : "prosinec", + "Dec." : "pro.", "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Pouze následující znaky jsou povoleny pro uživatelské jméno: „a-z“, „A-Z“, „0-9“, a „_.@-'“", "A valid username must be provided" : "Je třeba zadat platné uživatelské jméno", "Username contains whitespace at the beginning or at the end" : "Uživatelské jméno obsahuje mezery na svém začátku nebo konci", diff --git a/lib/l10n/cs.json b/lib/l10n/cs.json index 99cc9b2f406..322b3bc62f2 100644 --- a/lib/l10n/cs.json +++ b/lib/l10n/cs.json @@ -5,7 +5,7 @@ "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Nebo, pokud chcete mít soubor config.php pouze pro čtení, nastavte v něm volbu „config_is_read_only“ na hodnotu true.", "This can usually be fixed by giving the webserver write access to the config directory. See %s" : "Toto obvykle lze vyřešit udělením oprávnění k zápisu do kořenové složky webu pro účet, pod kterým je provozován webový server. Viz %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" : "Nebo, pokud chcete mít soubor config.php pouze pro čtení, nastavte v něm volbu „config_is_read_only“ na hodnotu true. Viz %s", - "The files of the app %1$s were not replaced correctly. Make sure it is a version compatible with the server." : "Soubory aplikace %1$s nebyly řádně nahrazeny. Ověřte, že je to verze kompatibilní se serverem.", + "The files of the app %1$s were not replaced correctly. Make sure it is a version compatible with the server." : "Soubory aplikace %1$s nebyly nahrazeny řádně. Ověřte, že se jedná o verzi, která je kompatibilní se serverem.", "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 nastavení ze vzorových souborů. Toto není podporováno a může poškodit vaši instalaci. Před prováděním změn v souboru config.php si přečtěte dokumentaci", "%1$s and %2$s" : "%1$s a %2$s", @@ -16,7 +16,7 @@ "Enterprise bundle" : "Sada pro organizace", "Groupware bundle" : "Sada pro podporu spolupráce", "Social sharing bundle" : "Balíček sociálního sdílení", - "PHP %s or higher is required." : "Je vyžadováno PHP %s nebo vyšší.", + "PHP %s or higher is required." : "Je vyžadováno PHP %s nebo novější.", "PHP with a version lower than %s is required." : "Je vyžadováno PHP ve verzi nižší než %s.", "%sbit or higher PHP required." : "Je vyžadováno PHP %sbit nebo vyšší.", "Following databases are supported: %s" : "Jsou podporovány následující databáze: %s", @@ -25,26 +25,26 @@ "Library %1$s with a version higher than %2$s is required - available version %3$s." : "Je vyžadována knihovna %1$s novější verze než %2$s – verze k dispozici je %3$s.", "Library %1$s with a version lower than %2$s is required - available version %3$s." : "Je vyžadována knihovna %1$s verzi nižší než %2$s – dostupná verze %3$s.", "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 or sub admin" : "Je třeba, aby přihlášený uživatel byl správcem či dílčím správcem", + "Server version %s or higher is required." : "Je potřeba verze serveru %s nebo novější.", + "Server version %s or lower is required." : "Je potřeba verze serveru %s nebo starší.", + "Logged in user must be an admin or sub admin" : "Je třeba, aby přihlášený uživatel byl správcem či správcem pro dílčí oblast", "Logged in user must be an admin" : "Je třeba, aby přihlášený uživatel byl správce", "Wiping of device %s has started" : "Vymazávání zařízení %s zahájeno", "Wiping of device »%s« has started" : "Vymazávání zařízení „%s“ zahájeno", - "»%s« started remote wipe" : "»%s« vzdálené vymazání spuštěno", + "»%s« started remote wipe" : "„%s“ zahájilo vymazávání na dálku", "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "Přístroj či aplikace »%s« spustila proces vzdáleného vymazání. Obdržíte další e-mail poté co bude proces ukončen", "Wiping of device %s has finished" : "Vymazávání zařízení %s dokončeno", "Wiping of device »%s« has finished" : "Vymazávání zařízení „%s“ dokončeno", - "»%s« finished remote wipe" : "»%s« vzdálené vymazání dokončeno", - "Device or application »%s« has finished the remote wipe process." : "Přístroj či aplikace »%s« dokončila proces vzdáleného vymazání.", + "»%s« finished remote wipe" : "„%s“ dokončilo vymazání na dálku", + "Device or application »%s« has finished the remote wipe process." : "Přístroj či aplikace „%s“ dokončila proces vymazání na dálku.", "Remote wipe started" : "Vymazání na dálku zahájeno", - "A remote wipe was started on device %s" : "Vzdálené vymazání běží na přístroji %s", + "A remote wipe was started on device %s" : "Na zařízení %s bylo spuštěno vymazání na dálku", "Remote wipe finished" : "Vymazání na dálku dokončeno", - "The remote wipe on %s has finished" : "Vzdálené vymazání přístroje %s dokončeno", + "The remote wipe on %s has finished" : "Vymazání %s na dálku dokončeno", "Authentication" : "Ověření", "Unknown filetype" : "Neznámý typ souboru", "Invalid image" : "Neplatný obrázek", - "Avatar image is not square" : "Avatar není čtvercový", + "Avatar image is not square" : "Obrázek s avatarem není čtvercový", "today" : "dnes", "tomorrow" : "zítra", "yesterday" : "včera", @@ -64,7 +64,7 @@ "_%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.", + "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul s identifikátorem: %s neexistuje. Povolte ho v nastavení aplikací, nebo se obraťte na správce.", "File name is a reserved word" : "Název souboru je rezervované slovo", "File name contains at least one invalid character" : "Název souboru obsahuje nejméně jeden neplatný znak", "File name is too long" : "Název souboru je příliš dlouhý", @@ -100,16 +100,16 @@ "For the best results, please consider using a GNU/Linux server instead." : "Místo toho zvažte pro nejlepší funkčnost použití GNU/Linux serveru.", "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." : "Zdá se, že tato instance %s je provozována v 32-bitovém PHP prostředí a v php.ini je nastavena volba open_basedir. Toto povede k problémům se soubory většími než 4 GB a silně není doporučováno.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Odstraňte z php.ini nastavení volby open_basedir nebo přejděte na 64-bitové PHP.", - "Set an admin username." : "Zadejte uživatelské jméno správce.", + "Set an admin username." : "Nastavte uživatelské jméno správce.", "Set an admin password." : "Zadejte heslo správce.", "Can't create or write into the data directory %s" : "Nedaří se vytvořit nebo zapisovat do datového adresáře %s", "Invalid Federated Cloud ID" : "Neplatné sdružené cloud ID", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Úložiště pro sdílení %s musí implementovat rozhraní OCP\\Share_Backend", "Sharing backend %s not found" : "Úložiště sdílení %s nenalezeno", "Sharing backend for %s not found" : "Úložiště sdílení pro %s nenalezeno", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s sdílí »%2$s« a dodává:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s sdílí »%2$s« a dodává", - "»%s« added a note to a file shared with you" : "»%s« dodává poznámku k nasdílenému souboru ", + "%1$s shared »%2$s« with you and wants to add:" : "%1$s sdílí „%2$s“ a dodává:", + "%1$s shared »%2$s« with you and wants to add" : "%1$s sdílí „%2$s“ a dodává", + "»%s« added a note to a file shared with you" : "„%s“ dodává poznámku k nasdílenému souboru ", "Open »%s«" : "Otevřít „%s“", "%1$s via %2$s" : "%1$s prostřednictvím %2$s", "You are not allowed to share %s" : "Nemáte povoleno sdílet %s", @@ -117,10 +117,10 @@ "Files can’t be shared with delete permissions" : "Soubory nelze sdílet s oprávněními k odstranění", "Files can’t be shared with create permissions" : "Soubory nelze sdílet s oprávněními k vytváření", "Expiration date is in the past" : "Datum skončení platnosti je v minulosti", - "Can’t set expiration date more than %s days in the future" : "Nelze nastavit datum vypršení platnosti více než %s dní v budoucnu", + "Can’t set expiration date more than %s days in the future" : "Nelze nastavit datum skončení platnosti více než %s dní v budoucnu", "%1$s shared »%2$s« with you" : "%1$s s vámi sdílí „%2$s“", "%1$s shared »%2$s« with you." : "%1$s vám nasdílel(a) „%2$s“.", - "Click the button below to open it." : "Pro otevření kliknětena tlačítko níže.", + "Click the button below to open it." : "Pro otevření klikněte na tlačítko níže.", "The requested share does not exist anymore" : "Požadované sdílení už neexistuje", "Could not find category \"%s\"" : "Nedaří se nalézt kategorii „%s“", "Sunday" : "neděle", @@ -130,20 +130,20 @@ "Thursday" : "čtvrtek", "Friday" : "pátek", "Saturday" : "sobota", - "Sun." : "Ne", - "Mon." : "Po", - "Tue." : "Út", - "Wed." : "St", - "Thu." : "Čt", - "Fri." : "Pá", - "Sat." : "So", - "Su" : "Ne", - "Mo" : "Po", - "Tu" : "Út", - "We" : "St", - "Th" : "Čt", - "Fr" : "Pá", - "Sa" : "So", + "Sun." : "ne", + "Mon." : "po", + "Tue." : "út", + "Wed." : "st", + "Thu." : "čt", + "Fri." : "pá", + "Sat." : "so", + "Su" : "ne", + "Mo" : "po", + "Tu" : "út", + "We" : "st", + "Th" : "čt", + "Fr" : "pá", + "Sa" : "so", "January" : "leden", "February" : "únor", "March" : "březen", @@ -156,18 +156,18 @@ "October" : "říjen", "November" : "listopad", "December" : "prosinec", - "Jan." : "leden", - "Feb." : "únor", - "Mar." : "březen", - "Apr." : "duben", - "May." : "květen", - "Jun." : "červen", - "Jul." : "červenec", - "Aug." : "srpen", - "Sep." : "září", - "Oct." : "říjen", + "Jan." : "led.", + "Feb." : "úno.", + "Mar." : "bře.", + "Apr." : "dub.", + "May." : "kvě.", + "Jun." : "čvn.", + "Jul." : "čvc.", + "Aug." : "srp.", + "Sep." : "zář.", + "Oct." : "říj.", "Nov." : "list.", - "Dec." : "prosinec", + "Dec." : "pro.", "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", and \"_.@-'\"" : "Pouze následující znaky jsou povoleny pro uživatelské jméno: „a-z“, „A-Z“, „0-9“, a „_.@-'“", "A valid username must be provided" : "Je třeba zadat platné uživatelské jméno", "Username contains whitespace at the beginning or at the end" : "Uživatelské jméno obsahuje mezery na svém začátku nebo konci", diff --git a/lib/l10n/eu.js b/lib/l10n/eu.js index 2febc17898d..7299122e532 100644 --- a/lib/l10n/eu.js +++ b/lib/l10n/eu.js @@ -118,6 +118,7 @@ OC.L10N.register( "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", + "File is currently busy, please try again later" : "Fitxategia lanpetuta dago, saiatu berriro geroago", "Can't read file" : "Ezin da fitxategia irakurri", "Application is not enabled" : "Aplikazioa ez dago gaituta", "Authentication error" : "Autentifikazio errorea", @@ -129,6 +130,7 @@ OC.L10N.register( "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.", + "Adjusting this setting in php.ini will make Nextcloud run again" : "Ezarpen hau php.ini fitxategian doitzen bada, Nextcloud berriro exekutatuko da", "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.", diff --git a/lib/l10n/eu.json b/lib/l10n/eu.json index a09a04fbb9c..034bbc306fe 100644 --- a/lib/l10n/eu.json +++ b/lib/l10n/eu.json @@ -116,6 +116,7 @@ "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", + "File is currently busy, please try again later" : "Fitxategia lanpetuta dago, saiatu berriro geroago", "Can't read file" : "Ezin da fitxategia irakurri", "Application is not enabled" : "Aplikazioa ez dago gaituta", "Authentication error" : "Autentifikazio errorea", @@ -127,6 +128,7 @@ "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.", + "Adjusting this setting in php.ini will make Nextcloud run again" : "Ezarpen hau php.ini fitxategian doitzen bada, Nextcloud berriro exekutatuko da", "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.", diff --git a/lib/l10n/lt_LT.js b/lib/l10n/lt_LT.js index 0b54d89dc42..f24fd6afc2c 100644 --- a/lib/l10n/lt_LT.js +++ b/lib/l10n/lt_LT.js @@ -20,6 +20,14 @@ OC.L10N.register( "Server version %s or higher is required." : "Reikalinga %s arba aukštesnė serverio versija ", "Server version %s or lower is required." : "Reikalinga %s arba žemesnė serverio versija. ", "Logged in user must be an admin" : "Prisijungęs naudotojas privalo būti administratoriumi", + "»%s« started remote wipe" : "»%s« pradėjo nuotolinių duomenų ištrynimą", + "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "Įrenginys ar programa »%s« pradėjo nuotolinių duomenų ištrynimo procesą. Procesui užsibaigus, gausite dar vieną el. laišką", + "»%s« finished remote wipe" : "»%s« užbaigė nuotolinių duomenų ištrynimą", + "Device or application »%s« has finished the remote wipe process." : "Įrenginys ar programa »%s« užbaigė nuotolinių duomenų ištrynimo procesą.", + "Remote wipe started" : "Nuotolinių duomenų ištrynimas pradėtas", + "A remote wipe was started on device %s" : "Nuotolinių duomenų ištrynimas buvo pradėtas įrenginyje %s", + "Remote wipe finished" : "Nuotolinių duomenų ištrynimas užbaigtas", + "The remote wipe on %s has finished" : "Nuotolinių duomenų ištrynimas ties %s yra užbaigtas", "Authentication" : "Tapatybės nustatymas", "Unknown filetype" : "Nežinomas failo tipas", "Invalid image" : "Neteisingas paveikslas", diff --git a/lib/l10n/lt_LT.json b/lib/l10n/lt_LT.json index aa820cc988b..125cd0ab0f5 100644 --- a/lib/l10n/lt_LT.json +++ b/lib/l10n/lt_LT.json @@ -18,6 +18,14 @@ "Server version %s or higher is required." : "Reikalinga %s arba aukštesnė serverio versija ", "Server version %s or lower is required." : "Reikalinga %s arba žemesnė serverio versija. ", "Logged in user must be an admin" : "Prisijungęs naudotojas privalo būti administratoriumi", + "»%s« started remote wipe" : "»%s« pradėjo nuotolinių duomenų ištrynimą", + "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "Įrenginys ar programa »%s« pradėjo nuotolinių duomenų ištrynimo procesą. Procesui užsibaigus, gausite dar vieną el. laišką", + "»%s« finished remote wipe" : "»%s« užbaigė nuotolinių duomenų ištrynimą", + "Device or application »%s« has finished the remote wipe process." : "Įrenginys ar programa »%s« užbaigė nuotolinių duomenų ištrynimo procesą.", + "Remote wipe started" : "Nuotolinių duomenų ištrynimas pradėtas", + "A remote wipe was started on device %s" : "Nuotolinių duomenų ištrynimas buvo pradėtas įrenginyje %s", + "Remote wipe finished" : "Nuotolinių duomenų ištrynimas užbaigtas", + "The remote wipe on %s has finished" : "Nuotolinių duomenų ištrynimas ties %s yra užbaigtas", "Authentication" : "Tapatybės nustatymas", "Unknown filetype" : "Nežinomas failo tipas", "Invalid image" : "Neteisingas paveikslas", diff --git a/lib/l10n/sl.js b/lib/l10n/sl.js index 79856e2a14a..b8c6733aee5 100644 --- a/lib/l10n/sl.js +++ b/lib/l10n/sl.js @@ -15,7 +15,7 @@ OC.L10N.register( "Social sharing bundle" : "Paket družbene izmenjave", "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.", + "%sbit or higher PHP required." : "Zahtevana je %s-bitna različica PHP 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.", @@ -69,15 +69,15 @@ OC.L10N.register( "Additional settings" : "Dodatne nastavitve", "Personal info" : "Osebni podatki", "Mobile & desktop" : "Mobilni in namizni dostop", - "%s enter the database username and name." : "%s - vnos uporabniškega imena in imena podatkovne zbirke.", + "%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 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.", + "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.", @@ -90,7 +90,7 @@ OC.L10N.register( "Open »%s«" : "Odpri »%s«", "You are not allowed to share %s" : "Omogočanje souporabe %s brez ustreznih dovoljenj ni mogoče.", "Expiration date is in the past" : "Datum preteka je že mimo!", - "Could not find category \"%s\"" : "Kategorije \"%s\" ni mogoče najti.", + "Could not find category \"%s\"" : "Kategorije »%s« ni mogoče najti.", "Sunday" : "nedelja", "Monday" : "ponedeljek", "Tuesday" : "torek", @@ -136,7 +136,7 @@ OC.L10N.register( "Oct." : "okt", "Nov." : "nov", "Dec." : "dec", - "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 \"_.@-'\"", + "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« in »_.@-«\".", "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.", "Username must not consist of dots only" : "Uporabniško ime ne sme biti zgolj iz pik", @@ -151,7 +151,7 @@ OC.L10N.register( "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 \"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.", @@ -159,8 +159,8 @@ OC.L10N.register( "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" : "Prilagoditev te nastavitve v php.ini vzpostavi ponovno delovanje okolja 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", + "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "Vrednost mbstring.func_overload je nastavljena na »%s« in ne na pričakovano vrednost »0«.", + "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Za rešitev težave je treba v datoteki php.ini nastaviti možnost <code>mbstring.func_overload</code> na <code>0</code>.", "libxml2 2.7.0 is at least required. Currently %s is installed." : "Različica knjižnice libxml2 mora biti 2.7.0 ali višja. 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." : " Kaže, da je PHP nastavljen tako, da odreže vrstične predmete docblock. To povzroči, da nekateri jedrni programi niso dosegljivi.", @@ -170,7 +170,7 @@ OC.L10N.register( "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\"", + "Check the value of \"datadirectory\" in your configuration" : "Med nastavitvami je treba preveriti 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", @@ -187,8 +187,8 @@ OC.L10N.register( "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", "Sharing %s failed, because you can not share with yourself" : "Nastavitev %s souporabe je spodletela, ker souporaba s samim seboj ni mogoča.", - "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.", + "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 povezave.", + "Sharing %s failed, because sharing with links is not allowed" : "Nastavljanje souporabe %s je spodletelo, ker souporaba s povezavo ni dovoljena.", "Not allowed to create a federated share with the same user" : "Ni dovoljeno ustvariti souporabe zveznega oblaka z istim uporabnikom", "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.", diff --git a/lib/l10n/sl.json b/lib/l10n/sl.json index 3df87011a92..e0319421631 100644 --- a/lib/l10n/sl.json +++ b/lib/l10n/sl.json @@ -13,7 +13,7 @@ "Social sharing bundle" : "Paket družbene izmenjave", "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.", + "%sbit or higher PHP required." : "Zahtevana je %s-bitna različica PHP 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.", @@ -67,15 +67,15 @@ "Additional settings" : "Dodatne nastavitve", "Personal info" : "Osebni podatki", "Mobile & desktop" : "Mobilni in namizni dostop", - "%s enter the database username and name." : "%s - vnos uporabniškega imena in imena podatkovne zbirke.", + "%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 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.", + "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.", @@ -88,7 +88,7 @@ "Open »%s«" : "Odpri »%s«", "You are not allowed to share %s" : "Omogočanje souporabe %s brez ustreznih dovoljenj ni mogoče.", "Expiration date is in the past" : "Datum preteka je že mimo!", - "Could not find category \"%s\"" : "Kategorije \"%s\" ni mogoče najti.", + "Could not find category \"%s\"" : "Kategorije »%s« ni mogoče najti.", "Sunday" : "nedelja", "Monday" : "ponedeljek", "Tuesday" : "torek", @@ -134,7 +134,7 @@ "Oct." : "okt", "Nov." : "nov", "Dec." : "dec", - "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 \"_.@-'\"", + "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« in »_.@-«\".", "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.", "Username must not consist of dots only" : "Uporabniško ime ne sme biti zgolj iz pik", @@ -149,7 +149,7 @@ "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 \"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.", @@ -157,8 +157,8 @@ "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" : "Prilagoditev te nastavitve v php.ini vzpostavi ponovno delovanje okolja 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", + "mbstring.func_overload is set to \"%s\" instead of the expected value \"0\"" : "Vrednost mbstring.func_overload je nastavljena na »%s« in ne na pričakovano vrednost »0«.", + "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "Za rešitev težave je treba v datoteki php.ini nastaviti možnost <code>mbstring.func_overload</code> na <code>0</code>.", "libxml2 2.7.0 is at least required. Currently %s is installed." : "Različica knjižnice libxml2 mora biti 2.7.0 ali višja. 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." : " Kaže, da je PHP nastavljen tako, da odreže vrstične predmete docblock. To povzroči, da nekateri jedrni programi niso dosegljivi.", @@ -168,7 +168,7 @@ "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\"", + "Check the value of \"datadirectory\" in your configuration" : "Med nastavitvami je treba preveriti 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", @@ -185,8 +185,8 @@ "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", "Sharing %s failed, because you can not share with yourself" : "Nastavitev %s souporabe je spodletela, ker souporaba s samim seboj ni mogoča.", - "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.", + "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 povezave.", + "Sharing %s failed, because sharing with links is not allowed" : "Nastavljanje souporabe %s je spodletelo, ker souporaba s povezavo ni dovoljena.", "Not allowed to create a federated share with the same user" : "Ni dovoljeno ustvariti souporabe zveznega oblaka z istim uporabnikom", "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.", diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php index 587178e8ede..9d210cd8419 100644 --- a/lib/private/AppFramework/Http/Request.php +++ b/lib/private/AppFramework/Http/Request.php @@ -853,6 +853,10 @@ class Request implements \ArrayAccess, \Countable, IRequest { * @return string Server host */ public function getInsecureServerHost(): string { + if ($this->fromTrustedProxy() && $this->getOverwriteHost() !== null) { + return $this->getOverwriteHost(); + } + $host = 'localhost'; if ($this->fromTrustedProxy() && isset($this->server['HTTP_X_FORWARDED_HOST'])) { if (strpos($this->server['HTTP_X_FORWARDED_HOST'], ',') !== false) { @@ -868,6 +872,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { $host = $this->server['SERVER_NAME']; } } + return $host; } diff --git a/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php b/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php new file mode 100644 index 00000000000..6719037b4a0 --- /dev/null +++ b/lib/private/Authentication/Exceptions/TokenPasswordExpiredException.php @@ -0,0 +1,29 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2019, 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\Exceptions; + +class TokenPasswordExpiredException extends ExpiredTokenException { + +} diff --git a/lib/private/Authentication/Token/Manager.php b/lib/private/Authentication/Token/Manager.php index ea94efce54d..0642d4426c4 100644 --- a/lib/private/Authentication/Token/Manager.php +++ b/lib/private/Authentication/Token/Manager.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace OC\Authentication\Token; +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Exceptions\PasswordlessTokenException; @@ -60,15 +61,29 @@ class Manager implements IProvider { 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 - ); + try { + return $this->publicKeyTokenProvider->generateToken( + $token, + $uid, + $loginName, + $password, + $name, + $type, + $remember + ); + } catch (UniqueConstraintViolationException $e) { + // It's rare, but if two requests of the same session (e.g. env-based SAML) + // try to create the session token they might end up here at the same time + // because we use the session ID as token and the db token is created anew + // with every request. + // + // If the UIDs match, then this should be fine. + $existing = $this->getToken($token); + if ($existing->getUID() !== $uid) { + throw new \Exception('Token conflict handled, but UIDs do not match. This should not happen', 0, $e); + } + return $existing; + } } /** diff --git a/lib/private/Authentication/Token/PublicKeyTokenProvider.php b/lib/private/Authentication/Token/PublicKeyTokenProvider.php index 624e2c0cadc..19987bec253 100644 --- a/lib/private/Authentication/Token/PublicKeyTokenProvider.php +++ b/lib/private/Authentication/Token/PublicKeyTokenProvider.php @@ -25,6 +25,7 @@ namespace OC\Authentication\Token; use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; +use OC\Authentication\Exceptions\TokenPasswordExpiredException; use OC\Authentication\Exceptions\PasswordlessTokenException; use OC\Authentication\Exceptions\WipeTokenException; use OC\Cache\CappedMemoryCache; @@ -108,6 +109,11 @@ class PublicKeyTokenProvider implements IProvider { throw new WipeTokenException($token); } + if ($token->getPasswordInvalid() === true) { + //The password is invalid we should throw an TokenPasswordExpiredException + throw new TokenPasswordExpiredException($token); + } + return $token; } @@ -126,6 +132,11 @@ class PublicKeyTokenProvider implements IProvider { throw new WipeTokenException($token); } + if ($token->getPasswordInvalid() === true) { + //The password is invalid we should throw an TokenPasswordExpiredException + throw new TokenPasswordExpiredException($token); + } + return $token; } diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php index 971b7025564..9de269224f5 100644 --- a/lib/private/Collaboration/Collaborators/UserPlugin.php +++ b/lib/private/Collaboration/Collaborators/UserPlugin.php @@ -71,7 +71,7 @@ class UserPlugin implements ISearchPlugin { foreach ($userGroups as $userGroup) { $usersTmp = $this->groupManager->displayNamesInGroup($userGroup, $search, $limit, $offset); foreach ($usersTmp as $uid => $userDisplayName) { - $users[$uid] = $userDisplayName; + $users[(string) $uid] = $userDisplayName; } } } else { @@ -80,7 +80,7 @@ class UserPlugin implements ISearchPlugin { foreach ($usersTmp as $user) { if ($user->isEnabled()) { // Don't keep deactivated users - $users[$user->getUID()] = $user->getDisplayName(); + $users[(string) $user->getUID()] = $user->getDisplayName(); } } } @@ -94,6 +94,7 @@ class UserPlugin implements ISearchPlugin { $foundUserById = false; $lowerSearch = strtolower($search); foreach ($users as $uid => $userDisplayName) { + $uid = (string) $uid; if (strtolower($uid) === $lowerSearch || strtolower($userDisplayName) === $lowerSearch) { if (strtolower($uid) === $lowerSearch) { $foundUserById = true; diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php index f9c6f4155a3..65e1d84bfb1 100644 --- a/lib/private/DB/Connection.php +++ b/lib/private/DB/Connection.php @@ -38,6 +38,7 @@ use Doctrine\DBAL\Driver; use Doctrine\DBAL\Exception\ConstraintViolationException; use Doctrine\DBAL\Platforms\MySqlPlatform; use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\TransactionIsolationLevel; use OC\DB\QueryBuilder\QueryBuilder; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; @@ -148,7 +149,7 @@ class Connection extends ReconnectWrapper implements IDBConnection { $this->adapter = new $params['adapter']($this); $this->tablePrefix = $params['tablePrefix']; - parent::setTransactionIsolation(parent::TRANSACTION_READ_COMMITTED); + $this->setTransactionIsolation(TransactionIsolationLevel::READ_COMMITTED); } /** diff --git a/lib/private/DirectEditing/Manager.php b/lib/private/DirectEditing/Manager.php new file mode 100644 index 00000000000..26adad9e572 --- /dev/null +++ b/lib/private/DirectEditing/Manager.php @@ -0,0 +1,236 @@ +<?php +/** + * @copyright Copyright (c) 2019 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 OC\DirectEditing; + +use Doctrine\DBAL\FetchMode; +use OCP\AppFramework\Http\NotFoundResponse; +use OCP\AppFramework\Http\Response; +use OCP\AppFramework\Http\TemplateResponse; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\DirectEditing\ACreateFromTemplate; +use OCP\DirectEditing\IEditor; +use \OCP\DirectEditing\IManager; +use OCP\DirectEditing\IToken; +use OCP\DirectEditing\RegisterDirectEditorEvent; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\File; +use OCP\Files\IRootFolder; +use OCP\Files\NotFoundException; +use OCP\IDBConnection; +use OCP\IUserSession; +use OCP\Security\ISecureRandom; +use OCP\Share\IShare; + +class Manager implements IManager { + + private const TOKEN_CLEANUP_TIME = 12 * 60 * 60 ; + + public const TABLE_TOKENS = 'direct_edit'; + + /** @var IEditor[] */ + private $editors = []; + + /** @var IDBConnection */ + private $connection; + /** + * @var ISecureRandom + */ + private $random; + private $userId; + private $rootFolder; + + public function __construct( + ISecureRandom $random, + IDBConnection $connection, + IUserSession $userSession, + IRootFolder $rootFolder + ) { + $this->random = $random; + $this->connection = $connection; + $this->userId = $userSession->getUser() ? $userSession->getUser()->getUID() : null; + $this->rootFolder = $rootFolder; + } + + public function registerDirectEditor(IEditor $directEditor): void { + $this->editors[$directEditor->getId()] = $directEditor; + } + + public function getEditors(): array { + return $this->editors; + } + + public function getTemplates(string $editor, string $type): array { + if (!array_key_exists($editor, $this->editors)) { + throw new \RuntimeException('No matching editor found'); + } + $templates = []; + foreach ($this->editors[$editor]->getCreators() as $creator) { + if ($creator instanceof ACreateFromTemplate && $creator->getId() === $type) { + $templates = $creator->getTemplates(); + } + } + $return = []; + $return['templates'] = $templates; + return $return; + } + + public function create(string $path, string $editorId, string $creatorId, $templateId = null): string { + $userFolder = $this->rootFolder->getUserFolder($this->userId); + $file = $userFolder->newFile($path); + $editor = $this->getEditor($editorId); + $creators = $editor->getCreators(); + foreach ($creators as $creator) { + if ($creator->getId() === $creatorId) { + $creator->create($file, $creatorId, $templateId); + return $this->createToken($editorId, $file); + } + } + throw new \RuntimeException('No creator found'); + } + + public function open(int $fileId, string $editorId = null): string { + $file = $this->rootFolder->getUserFolder($this->userId)->getById($fileId); + if (count($file) === 0 || !($file[0] instanceof File) || $file === null) { + throw new NotFoundException(); + } + /** @var File $file */ + $file = $file[0]; + + if ($editorId === null) { + $editorId = $this->findEditorForFile($file); + } + + return $this->createToken($editorId, $file); + } + + private function findEditorForFile(File $file) { + foreach ($this->editors as $editor) { + if (in_array($file->getMimeType(), $editor->getMimetypes())) { + return $editor->getId(); + } + } + throw new \RuntimeException('No default editor found for files mimetype'); + } + + public function edit(string $token): Response { + try { + /** @var IEditor $editor */ + $tokenObject = $this->getToken($token); + if ($tokenObject->hasBeenAccessed()) { + throw new \RuntimeException('Token has already been used and can only be used for followup requests'); + } + $editor = $this->getEditor($tokenObject->getEditor()); + $this->accessToken($token); + + } catch (\Throwable $throwable) { + $this->invalidateToken($token); + return new NotFoundResponse(); + } + return $editor->open($tokenObject); + } + + public function editSecure(File $file, string $editorId): TemplateResponse { + // TODO: Implementation in follow up + } + + private function getEditor($editorId): IEditor { + if (!array_key_exists($editorId, $this->editors)) { + throw new \RuntimeException('No editor found'); + } + return $this->editors[$editorId]; + } + + public function getToken(string $token): IToken { + $query = $this->connection->getQueryBuilder(); + $query->select('*')->from(self::TABLE_TOKENS) + ->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR))); + $result = $query->execute(); + if ($tokenRow = $result->fetch(FetchMode::ASSOCIATIVE)) { + return new Token($this, $tokenRow); + } + throw new \RuntimeException('Failed to validate the token'); + } + + public function cleanup(): int { + $query = $this->connection->getQueryBuilder(); + $query->delete(self::TABLE_TOKENS) + ->where($query->expr()->lt('timestamp', $query->createNamedParameter(time() - self::TOKEN_CLEANUP_TIME))); + return $query->execute(); + } + + public function refreshToken(string $token): bool { + $query = $this->connection->getQueryBuilder(); + $query->update(self::TABLE_TOKENS) + ->set('timestamp', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT)) + ->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR))); + $result = $query->execute(); + return $result !== 0; + } + + + public function invalidateToken(string $token): bool { + $query = $this->connection->getQueryBuilder(); + $query->delete(self::TABLE_TOKENS) + ->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR))); + $result = $query->execute(); + return $result !== 0; + } + + public function accessToken(string $token): bool { + $query = $this->connection->getQueryBuilder(); + $query->update(self::TABLE_TOKENS) + ->set('accessed', $query->createNamedParameter(true, IQueryBuilder::PARAM_BOOL)) + ->set('timestamp', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT)) + ->where($query->expr()->eq('token', $query->createNamedParameter($token, IQueryBuilder::PARAM_STR))); + $result = $query->execute(); + return $result !== 0; + } + + public function invokeTokenScope($userId): void { + \OC_User::setIncognitoMode(true); + \OC_User::setUserId($userId); + } + + public function createToken($editorId, File $file, IShare $share = null): string { + $token = $this->random->generate(64, ISecureRandom::CHAR_HUMAN_READABLE); + $query = $this->connection->getQueryBuilder(); + $query->insert(self::TABLE_TOKENS) + ->values([ + 'token' => $query->createNamedParameter($token), + 'editor_id' => $query->createNamedParameter($editorId), + 'file_id' => $query->createNamedParameter($file->getId()), + 'user_id' => $query->createNamedParameter($this->userId), + 'share_id' => $query->createNamedParameter($share !== null ? $share->getId(): null), + 'timestamp' => $query->createNamedParameter(time()) + ]); + $query->execute(); + return $token; + } + + public function getFileForToken($userId, $fileId) { + $userFolder = $this->rootFolder->getUserFolder($userId); + return $userFolder->getById($fileId)[0]; + } + +} diff --git a/lib/private/DirectEditing/Token.php b/lib/private/DirectEditing/Token.php new file mode 100644 index 00000000000..148621a2cf3 --- /dev/null +++ b/lib/private/DirectEditing/Token.php @@ -0,0 +1,76 @@ +<?php +/** + * @copyright Copyright (c) 2019 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 OC\DirectEditing; + + +use OCP\DirectEditing\IToken; +use OCP\Files\File; + +class Token implements IToken { + + /** @var Manager */ + private $manager; + private $data; + + public function __construct(Manager $manager, $data) { + $this->manager = $manager; + $this->data = $data; + } + + public function extend(): void { + $this->manager->refreshToken($this->data['token']); + } + + public function invalidate(): void { + $this->manager->invalidateToken($this->data['token']); + } + + public function getFile(): File { + if ($this->data['share_id'] !== null) { + return $this->manager->getShareForToken($this->data['share_id']); + } + return $this->manager->getFileForToken($this->data['user_id'], $this->data['file_id']); + } + + public function getToken(): string { + return $this->data['token']; + } + + public function useTokenScope(): void { + $this->manager->invokeTokenScope($this->data['user_id']); + } + + public function hasBeenAccessed(): bool { + return (bool) $this->data['accessed']; + } + + public function getEditor(): string { + return $this->data['editor_id']; + } + + public function getUser(): string { + return $this->data['user_id']; + } + +} diff --git a/lib/private/Files/Node/File.php b/lib/private/Files/Node/File.php index b504c7a29da..e4669f70709 100644 --- a/lib/private/Files/Node/File.php +++ b/lib/private/Files/Node/File.php @@ -28,6 +28,7 @@ namespace OC\Files\Node; use OCP\Files\GenericFileException; use OCP\Files\NotPermittedException; +use OCP\Lock\LockedException; class File extends Node implements \OCP\Files\File { /** @@ -42,7 +43,8 @@ class File extends Node implements \OCP\Files\File { /** * @return string - * @throws \OCP\Files\NotPermittedException + * @throws NotPermittedException + * @throws LockedException */ public function getContent() { if ($this->checkPermissions(\OCP\Constants::PERMISSION_READ)) { @@ -57,8 +59,9 @@ class File extends Node implements \OCP\Files\File { /** * @param string|resource $data - * @throws \OCP\Files\NotPermittedException + * @throws NotPermittedException * @throws \OCP\Files\GenericFileException + * @throws LockedException */ public function putContent($data) { if ($this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE)) { @@ -76,7 +79,8 @@ class File extends Node implements \OCP\Files\File { /** * @param string $mode * @return resource - * @throws \OCP\Files\NotPermittedException + * @throws NotPermittedException + * @throws LockedException */ public function fopen($mode) { $preHooks = array(); @@ -113,6 +117,11 @@ class File extends Node implements \OCP\Files\File { } } + /** + * @throws NotPermittedException + * @throws \OCP\Files\InvalidPathException + * @throws \OCP\Files\NotFoundException + */ public function delete() { if ($this->checkPermissions(\OCP\Constants::PERMISSION_DELETE)) { $this->sendHooks(array('preDelete')); diff --git a/lib/private/Files/Node/HookConnector.php b/lib/private/Files/Node/HookConnector.php index b792b584077..417bb4980ee 100644 --- a/lib/private/Files/Node/HookConnector.php +++ b/lib/private/Files/Node/HookConnector.php @@ -24,10 +24,10 @@ namespace OC\Files\Node; use OC\Files\Filesystem; use OC\Files\View; +use OCP\EventDispatcher\GenericEvent; use OCP\Files\FileInfo; use OCP\Util; use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\GenericEvent; class HookConnector { /** diff --git a/lib/private/Files/Node/Node.php b/lib/private/Files/Node/Node.php index 95d16cf5c99..7f50524f28d 100644 --- a/lib/private/Files/Node/Node.php +++ b/lib/private/Files/Node/Node.php @@ -33,6 +33,7 @@ use OCP\Files\FileInfo; use OCP\Files\InvalidPathException; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; +use OCP\Lock\LockedException; use Symfony\Component\EventDispatcher\GenericEvent; // FIXME: this class really should be abstract @@ -75,6 +76,7 @@ class Node implements \OCP\Files\Node { * * @param string $path path * @return string non-existing node class + * @throws \Exception */ protected function createNonExistingNode($path) { throw new \Exception('Must be implemented by subclasses'); @@ -117,6 +119,8 @@ class Node implements \OCP\Files\Node { /** * @param int $permissions * @return bool + * @throws InvalidPathException + * @throws NotFoundException */ protected function checkPermissions($permissions) { return ($this->getPermissions() & $permissions) === $permissions; @@ -127,7 +131,9 @@ class Node implements \OCP\Files\Node { /** * @param int $mtime - * @throws \OCP\Files\NotPermittedException + * @throws InvalidPathException + * @throws NotFoundException + * @throws NotPermittedException */ public function touch($mtime = null) { if ($this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE)) { @@ -366,7 +372,7 @@ class Node implements \OCP\Files\Node { /** * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE - * @throws \OCP\Lock\LockedException + * @throws LockedException */ public function lock($type) { $this->view->lockFile($this->path, $type); @@ -374,7 +380,7 @@ class Node implements \OCP\Files\Node { /** * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE - * @throws \OCP\Lock\LockedException + * @throws LockedException */ public function changeLock($type) { $this->view->changeLock($this->path, $type); @@ -382,7 +388,7 @@ class Node implements \OCP\Files\Node { /** * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE - * @throws \OCP\Lock\LockedException + * @throws LockedException */ public function unlock($type) { $this->view->unlockFile($this->path, $type); @@ -390,8 +396,10 @@ class Node implements \OCP\Files\Node { /** * @param string $targetPath - * @throws \OCP\Files\NotPermittedException if copy not allowed or failed * @return \OC\Files\Node\Node + * @throws InvalidPathException + * @throws NotFoundException + * @throws NotPermittedException if copy not allowed or failed */ public function copy($targetPath) { $targetPath = $this->normalizePath($targetPath); @@ -414,8 +422,11 @@ class Node implements \OCP\Files\Node { /** * @param string $targetPath - * @throws \OCP\Files\NotPermittedException if move not allowed or failed * @return \OC\Files\Node\Node + * @throws InvalidPathException + * @throws NotFoundException + * @throws NotPermittedException if move not allowed or failed + * @throws LockedException */ public function move($targetPath) { $targetPath = $this->normalizePath($targetPath); diff --git a/lib/private/Files/Storage/DAV.php b/lib/private/Files/Storage/DAV.php index 69e6f309c31..ca96e6b7434 100644 --- a/lib/private/Files/Storage/DAV.php +++ b/lib/private/Files/Storage/DAV.php @@ -34,7 +34,6 @@ namespace OC\Files\Storage; use Exception; -use GuzzleHttp\Exception\RequestException; use Icewind\Streams\CallbackWrapper; use Icewind\Streams\IteratorDirectory; use OC\Files\Filesystem; @@ -45,6 +44,8 @@ use OCP\Files\FileInfo; use OCP\Files\ForbiddenException; use OCP\Files\StorageInvalidException; use OCP\Files\StorageNotAvailableException; +use OCP\Http\Client\IClientService; +use OCP\ICertificateManager; use OCP\ILogger; use OCP\Util; use Psr\Http\Message\ResponseInterface; @@ -79,8 +80,10 @@ class DAV extends Common { protected $client; /** @var ArrayCache */ protected $statCache; - /** @var \OCP\Http\Client\IClientService */ + /** @var IClientService */ protected $httpClientService; + /** @var ICertificateManager */ + protected $certManager; /** * @param array $params @@ -111,13 +114,9 @@ class DAV extends Common { } if ($this->secure === true) { // inject mock for testing - $certManager = \OC::$server->getCertificateManager(); - if (is_null($certManager)) { //no user - $certManager = \OC::$server->getCertificateManager(null); - } - $certPath = $certManager->getAbsoluteBundlePath(); - if (file_exists($certPath)) { - $this->certPath = $certPath; + $this->certManager = \OC::$server->getCertificateManager(); + if (is_null($this->certManager)) { //no user + $this->certManager = \OC::$server->getCertificateManager(null); } } $this->root = $params['root'] ?? '/'; @@ -150,8 +149,15 @@ class DAV extends Common { $this->client = new Client($settings); $this->client->setThrowExceptions(true); - if ($this->secure === true && $this->certPath) { - $this->client->addCurlSetting(CURLOPT_CAINFO, $this->certPath); + + if($this->secure === true) { + $certPath = $this->certManager->getAbsoluteBundlePath(); + if (file_exists($certPath)) { + $this->certPath = $certPath; + } + if ($this->certPath) { + $this->client->addCurlSetting(CURLOPT_CAINFO, $this->certPath); + } } } diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php index e9a9e8e9885..aade0cdaf25 100644 --- a/lib/private/Files/Storage/Local.php +++ b/lib/private/Files/Storage/Local.php @@ -424,12 +424,26 @@ class Local extends \OC\Files\Storage\Common { public function getETag($path) { if ($this->is_file($path)) { $stat = $this->stat($path); - return md5( - $stat['mtime'] . - $stat['ino'] . - $stat['dev'] . - $stat['size'] - ); + + if ($stat === false) { + return md5(''); + } + + $toHash = ''; + if (isset($stat['mtime'])) { + $toHash .= $stat['mtime']; + } + if (isset($stat['ino'])) { + $toHash .= $stat['ino']; + } + if (isset($stat['dev'])) { + $toHash .= $stat['dev']; + } + if (isset($stat['size'])) { + $toHash .= $stat['size']; + } + + return md5($toHash); } else { return parent::getETag($path); } diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php index 4f4c4b90f2c..ed962bde1a4 100644 --- a/lib/private/Files/View.php +++ b/lib/private/Files/View.php @@ -589,6 +589,7 @@ class View { /** * @param string $path * @return mixed + * @throws LockedException */ public function file_get_contents($path) { return $this->basicOperation('file_get_contents', $path, array('read')); @@ -640,7 +641,7 @@ class View { * @param string $path * @param string|resource $data * @return bool|mixed - * @throws \Exception + * @throws LockedException */ public function file_put_contents($path, $data) { if (is_resource($data)) { //not having to deal with streams in file_put_contents makes life easier @@ -739,6 +740,7 @@ class View { * @param string $path2 target path * * @return bool|mixed + * @throws LockedException */ public function rename($path1, $path2) { $absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1)); @@ -962,6 +964,7 @@ class View { * @param string $path * @param string $mode 'r' or 'w' * @return resource + * @throws LockedException */ public function fopen($path, $mode) { $mode = str_replace('b', '', $mode); // the binary flag is a windows only feature which we do not support @@ -1117,7 +1120,7 @@ class View { * @param array $hooks (optional) * @param mixed $extraParam (optional) * @return mixed - * @throws \Exception + * @throws LockedException * * This method takes requests for basic filesystem functions (e.g. reading & writing * files), processes hooks and proxies, sanitises paths, and finally passes them on to @@ -1919,7 +1922,7 @@ class View { * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage * * @return bool False if the path is excluded from locking, true otherwise - * @throws \OCP\Lock\LockedException if the path is already locked + * @throws LockedException if the path is already locked */ private function lockPath($path, $type, $lockMountPoint = false) { $absolutePath = $this->getAbsolutePath($path); @@ -1939,9 +1942,9 @@ class View { $this->lockingProvider ); } - } catch (\OCP\Lock\LockedException $e) { + } catch (LockedException $e) { // rethrow with the a human-readable path - throw new \OCP\Lock\LockedException( + throw new LockedException( $this->getPathRelativeToFiles($absolutePath), $e ); @@ -1959,7 +1962,7 @@ class View { * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage * * @return bool False if the path is excluded from locking, true otherwise - * @throws \OCP\Lock\LockedException if the path is already locked + * @throws LockedException if the path is already locked */ public function changeLock($path, $type, $lockMountPoint = false) { $path = Filesystem::normalizePath($path); @@ -1980,15 +1983,15 @@ class View { $this->lockingProvider ); } - } catch (\OCP\Lock\LockedException $e) { + } catch (LockedException $e) { try { // rethrow with the a human-readable path - throw new \OCP\Lock\LockedException( + throw new LockedException( $this->getPathRelativeToFiles($absolutePath), $e ); } catch (\InvalidArgumentException $e) { - throw new \OCP\Lock\LockedException( + throw new LockedException( $absolutePath, $e ); @@ -2007,6 +2010,7 @@ class View { * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage * * @return bool False if the path is excluded from locking, true otherwise + * @throws LockedException */ private function unlockPath($path, $type, $lockMountPoint = false) { $absolutePath = $this->getAbsolutePath($path); @@ -2038,6 +2042,7 @@ class View { * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage * * @return bool False if the path is excluded from locking, true otherwise + * @throws LockedException */ public function lockFile($path, $type, $lockMountPoint = false) { $absolutePath = $this->getAbsolutePath($path); @@ -2064,6 +2069,7 @@ class View { * @param bool $lockMountPoint true to lock the mount point, false to lock the attached mount/storage * * @return bool False if the path is excluded from locking, true otherwise + * @throws LockedException */ public function unlockFile($path, $type, $lockMountPoint = false) { $absolutePath = $this->getAbsolutePath($path); diff --git a/lib/private/Group/Manager.php b/lib/private/Group/Manager.php index 0e51b4ec2cc..dc4a7fbd11c 100644 --- a/lib/private/Group/Manager.php +++ b/lib/private/Group/Manager.php @@ -392,7 +392,7 @@ class Manager extends PublicEmitter implements IGroupManager { $matchingUsers = []; foreach ($groupUsers as $groupUser) { - $matchingUsers[$groupUser->getUID()] = $groupUser->getDisplayName(); + $matchingUsers[(string) $groupUser->getUID()] = $groupUser->getDisplayName(); } return $matchingUsers; } diff --git a/lib/private/Log/ExceptionSerializer.php b/lib/private/Log/ExceptionSerializer.php index 8cfdb57b225..a3b855aea26 100644 --- a/lib/private/Log/ExceptionSerializer.php +++ b/lib/private/Log/ExceptionSerializer.php @@ -92,7 +92,9 @@ class ExceptionSerializer { ]; private function editTrace(array &$sensitiveValues, array $traceLine): array { - $sensitiveValues = array_merge($sensitiveValues, $traceLine['args']); + if (isset($traceLine['args'])) { + $sensitiveValues = array_merge($sensitiveValues, $traceLine['args']); + } $traceLine['args'] = ['*** sensitive parameters replaced ***']; return $traceLine; } diff --git a/lib/private/Server.php b/lib/private/Server.php index b4af17ba288..fa2a521b6b1 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -199,6 +199,8 @@ class Server extends ServerContainer implements IServerContainer { $this->registerAlias(\OCP\Contacts\IManager::class, \OC\ContactsManager::class); $this->registerAlias('ContactsManager', \OCP\Contacts\IManager::class); + $this->registerAlias(\OCP\DirectEditing\IManager::class, \OC\DirectEditing\Manager::class); + $this->registerAlias(IActionFactory::class, ActionFactory::class); @@ -315,9 +317,6 @@ class Server extends ServerContainer implements IServerContainer { }); $this->registerAlias('LazyRootFolder', \OCP\Files\IRootFolder::class); - $this->registerService(\OC\User\Manager::class, function (Server $c) { - return new \OC\User\Manager($c->getConfig(), $c->getEventDispatcher()); - }); $this->registerAlias('UserManager', \OC\User\Manager::class); $this->registerAlias(\OCP\IUserManager::class, \OC\User\Manager::class); diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php index a5ffa9e0f1e..1205cb81525 100644 --- a/lib/private/Settings/Manager.php +++ b/lib/private/Settings/Manager.php @@ -348,7 +348,7 @@ class Manager implements IManager { } $sections = [ - 0 => [new Section('personal-info', $this->l->t('Personal info'), 0, $this->url->imagePath('core', 'actions/info.svg'))], + 0 => [new Section('personal-info', $this->l->t('Personal info'), 0, $this->url->imagePath('core', 'actions/user.svg'))], 5 => [new Section('security', $this->l->t('Security'), 0, $this->url->imagePath('settings', 'password.svg'))], 15 => [new Section('sync-clients', $this->l->t('Mobile & desktop'), 0, $this->url->imagePath('core', 'clients/phone.svg'))], ]; diff --git a/lib/private/Setup.php b/lib/private/Setup.php index 266c70846c6..4ebd5618189 100644 --- a/lib/private/Setup.php +++ b/lib/private/Setup.php @@ -49,6 +49,7 @@ use OC\Authentication\Token\DefaultTokenCleanupJob; use OC\Authentication\Token\DefaultTokenProvider; use OC\Log\Rotate; use OC\Preview\BackgroundCleanupJob; +use OCP\AppFramework\Utility\ITimeFactory; use OCP\Defaults; use OCP\IGroup; use OCP\IL10N; @@ -421,6 +422,9 @@ class Setup { $userSession->login($username, $password); $userSession->createSessionToken($request, $userSession->getUser()->getUID(), $username, $password); + $session = $userSession->getSession(); + $session->set('last-password-confirm', \OC::$server->query(ITimeFactory::class)->getTime()); + // Set email for admin if (!empty($options['adminemail'])) { $config->setUserValue($user->getUID(), 'settings', 'email', $options['adminemail']); diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php index c25a7b03d5c..152e5d55394 100644 --- a/lib/private/Share20/DefaultShareProvider.php +++ b/lib/private/Share20/DefaultShareProvider.php @@ -144,9 +144,19 @@ class DefaultShareProvider implements IShareProvider { //Set the UID of the user we share with $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith())); $qb->setValue('accepted', $qb->createNamedParameter(IShare::STATUS_PENDING)); + + //If an expiration date is set store it + if ($share->getExpirationDate() !== null) { + $qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime')); + } } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { //Set the GID of the group we share with $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith())); + + //If an expiration date is set store it + if ($share->getExpirationDate() !== null) { + $qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime')); + } } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { //set label for public link $qb->setValue('label', $qb->createNamedParameter($share->getLabel())); diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index d9809fd128a..db9c704871d 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -55,6 +55,7 @@ use OCP\IUser; use OCP\IUserManager; use OCP\L10N\IFactory; use OCP\Mail\IMailer; +use OCP\Security\Events\ValidatePasswordPolicyEvent; use OCP\Security\IHasher; use OCP\Security\ISecureRandom; use OCP\Share; @@ -191,8 +192,7 @@ class Manager implements IManager { // Let others verify the password try { - $event = new GenericEvent($password); - $this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event); + $this->eventDispatcher->dispatch(new ValidatePasswordPolicyEvent($password)); } catch (HintException $e) { throw new \Exception($e->getHint()); } @@ -360,6 +360,77 @@ class Manager implements IManager { * @throws \InvalidArgumentException * @throws \Exception */ + protected function validateExpirationDateInternal(\OCP\Share\IShare $share) { + $expirationDate = $share->getExpirationDate(); + + if ($expirationDate !== null) { + //Make sure the expiration date is a date + $expirationDate->setTime(0, 0, 0); + + $date = new \DateTime(); + $date->setTime(0, 0, 0); + if ($date >= $expirationDate) { + $message = $this->l->t('Expiration date is in the past'); + throw new GenericShareException($message, $message, 404); + } + } + + // If expiredate is empty set a default one if there is a default + $fullId = null; + try { + $fullId = $share->getFullId(); + } catch (\UnexpectedValueException $e) { + // This is a new share + } + + if ($fullId === null && $expirationDate === null && $this->shareApiInternalDefaultExpireDate()) { + $expirationDate = new \DateTime(); + $expirationDate->setTime(0,0,0); + $expirationDate->add(new \DateInterval('P'.$this->shareApiInternalDefaultExpireDays().'D')); + } + + // If we enforce the expiration date check that is does not exceed + if ($this->shareApiInternalDefaultExpireDateEnforced()) { + if ($expirationDate === null) { + throw new \InvalidArgumentException('Expiration date is enforced'); + } + + $date = new \DateTime(); + $date->setTime(0, 0, 0); + $date->add(new \DateInterval('P' . $this->shareApiInternalDefaultExpireDays() . 'D')); + if ($date < $expirationDate) { + $message = $this->l->t('Can’t set expiration date more than %s days in the future', [$this->shareApiInternalDefaultExpireDays()]); + throw new GenericShareException($message, $message, 404); + } + } + + $accepted = true; + $message = ''; + \OCP\Util::emitHook('\OC\Share', 'verifyExpirationDate', [ + 'expirationDate' => &$expirationDate, + 'accepted' => &$accepted, + 'message' => &$message, + 'passwordSet' => $share->getPassword() !== null, + ]); + + if (!$accepted) { + throw new \Exception($message); + } + + $share->setExpirationDate($expirationDate); + + return $share; + } + + /** + * Validate if the expiration date fits the system settings + * + * @param \OCP\Share\IShare $share The share to validate the expiration date of + * @return \OCP\Share\IShare The modified share object + * @throws GenericShareException + * @throws \InvalidArgumentException + * @throws \Exception + */ protected function validateExpirationDate(\OCP\Share\IShare $share) { $expirationDate = $share->getExpirationDate(); @@ -636,8 +707,16 @@ class Manager implements IManager { //Verify share type if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { $this->userCreateChecks($share); + + //Verify the expiration date + $share = $this->validateExpirationDateInternal($share); + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { $this->groupCreateChecks($share); + + //Verify the expiration date + $share = $this->validateExpirationDateInternal($share); + } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { $this->linkCreateChecks($share); $this->setLinkParent($share); @@ -653,7 +732,7 @@ class Manager implements IManager { ); //Verify the expiration date - $this->validateExpirationDate($share); + $share = $this->validateExpirationDate($share); //Verify the password $this->verifyPassword($share->getPassword()); @@ -850,8 +929,20 @@ class Manager implements IManager { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { $this->userCreateChecks($share); + + if ($share->getExpirationDate() != $originalShare->getExpirationDate()) { + //Verify the expiration date + $this->validateExpirationDate($share); + $expirationDateUpdated = true; + } } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { $this->groupCreateChecks($share); + + if ($share->getExpirationDate() != $originalShare->getExpirationDate()) { + //Verify the expiration date + $this->validateExpirationDate($share); + $expirationDateUpdated = true; + } } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { $this->linkCreateChecks($share); @@ -1575,7 +1666,7 @@ class Manager implements IManager { } /** - * Is default expire date enabled + * Is default link expire date enabled * * @return bool */ @@ -1584,7 +1675,7 @@ class Manager implements IManager { } /** - * Is default expire date enforced + * Is default link expire date enforced *` * @return bool */ @@ -1593,9 +1684,9 @@ class Manager implements IManager { $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes'; } + /** - * Number of default expire days - *shareApiLinkAllowPublicUpload + * Number of default link expire days * @return int */ public function shareApiLinkDefaultExpireDays() { @@ -1603,6 +1694,34 @@ class Manager implements IManager { } /** + * Is default internal expire date enabled + * + * @return bool + */ + public function shareApiInternalDefaultExpireDate(): bool { + return $this->config->getAppValue('core', 'shareapi_default_internal_expire_date', 'no') === 'yes'; + } + + /** + * Is default expire date enforced + *` + * @return bool + */ + public function shareApiInternalDefaultExpireDateEnforced(): bool { + return $this->shareApiInternalDefaultExpireDate() && + $this->config->getAppValue('core', 'shareapi_enforce_internal_expire_date', 'no') === 'yes'; + } + + + /** + * Number of default expire days + * @return int + */ + public function shareApiInternalDefaultExpireDays(): int { + return (int)$this->config->getAppValue('core', 'shareapi_internal_expire_after_n_days', '7'); + } + + /** * Allow public upload on link shares * * @return bool diff --git a/lib/private/Template/JSConfigHelper.php b/lib/private/Template/JSConfigHelper.php index df5eda9121b..065bf2545e0 100644 --- a/lib/private/Template/JSConfigHelper.php +++ b/lib/private/Template/JSConfigHelper.php @@ -149,6 +149,13 @@ class JSConfigHelper { } $outgoingServer2serverShareEnabled = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes'; + $defaultInternalExpireDateEnabled = $this->config->getAppValue('core', 'shareapi_default_internal_expire_date', 'no') === 'yes'; + $defaultInternalExpireDate = $defaultInternalExpireDateEnforced = null; + if ($defaultInternalExpireDateEnabled) { + $defaultInternalExpireDate = (int) $this->config->getAppValue('core', 'shareapi_internal_expire_after_n_days', '7'); + $defaultInternalExpireDateEnforced = $this->config->getAppValue('core', 'shareapi_internal_enforce_expire_date', 'no') === 'yes'; + } + $countOfDataLocation = 0; $dataLocation = str_replace(\OC::$SERVERROOT .'/', '', $this->config->getSystemValue('datadirectory', ''), $countOfDataLocation); if($countOfDataLocation !== 1 || !$this->groupManager->isAdmin($uid)) { @@ -255,7 +262,10 @@ class JSConfigHelper { 'resharingAllowed' => \OC\Share\Share::isResharingAllowed(), 'remoteShareAllowed' => $outgoingServer2serverShareEnabled, 'federatedCloudShareDoc' => $this->urlGenerator->linkToDocs('user-sharing-federated'), - 'allowGroupSharing' => \OC::$server->getShareManager()->allowGroupSharing() + 'allowGroupSharing' => \OC::$server->getShareManager()->allowGroupSharing(), + 'defaultInternalExpireDateEnabled' => $defaultInternalExpireDateEnabled, + 'defaultInternalExpireDate' => $defaultInternalExpireDate, + 'defaultInternalExpireDateEnforced' => $defaultInternalExpireDateEnforced, ] ]), "_theme" => json_encode([ diff --git a/lib/private/URLGenerator.php b/lib/private/URLGenerator.php index 167690f3a6e..1fb69031f03 100644 --- a/lib/private/URLGenerator.php +++ b/lib/private/URLGenerator.php @@ -94,8 +94,9 @@ class URLGenerator implements IURLGenerator { public function linkToOCSRouteAbsolute(string $routeName, array $arguments = []): string { $route = \OC::$server->getRouter()->generate('ocs.'.$routeName, $arguments, false); - if (strpos($route, '/index.php') === 0) { - $route = substr($route, 10); + $indexPhpPos = strpos($route, '/index.php/'); + if ($indexPhpPos !== false) { + $route = substr($route, $indexPhpPos + 10); } $route = substr($route, 7); diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php index 23dbe8c2334..a4c35deb2b8 100644 --- a/lib/private/User/Database.php +++ b/lib/private/User/Database.php @@ -58,7 +58,9 @@ declare(strict_types=1); namespace OC\User; use OC\Cache\CappedMemoryCache; +use OCP\EventDispatcher\IEventDispatcher; use OCP\IDBConnection; +use OCP\Security\Events\ValidatePasswordPolicyEvent; use OCP\User\Backend\ABackend; use OCP\User\Backend\ICheckPasswordBackend; use OCP\User\Backend\ICountUsersBackend; @@ -68,7 +70,6 @@ use OCP\User\Backend\IGetHomeBackend; use OCP\User\Backend\IGetRealUIDBackend; use OCP\User\Backend\ISetDisplayNameBackend; use OCP\User\Backend\ISetPasswordBackend; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\GenericEvent; /** @@ -86,7 +87,7 @@ class Database extends ABackend /** @var CappedMemoryCache */ private $cache; - /** @var EventDispatcherInterface */ + /** @var IEventDispatcher */ private $eventDispatcher; /** @var IDBConnection */ @@ -98,13 +99,13 @@ class Database extends ABackend /** * \OC\User\Database constructor. * - * @param EventDispatcherInterface $eventDispatcher + * @param IEventDispatcher $eventDispatcher * @param string $table */ public function __construct($eventDispatcher = null, $table = 'users') { $this->cache = new CappedMemoryCache(); $this->table = $table; - $this->eventDispatcher = $eventDispatcher ? $eventDispatcher : \OC::$server->getEventDispatcher(); + $this->eventDispatcher = $eventDispatcher ? $eventDispatcher : \OC::$server->query(IEventDispatcher::class); } /** @@ -130,8 +131,7 @@ class Database extends ABackend $this->fixDI(); if (!$this->userExists($uid)) { - $event = new GenericEvent($password); - $this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event); + $this->eventDispatcher->dispatchTyped(new ValidatePasswordPolicyEvent($password)); $qb = $this->dbConn->getQueryBuilder(); $qb->insert($this->table) @@ -199,8 +199,7 @@ class Database extends ABackend $this->fixDI(); if ($this->userExists($uid)) { - $event = new GenericEvent($password); - $this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event); + $this->eventDispatcher->dispatchTyped(new ValidatePasswordPolicyEvent($password)); $hasher = \OC::$server->getHasher(); $hashedPassword = $hasher->hash($password); diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index da2d354b7ef..29cae3da79b 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -33,12 +33,15 @@ namespace OC\User; use OC\Hooks\PublicEmitter; use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\EventDispatcher\IEventDispatcher; use OCP\IConfig; use OCP\IGroup; use OCP\IUser; use OCP\IUserBackend; use OCP\IUserManager; use OCP\User\Backend\IGetRealUIDBackend; +use OCP\User\Events\CreateUserEvent; +use OCP\User\Events\UserCreatedEvent; use OCP\UserInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -72,17 +75,24 @@ class Manager extends PublicEmitter implements IUserManager { /** @var IConfig */ private $config; + /** @var EventDispatcherInterface */ private $dispatcher; - public function __construct(IConfig $config, EventDispatcherInterface $dispatcher) { + /** @var IEventDispatcher */ + private $eventDispatcher; + + public function __construct(IConfig $config, + EventDispatcherInterface $oldDispatcher, + IEventDispatcher $eventDispatcher) { $this->config = $config; - $this->dispatcher = $dispatcher; + $this->dispatcher = $oldDispatcher; $cachedUsers = &$this->cachedUsers; $this->listen('\OC\User', 'postDelete', function ($user) use (&$cachedUsers) { /** @var \OC\User\User $user */ unset($cachedUsers[$user->getUID()]); }); + $this->eventDispatcher = $eventDispatcher; } /** @@ -349,6 +359,7 @@ class Manager extends PublicEmitter implements IUserManager { } $this->emit('\OC\User', 'preCreateUser', [$uid, $password]); + $this->eventDispatcher->dispatchTyped(new CreateUserEvent($uid, $password)); $state = $backend->createUser($uid, $password); if($state === false) { throw new \InvalidArgumentException($l->t('Could not create user')); @@ -356,6 +367,7 @@ class Manager extends PublicEmitter implements IUserManager { $user = $this->getUserObject($uid, $backend); if ($user instanceof IUser) { $this->emit('\OC\User', 'postCreateUser', [$user, $password]); + $this->eventDispatcher->dispatchTyped(new UserCreatedEvent($user, $password)); } return $user; } @@ -460,11 +472,11 @@ 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)); - + $result = $queryBuilder->execute(); $count = $result->fetchColumn(); $result->closeCursor(); - + if ($count !== false) { $count = (int)$count; } else { @@ -494,7 +506,7 @@ class Manager extends PublicEmitter implements IUserManager { $result = $queryBuilder->execute(); $count = $result->fetchColumn(); $result->closeCursor(); - + if ($count !== false) { $count = (int)$count; } else { diff --git a/lib/public/AppFramework/Db/Entity.php b/lib/public/AppFramework/Db/Entity.php index 091b90257b4..8bd537211fc 100644 --- a/lib/public/AppFramework/Db/Entity.php +++ b/lib/public/AppFramework/Db/Entity.php @@ -87,7 +87,7 @@ abstract class Entity { return $this->_fieldTypes; } - + /** * Marks the entity as clean needed for setting the id after the insertion * @since 7.0.0 @@ -115,7 +115,7 @@ abstract class Entity { $this->$name = $args[0]; } else { - throw new \BadFunctionCallException($name . + throw new \BadFunctionCallException($name . ' is not a valid attribute'); } } @@ -129,7 +129,7 @@ abstract class Entity { if(property_exists($this, $name)){ return $this->$name; } else { - throw new \BadFunctionCallException($name . + throw new \BadFunctionCallException($name . ' is not a valid attribute'); } } @@ -137,7 +137,7 @@ abstract class Entity { /** * Each time a setter is called, push the part after set - * into an array: for instance setId will save Id in the + * into an array: for instance setId will save Id in the * updated fields array so it can be easily used to create the * getter method * @since 7.0.0 @@ -147,7 +147,7 @@ abstract class Entity { $this->setter(lcfirst(substr($methodName, 3)), $args); } elseif (strpos($methodName, 'get') === 0) { return $this->getter(lcfirst(substr($methodName, 3))); - } elseif (strpos($methodName, 'is') === 0) { + } elseif ($this->isGetterForBoolProperty($methodName)) { return $this->getter(lcfirst(substr($methodName, 2))); } else { throw new \BadFunctionCallException($methodName . @@ -156,6 +156,18 @@ abstract class Entity { } + /** + * @param string $methodName + * @return bool + * @since 18.0.0 + */ + protected function isGetterForBoolProperty(string $methodName): bool { + if (strpos($methodName, 'is') === 0) { + $fieldName = lcfirst(substr($methodName, 2)); + return isset($this->_fieldTypes[$fieldName]) && strpos($this->_fieldTypes[$fieldName], 'bool') === 0; + } + return false; + } /** * Mark am attribute as updated @@ -168,7 +180,7 @@ abstract class Entity { /** - * Transform a database columnname to a property + * Transform a database columnname to a property * @param string $columnName the name of the column * @return string the property name * @since 7.0.0 diff --git a/lib/public/DirectEditing/ACreateEmpty.php b/lib/public/DirectEditing/ACreateEmpty.php new file mode 100644 index 00000000000..ab7f7fd3ae8 --- /dev/null +++ b/lib/public/DirectEditing/ACreateEmpty.php @@ -0,0 +1,79 @@ +<?php +/** + * @copyright Copyright (c) 2019 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\DirectEditing; + + +use OCP\Files\File; + +/** + * @since 18.0.0 + */ +abstract class ACreateEmpty { + + /** + * Unique id for the creator to filter templates + * + * e.g. document/spreadsheet/presentation + * + * @since 18.0.0 + * @return string + */ + abstract public function getId(): string; + + /** + * Descriptive name for the create action + * + * e.g Create a new document + * + * @since 18.0.0 + * @return string + */ + abstract public function getName(): string; + + /** + * Default file extension for the new file + * + * @since 18.0.0 + * @return string + */ + abstract public function getExtension(): string; + + /** + * Mimetype of the resulting created file + * + * @since 18.0.0 + * @return string + */ + abstract public function getMimetype(): string; + + /** + * Add content when creating empty files + * + * @since 18.0.0 + * @param File $file + */ + public function create(File $file, string $creatorId = null, string $templateId = null): void { + + } +} diff --git a/lib/public/DirectEditing/ACreateFromTemplate.php b/lib/public/DirectEditing/ACreateFromTemplate.php new file mode 100644 index 00000000000..89420a63743 --- /dev/null +++ b/lib/public/DirectEditing/ACreateFromTemplate.php @@ -0,0 +1,39 @@ +<?php +/** + * @copyright Copyright (c) 2019 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\DirectEditing; + +/** + * @since 18.0.0 + */ +abstract class ACreateFromTemplate extends ACreateEmpty { + + /** + * List of available templates for the create from template action + * + * @since 18.0.0 + * @return ATemplate[] + */ + abstract public function getTemplates(): array; + +} diff --git a/lib/public/DirectEditing/ATemplate.php b/lib/public/DirectEditing/ATemplate.php new file mode 100644 index 00000000000..734317eebef --- /dev/null +++ b/lib/public/DirectEditing/ATemplate.php @@ -0,0 +1,71 @@ +<?php +/** + * @copyright Copyright (c) 2019 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\DirectEditing; + +use JsonSerializable; + +/** + * Class ATemplate + * + * @package OCP\DirectEditing + * @since 18.0.0 + */ +abstract class ATemplate implements JsonSerializable { + + /** + * Return a unique id so the app can identify the template + * + * @since 18.0.0 + * @return string + */ + abstract public function getId(): string; + + /** + * Return a title that is displayed to the user + * + * @since 18.0.0 + * @return string + */ + abstract public function getTitle(): string; + + /** + * Return a link to the template preview image + * + * @since 18.0.0 + * @return string + */ + abstract public function getPreview(): string; + + /** + * @since 18.0.0 + * @return array|mixed + */ + public function jsonSerialize() { + return [ + 'id' => $this->getId(), + 'title' => $this->getTitle(), + 'preview' => $this->getPreview(), + ]; + } +} diff --git a/lib/public/DirectEditing/IEditor.php b/lib/public/DirectEditing/IEditor.php new file mode 100644 index 00000000000..a2bc0d74255 --- /dev/null +++ b/lib/public/DirectEditing/IEditor.php @@ -0,0 +1,99 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2019 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\DirectEditing; + + +use OCP\AppFramework\Http\Response; + +/** + * @since 18.0.0 + */ +interface IEditor { + + /** + * Return a unique identifier for the editor + * + * e.g. richdocuments + * + * @since 18.0.0 + * @return string + */ + public function getId(): string; + + /** + * Return a readable name for the editor + * + * e.g. Collabora Online + * + * @since 18.0.0 + * @return string + */ + public function getName(): string; + + /** + * A list of mimetypes that should open the editor by default + * + * @since 18.0.0 + * @return string[] + */ + public function getMimetypes(): array; + + /** + * A list of mimetypes that can be opened in the editor optionally + * + * @since 18.0.0 + * @return string[] + */ + public function getMimetypesOptional(): array; + + /** + * Return a list of file creation options to be presented to the user + * + * @since 18.0.0 + * @return ACreateFromTemplate[]|ACreateEmpty[] + */ + public function getCreators(): array; + + /** + * Return if the view is able to securely view a file without downloading it to the browser + * + * @since 18.0.0 + * @return bool + */ + public function isSecure(): bool; + + /** + * Return a template response for displaying the editor + * + * open can only be called once when the client requests the editor with a one-time-use token + * For handling editing and later requests, editors need to impelement their own token handling and take care of invalidation + * + * This behavior is similar to the current direct editing implementation in collabora where we generate a one-time token and switch over to the regular wopi token for the actual editing/saving process + * + * @since 18.0.0 + * @return Response + */ + public function open(IToken $token): Response; +} diff --git a/lib/public/DirectEditing/IManager.php b/lib/public/DirectEditing/IManager.php new file mode 100644 index 00000000000..07b9c5a1e4e --- /dev/null +++ b/lib/public/DirectEditing/IManager.php @@ -0,0 +1,88 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2019 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\DirectEditing; + +use OCP\AppFramework\Http\Response; +use OCP\Files\NotPermittedException; +use RuntimeException; + +/** + * Interface IManager + * + * @package OCP\DirectEditing + * @since 18.0.0 + */ +interface IManager { + + /** + * Register a new editor + * + * @since 18.0.0 + * @param IEditor $directEditor + */ + public function registerDirectEditor(IEditor $directEditor): void; + + /** + * Open the editing page for a provided token + * + * @since 18.0.0 + * @param string $token + * @return Response + */ + public function edit(string $token): Response; + + /** + * Create a new token based on the file path and editor details + * + * @since 18.0.0 + * @param string $path + * @param string $editorId + * @param string $creatorId + * @param null $templateId + * @return string + * @throws NotPermittedException + * @throws RuntimeException + */ + public function create(string $path, string $editorId, string $creatorId, $templateId = null): string; + + /** + * Get the token details for a given token + * + * @since 18.0.0 + * @param string $token + * @return IToken + */ + public function getToken(string $token): IToken; + + /** + * Cleanup expired tokens + * + * @since 18.0.0 + * @return int number of deleted tokens + */ + public function cleanup(): int; + +} + diff --git a/lib/public/DirectEditing/IToken.php b/lib/public/DirectEditing/IToken.php new file mode 100644 index 00000000000..a7eb415e28e --- /dev/null +++ b/lib/public/DirectEditing/IToken.php @@ -0,0 +1,83 @@ +<?php +/** + * @copyright Copyright (c) 2019 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\DirectEditing; + + +use OCP\Files\File; + +/** + * @since 18.0.0 + */ +interface IToken { + + /** + * Extend the token validity time + * + * @since 18.0.0 + */ + public function extend(): void; + + /** + * Invalidate the token + * + * @since 18.0.0 + */ + public function invalidate(): void; + + /** + * Check if the token has already been used + * + * @since 18.0.0 + * @return bool + */ + public function hasBeenAccessed(): bool; + + /** + * Change to the user scope of the token + * + * @since 18.0.0 + */ + public function useTokenScope(): void; + + /** + * Get the file that is related to the token + * + * @since 18.0.0 + * @return File + */ + public function getFile(): File; + + /** + * @since 18.0.0 + * @return string + */ + public function getEditor(): string; + + /** + * @since 18.0.0 + * @return string + */ + public function getUser(): string; + +} diff --git a/lib/public/DirectEditing/RegisterDirectEditorEvent.php b/lib/public/DirectEditing/RegisterDirectEditorEvent.php new file mode 100644 index 00000000000..801e9f8fb1b --- /dev/null +++ b/lib/public/DirectEditing/RegisterDirectEditorEvent.php @@ -0,0 +1,57 @@ +<?php +/** + * @copyright Copyright (c) 2019 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\DirectEditing; + +use OCP\EventDispatcher\Event; + +/** + * @since 18.0.0 + */ +class RegisterDirectEditorEvent extends Event { + + /** + * @var IManager + */ + private $manager; + + /** + * RegisterDirectEditorEvent constructor. + * + * @param IManager $manager + * @since 18.0.0 + */ + public function __construct(IManager $manager) { + parent::__construct(); + $this->manager = $manager; + } + + /** + * @since 18.0.0 + * @param IEditor $editor + */ + public function register(IEditor $editor): void { + $this->manager->registerDirectEditor($editor); + } + +} diff --git a/lib/public/EventDispatcher/GenericEvent.php b/lib/public/EventDispatcher/GenericEvent.php new file mode 100644 index 00000000000..4607e6621ae --- /dev/null +++ b/lib/public/EventDispatcher/GenericEvent.php @@ -0,0 +1,169 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2019 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\EventDispatcher; + +use ArrayAccess; +use ArrayIterator; +use InvalidArgumentException; +use IteratorAggregate; +use Traversable; +use function array_key_exists; + +/** + * Class GenericEvent + * + * convenience reimplementation of \Symfony\Component\GenericEvent against + * \OCP\EventDispatcher\Event + * + * @package OCP\EventDispatcher + * @since 18.0.0 + */ +class GenericEvent extends Event implements ArrayAccess, IteratorAggregate { + protected $subject; + protected $arguments; + + /** + * Encapsulate an event with $subject and $args. + * + * @since 18.0.0 + */ + public function __construct($subject = null, array $arguments = []) { + $this->subject = $subject; + $this->arguments = $arguments; + } + + /** + * Getter for subject property. + * + * @since 18.0.0 + */ + public function getSubject() { + return $this->subject; + } + + /** + * Get argument by key. + * + * @throws InvalidArgumentException if key is not found + * @since 18.0.0 + */ + public function getArgument(string $key) { + if ($this->hasArgument($key)) { + return $this->arguments[$key]; + } + + throw new InvalidArgumentException(sprintf('Argument "%s" not found.', $key)); + } + + /** + * Add argument to event. + * + * @since 18.0.0 + */ + public function setArgument($key, $value): GenericEvent { + $this->arguments[$key] = $value; + return $this; + } + + /** + * Getter for all arguments. + * + * @since 18.0.0 + */ + public function getArguments(): array { + return $this->arguments; + } + + /** + * Set args property. + * + * @since 18.0.0 + */ + public function setArguments(array $args = []): GenericEvent { + $this->arguments = $args; + return $this; + } + + /** + * Has argument. + * + * @since 18.0.0 + */ + public function hasArgument($key): bool { + return array_key_exists($key, $this->arguments); + } + + /** + * Retrieve an external iterator + * + * @link https://php.net/manual/en/iteratoraggregate.getiterator.php + * @since 18.0.0 + */ + public function getIterator(): Traversable { + return new ArrayIterator($this->arguments); + } + + /** + * Whether a offset exists + * + * @link https://php.net/manual/en/arrayaccess.offsetexists.php + * @since 18.0.0 + */ + public function offsetExists($offset): bool { + return $this->hasArgument($offset); + } + + /** + * Offset to retrieve + * + * @link https://php.net/manual/en/arrayaccess.offsetget.php + * @since 18.0.0 + */ + public function offsetGet($offset) { + return $this->arguments[$offset]; + } + + /** + * Offset to set + * + * @link https://php.net/manual/en/arrayaccess.offsetset.php + * @since 18.0.0 + */ + public function offsetSet($offset, $value): void { + $this->setArgument($offset, $value); + } + + /** + * Offset to unset + * + * @link https://php.net/manual/en/arrayaccess.offsetunset.php + * @since 18.0.0 + */ + public function offsetUnset($offset): void { + if ($this->hasArgument($offset)) { + unset($this->arguments[$offset]); + } + } +} diff --git a/lib/public/Files/File.php b/lib/public/Files/File.php index 1fe01cfb29a..bd3b3da0df2 100644 --- a/lib/public/Files/File.php +++ b/lib/public/Files/File.php @@ -33,6 +33,8 @@ namespace OCP\Files; +use OCP\Lock\LockedException; + /** * Interface File * @@ -44,7 +46,8 @@ interface File extends Node { * Get the content of the file as string * * @return string - * @throws \OCP\Files\NotPermittedException + * @throws NotPermittedException + * @throws LockedException * @since 6.0.0 */ public function getContent(); @@ -53,8 +56,9 @@ interface File extends Node { * Write to the file from string data * * @param string|resource $data - * @throws \OCP\Files\NotPermittedException - * @throws \OCP\Files\GenericFileException + * @throws NotPermittedException + * @throws GenericFileException + * @throws LockedException * @since 6.0.0 */ public function putContent($data); @@ -72,7 +76,8 @@ interface File extends Node { * * @param string $mode * @return resource - * @throws \OCP\Files\NotPermittedException + * @throws NotPermittedException + * @throws LockedException * @since 6.0.0 */ public function fopen($mode); diff --git a/lib/public/Files/Node.php b/lib/public/Files/Node.php index 4468b680014..af7d9454ca6 100644 --- a/lib/public/Files/Node.php +++ b/lib/public/Files/Node.php @@ -34,6 +34,8 @@ namespace OCP\Files; +use OCP\Lock\LockedException; + /** * Interface Node * @@ -45,15 +47,22 @@ interface Node extends FileInfo { * Move the file or folder to a new location * * @param string $targetPath the absolute target path - * @throws \OCP\Files\NotPermittedException - * @return \OCP\Files\Node + * @return Node + * @throws NotFoundException + * @throws NotPermittedException if move not allowed or failed + * @throws LockedException + * @throws InvalidPathException * @since 6.0.0 */ public function move($targetPath); /** * Delete the file or folder + * * @return void + * @throws NotPermittedException + * @throws InvalidPathException + * @throws NotFoundException * @since 6.0.0 */ public function delete(); @@ -62,7 +71,7 @@ interface Node extends FileInfo { * Cope the file or folder to a new location * * @param string $targetPath the absolute target path - * @return \OCP\Files\Node + * @return Node * @since 6.0.0 */ public function copy($targetPath); @@ -72,7 +81,9 @@ interface Node extends FileInfo { * If $mtime is omitted the current time will be used * * @param int $mtime (optional) modified date as unix timestamp - * @throws \OCP\Files\NotPermittedException + * @throws InvalidPathException + * @throws NotFoundException + * @throws NotPermittedException * @return void * @since 6.0.0 */ @@ -81,8 +92,8 @@ interface Node extends FileInfo { /** * Get the storage backend the file or folder is stored on * - * @return \OCP\Files\Storage - * @throws \OCP\Files\NotFoundException + * @return Storage + * @throws NotFoundException * @since 6.0.0 */ public function getStorage(); @@ -247,7 +258,7 @@ interface Node extends FileInfo { * any filesystem operation will automatically acquire the relevant locks for that operation. * * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE - * @throws \OCP\Lock\LockedException + * @throws LockedException * @since 9.1.0 */ public function lock($type); @@ -262,7 +273,7 @@ interface Node extends FileInfo { * Note that this is also the case if no existing lock exists for the file. * * @param int $targetType \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE - * @throws \OCP\Lock\LockedException + * @throws LockedException * @since 9.1.0 */ public function changeLock($targetType); @@ -275,7 +286,7 @@ interface Node extends FileInfo { * Note that this method will not give any sort of error when trying to free a lock that doesn't exist. * * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE - * @throws \OCP\Lock\LockedException + * @throws LockedException * @since 9.1.0 */ public function unlock($type); diff --git a/lib/public/Security/Events/GenerateSecurePasswordEvent.php b/lib/public/Security/Events/GenerateSecurePasswordEvent.php new file mode 100644 index 00000000000..a55c8daafbd --- /dev/null +++ b/lib/public/Security/Events/GenerateSecurePasswordEvent.php @@ -0,0 +1,50 @@ +<?php declare(strict_types=1); + +/** + * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2019 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\Security\Events; + +use OCP\EventDispatcher\Event; + +/** + * @since 18.0.0 + */ +class GenerateSecurePasswordEvent extends Event { + + /** @var null|string */ + private $password; + + /** + * @since 18.0.0 + */ + public function getPassword(): ?string { + return $this->password; + } + + /** + * @since 18.0.0 + */ + public function setPassword(string $password): void { + $this->password = $password; + } + +} diff --git a/lib/public/Security/Events/ValidatePasswordPolicyEvent.php b/lib/public/Security/Events/ValidatePasswordPolicyEvent.php new file mode 100644 index 00000000000..11378526cc7 --- /dev/null +++ b/lib/public/Security/Events/ValidatePasswordPolicyEvent.php @@ -0,0 +1,51 @@ +<?php declare(strict_types=1); + +/** + * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2019 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\Security\Events; + +use OCP\EventDispatcher\Event; + +/** + * @since 18.0.0 + */ +class ValidatePasswordPolicyEvent extends Event { + + /** @var string */ + private $password; + + /** + * @since 18.0.0 + */ + public function __construct(string $password) { + parent::__construct(); + $this->password = $password; + } + + /** + * @since 18.0.0 + */ + public function getPassword(): string { + return $this->password; + } + +} diff --git a/lib/public/User/Events/CreateUserEvent.php b/lib/public/User/Events/CreateUserEvent.php new file mode 100644 index 00000000000..877899fcba0 --- /dev/null +++ b/lib/public/User/Events/CreateUserEvent.php @@ -0,0 +1,63 @@ +<?php declare(strict_types=1); + +/** + * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2019 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\User\Events; + +use OCP\EventDispatcher\Event; + +/** + * @since 18.0.0 + */ +class CreateUserEvent extends Event { + + /** @var string */ + private $uid; + + /** @var string */ + private $password; + + /** + * @since 18.0.0 + */ + public function __construct(string $uid, + string $password) { + parent::__construct(); + $this->uid = $uid; + $this->password = $password; + } + + /** + * @since 18.0.0 + */ + public function getUid(): string { + return $this->uid; + } + + /** + * @since 18.0.0 + */ + public function getPassword(): string { + return $this->password; + } + +} diff --git a/lib/public/User/Events/UserCreatedEvent.php b/lib/public/User/Events/UserCreatedEvent.php new file mode 100644 index 00000000000..53debf5ff5c --- /dev/null +++ b/lib/public/User/Events/UserCreatedEvent.php @@ -0,0 +1,71 @@ +<?php declare(strict_types=1); + +/** + * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2019 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\User\Events; + +use OCP\EventDispatcher\Event; +use OCP\IUser; + +/** + * @since 18.0.0 + */ +class UserCreatedEvent extends Event { + + /** @var IUser */ + private $user; + + /** @var string */ + private $password; + + /** + * @since 18.0.0 + */ + public function __construct(IUser $user, + string $password) { + parent::__construct(); + $this->user = $user; + $this->password = $password; + } + + /** + * @since 18.0.0 + */ + public function getUser(): IUser { + return $this->user; + } + + /** + * @since 18.0.0 + */ + public function getUid(): string { + return $this->user->getUID(); + } + + /** + * @since 18.0.0 + */ + public function getPassword(): string { + return $this->password; + } + +} diff --git a/lib/public/WorkflowEngine/EntityContext/IDisplayName.php b/lib/public/WorkflowEngine/EntityContext/IDisplayName.php new file mode 100644 index 00000000000..eeaf7887d5a --- /dev/null +++ b/lib/public/WorkflowEngine/EntityContext/IDisplayName.php @@ -0,0 +1,41 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2019 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\WorkflowEngine\EntityContext; + +/** + * Interface IDisplayName + * + * @package OCP\WorkflowEngine\EntityContext + * + * @since 18.0.0 + */ +interface IDisplayName { + /** + * returns the end user facing name of the object related to the entity + * + * @since 18.0.0 + */ + public function getDisplayName(): string; +} diff --git a/lib/public/WorkflowEngine/EntityContext/IDisplayText.php b/lib/public/WorkflowEngine/EntityContext/IDisplayText.php new file mode 100644 index 00000000000..5e74171883a --- /dev/null +++ b/lib/public/WorkflowEngine/EntityContext/IDisplayText.php @@ -0,0 +1,47 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2019 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\WorkflowEngine\EntityContext; + +/** + * Interface IDisplayText + * + * @package OCP\WorkflowEngine\EntityContext + * + * @since 18.0.0 + */ +interface IDisplayText { + + /** + * returns translated text used for display to the end user. For instance, + * it can describe the event in a human readable way. + * + * The entity may react to a verbosity level that is provided. With the + * basic level, 0, it would return brief information, and more with higher + * numbers. All information shall be shown at a level of 3. + * + * @since 18.0.0 + */ + public function getDisplayText(int $verbosity = 0): string; +} diff --git a/lib/public/WorkflowEngine/EntityContext/IIcon.php b/lib/public/WorkflowEngine/EntityContext/IIcon.php new file mode 100644 index 00000000000..cde340c9931 --- /dev/null +++ b/lib/public/WorkflowEngine/EntityContext/IIcon.php @@ -0,0 +1,42 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2019 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\WorkflowEngine\EntityContext; + +/** + * Interface IIcon + * + * @package OCP\WorkflowEngine\EntityContext + * + * @since 18.0.0 + */ +interface IIcon { + /** + * returns a URL to an icon that is related to the entity, for instance + * a group icon for groups. + * + * @since 18.0.0 + */ + public function getIconUrl(): string; +} diff --git a/lib/public/WorkflowEngine/EntityContext/IUrl.php b/lib/public/WorkflowEngine/EntityContext/IUrl.php new file mode 100644 index 00000000000..a847dfaad05 --- /dev/null +++ b/lib/public/WorkflowEngine/EntityContext/IUrl.php @@ -0,0 +1,41 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2019 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\WorkflowEngine\EntityContext; + +/** + * Interface IUrl + * + * @package OCP\WorkflowEngine\EntityContext + * + * @since 18.0.0 + */ +interface IUrl { + /** + * returns a URL that is related to the entity, e.g. the link to a share + * + * @since 18.0.0 + */ + public function getUrl(): string; +} diff --git a/lib/public/WorkflowEngine/IEntity.php b/lib/public/WorkflowEngine/IEntity.php index b8205600498..47e2f102199 100644 --- a/lib/public/WorkflowEngine/IEntity.php +++ b/lib/public/WorkflowEngine/IEntity.php @@ -74,4 +74,12 @@ interface IEntity { */ public function prepareRuleMatcher(IRuleMatcher $ruleMatcher, string $eventName, Event $event): void; + /** + * returns whether the provided user id is allowed to run a flow against + * the known context + * + * @since 18.0.0 + */ + public function isLegitimatedForUserId(string $userId): bool; + } diff --git a/lib/public/WorkflowEngine/IRuleMatcher.php b/lib/public/WorkflowEngine/IRuleMatcher.php index 5569800edb7..28abaa56137 100644 --- a/lib/public/WorkflowEngine/IRuleMatcher.php +++ b/lib/public/WorkflowEngine/IRuleMatcher.php @@ -24,6 +24,8 @@ declare(strict_types=1); namespace OCP\WorkflowEngine; +use RuntimeException; + /** * Class IRuleMatcher * @@ -33,7 +35,45 @@ namespace OCP\WorkflowEngine; */ interface IRuleMatcher extends IFileCheck { /** + * This method is left for backwards compatibility and easier porting of + * apps. Please use 'getFlows' instead (and setOperation if you implement + * an IComplexOperation). + * * @since 18.0.0 + * @deprecated 18.0.0 */ public function getMatchingOperations(string $class, bool $returnFirstMatchingOperationOnly = true): array; + + /** + * @throws RuntimeException + * @since 18.0.0 + */ + public function getFlows(bool $returnFirstMatchingOperationOnly = true): array; + + /** + * this method can only be called once and is typically called by the + * Flow engine, unless for IComplexOperations. + * + * @throws RuntimeException + * @since 18.0.0 + */ + public function setOperation(IOperation $operation): void; + + /** + * this method can only be called once and is typically called by the + * Flow engine, unless for IComplexOperations. + * + * @throws RuntimeException + * @since 18.0.0 + */ + public function setEntity(IEntity $entity): void; + + /** + * returns the entity which might provide more information, depending on + * the interfaces it implements + * + * @return IEntity + * @since 18.0.0 + */ + public function getEntity(): IEntity; } diff --git a/lib/versioncheck.php b/lib/versioncheck.php index ffaa0e510a3..d404f66781e 100644 --- a/lib/versioncheck.php +++ b/lib/versioncheck.php @@ -1,17 +1,17 @@ <?php -// Show warning if a PHP version below 7.1 is used, -if (version_compare(PHP_VERSION, '7.1') === -1) { +// Show warning if a PHP version below 7.2 is used, +if (PHP_VERSION_ID < 70200) { http_response_code(500); - echo 'This version of Nextcloud requires at least PHP 7.1<br/>'; + echo 'This version of Nextcloud requires at least PHP 7.2<br/>'; echo 'You are currently running ' . PHP_VERSION . '. Please update your PHP version.'; exit(-1); } -// Show warning if > PHP 7.3 is used as Nextcloud is not compatible with > PHP 7.3 for now -if (version_compare(PHP_VERSION, '7.4.0') !== -1) { +// Show warning if > PHP 7.4 is used as Nextcloud is not compatible with > PHP 7.4 for now +if (PHP_VERSION_ID >= 70500) { http_response_code(500); - echo 'This version of Nextcloud is not compatible with > PHP 7.3.<br/>'; + echo 'This version of Nextcloud is not compatible with > PHP 7.4.<br/>'; echo 'You are currently running ' . PHP_VERSION . '.'; exit(-1); } |