From 1aba986d9f219a872c83b5f8b46f641e2699a222 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Sat, 9 Feb 2013 12:42:18 +0000 Subject: [PATCH 001/257] Fixed bug causing nested file read over webdav to fail --- apps/files_encryption/lib/proxy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 55cddf2bec..7ae36e34ce 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -281,7 +281,7 @@ class Proxy extends \OC_FileProxy { // Reformat path for use with OC_FSV $path_split = explode( '/', $path ); - $path_f = implode( array_slice( $path_split, 3 ) ); + $path_f = implode( '/', array_slice( $path_split, 3 ) ); // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; From b3e59ca1e31f162d7ac720d8729958f438b23a02 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Sat, 9 Feb 2013 18:39:32 +0000 Subject: [PATCH 002/257] Work on post_share hook for files_encryption New method in OCP\Share{}:: getUsersSharingFile() Development shapshot --- apps/files_encryption/hooks/hooks.php | 71 ++- apps/files_encryption/lib/keymanager.php | 583 +++++++++++------------ apps/files_encryption/lib/proxy.php | 32 +- lib/public/share.php | 54 +++ 4 files changed, 429 insertions(+), 311 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 8bdeee0937..c6d4c16115 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -166,14 +166,77 @@ class Hooks { */ public static function postShared( $params ) { - // Delete existing catfile - Keymanager::deleteFileKey( ); + // NOTE: $params is an array with these keys: + // itemSource -> int, filecache file ID + // shareWith -> string, uid of user being shared to + // fileTarget -> path of file being shared + // uidOwner -> owner of the original file being shared - // Generate new catfile and env keys - Crypt::multiKeyEncrypt( $plainContent, $publicKeys ); + $view = new \OC_FilesystemView( '/' ); + $userId = \OCP\User::getUser(); + $util = new Util( $view, $userId ); + + $shares = \OCP\Share::getUsersSharingFile( $params['fileTarget'] ); + + $userIds = array(); + + foreach ( $shares as $share ) { + + $util = new Util( $view, $share['userId'] ); + + // Check that the user is encryption capable + if ( $util->ready() ) { + + // Construct array of just UIDs for Keymanager{} + $userIds[] = $share['userId']; + + } else { + + // Log warning; we can't do necessary setup here + // because we don't have the user passphrase + // TODO: Provide user feedback indicating that + // sharing failed + \OC_Log::write( 'Encryption library', 'File cannot be shared: user "'.$share['userId'].'" is not setup for encryption', \OC_Log::WARN ); + + } + + } + + trigger_error("UIDS = ".var_export($userIds, 1)); + + $userPubKeys = Keymanager::getPublicKeys( $view, $userIds ); + +// trigger_error("PUB KEYS = ".var_export($userPubKeys, 1)); + + // TODO: Fetch path from Crypt{} getter + $plainContent = $view->file_get_contents( $userId . '/' . 'files'. '/' . $params['fileTarget'] ); + + // Generate new catfile and share keys + if ( ! $encrypted = Crypt::multiKeyEncrypt( $plainContent, $userPubKeys ) ) { + + // If the re-encryption failed, don't risk deleting data + return false; + + } + + trigger_error("ENCRYPTED = ". var_export($encrypted, 1)); // Save env keys to user folders + foreach ( $encrypted['keys'] as $key ) { +// Keymanager::setShareKey( $view, $params['fileTarget'], $userId, $key ); + + } + + // Delete existing catfile + // Check if keyfile exists (it won't if file has been shared before) + // Do this last to ensure file is recoverable in case of error + if ( $util->isEncryptedPath( $params['fileTarget'] ) ) { + + // NOTE: This will trigger an error if keyfile isn't found +// Keymanager::deleteFileKey( $params['fileTarget'] ); + + } } diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 0d0380db6e..3160572ba1 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -1,267 +1,244 @@ - - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library 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 library. If not, see . - * - */ - -namespace OCA\Encryption; - -/** - * @brief Class to manage storage and retrieval of encryption keys - * @note Where a method requires a view object, it's root must be '/' - */ -class Keymanager { + + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library 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 library. If not, see . + * + */ + +namespace OCA\Encryption; + +/** + * @brief Class to manage storage and retrieval of encryption keys + * @note Where a method requires a view object, it's root must be '/' + */ +class Keymanager { - /** - * @brief retrieve the ENCRYPTED private key from a user - * - * @return string private key or false - * @note the key returned by this method must be decrypted before use - */ - public static function getPrivateKey( \OC_FilesystemView $view, $user ) { - - $path = '/' . $user . '/' . 'files_encryption' . '/' . $user.'.private.key'; - - $key = $view->file_get_contents( $path ); - - return $key; - } - - /** - * @brief retrieve public key for a specified user + /** + * @brief retrieve the ENCRYPTED private key from a user + * + * @return string private key or false + * @note the key returned by this method must be decrypted before use + */ + public static function getPrivateKey( \OC_FilesystemView $view, $user ) { + + $path = '/' . $user . '/' . 'files_encryption' . '/' . $user.'.private.key'; + + $key = $view->file_get_contents( $path ); + + return $key; + } + + /** + * @brief retrieve public key for a specified user * @param \OC_FilesystemView $view * @param $userId - * @return string public key or false - */ - public static function getPublicKey( \OC_FilesystemView $view, $userId ) { - - return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' ); - - } - - /** - * @brief retrieve both keys from a user (private and public) + * @return string public key or false + */ + public static function getPublicKey( \OC_FilesystemView $view, $userId ) { + + return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' ); + + } + + /** + * @brief Retrieve a user's public and private key * @param \OC_FilesystemView $view * @param $userId - * @return array keys: privateKey, publicKey - */ - public static function getUserKeys( \OC_FilesystemView $view, $userId ) { - - return array( - 'publicKey' => self::getPublicKey( $view, $userId ) - , 'privateKey' => self::getPrivateKey( $view, $userId ) - ); - - } - - /** - * @brief Retrieve public keys of all users with access to a file - * @param string $path Path to file - * @return array of public keys for the given file - * @note Checks that the sharing app is enabled should be performed - * by client code, that isn't checked here - */ - public static function getPublicKeys( \OC_FilesystemView $view, $userId, $filePath ) { - - $path = ltrim( $path, '/' ); - - $filepath = '/' . $userId . '/files/' . $filePath; - - // Check if sharing is enabled - if ( OC_App::isEnabled( 'files_sharing' ) ) { - - - - } else { - - // check if it is a file owned by the user and not shared at all - $userview = new \OC_FilesystemView( '/'.$userId.'/files/' ); - - if ( $userview->file_exists( $path ) ) { - - $users[] = $userId; - - } - - } - - $view = new \OC_FilesystemView( '/public-keys/' ); - - $keylist = array(); - - $count = 0; - - foreach ( $users as $user ) { - - $keylist['key'.++$count] = $view->file_get_contents( $user.'.public.key' ); - - } - - return $keylist; - - } - - /** - * @brief store file encryption key - * - * @param string $path relative path of the file, including filename - * @param string $key - * @return bool true/false - * @note The keyfile is not encrypted here. Client code must - * asymmetrically encrypt the keyfile before passing it to this method - */ - public static function setFileKey( \OC_FilesystemView $view, $path, $userId, $catfile ) { - - $basePath = '/' . $userId . '/files_encryption/keyfiles'; - - $targetPath = self::keySetPreparation( $view, $path, $basePath, $userId ); - - if ( $view->is_dir( $basePath . '/' . $targetPath ) ) { - - - - } else { - - // Save the keyfile in parallel directory - return $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile ); - - } - - } - - /** - * @brief retrieve keyfile for an encrypted file + * @return array keys: privateKey, publicKey + */ + public static function getUserKeys( \OC_FilesystemView $view, $userId ) { + + return array( + 'publicKey' => self::getPublicKey( $view, $userId ) + , 'privateKey' => self::getPrivateKey( $view, $userId ) + ); + + } + + /** + * @brief Retrieve public keys for given users + * @param \OC_FilesystemView $view + * @param array $userIds + * @return array of public keys for the specified users + */ + public static function getPublicKeys( \OC_FilesystemView $view, $userIds ) { + + $i = 0; + $keys = array(); + + foreach ( $userIds as $userId ) { + + $i++; + $keys[$userId] = self::getPublicKey( $view, $userId ); + + } + + $keys['total'] = $i; + + return $keys; + + } + + /** + * @brief store file encryption key + * + * @param string $path relative path of the file, including filename + * @param string $key + * @return bool true/false + * @note The keyfile is not encrypted here. Client code must + * asymmetrically encrypt the keyfile before passing it to this method + */ + public static function setFileKey( \OC_FilesystemView $view, $path, $userId, $catfile ) { + + $basePath = '/' . $userId . '/files_encryption/keyfiles'; + + $targetPath = self::keySetPreparation( $view, $path, $basePath, $userId ); + + if ( $view->is_dir( $basePath . '/' . $targetPath ) ) { + + + + } else { + + // Save the keyfile in parallel directory + return $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile ); + + } + + } + + /** + * @brief retrieve keyfile for an encrypted file * @param \OC_FilesystemView $view * @param $userId * @param $filePath * @internal param \OCA\Encryption\file $string name * @return string file key or false - * @note The keyfile returned is asymmetrically encrypted. Decryption - * of the keyfile must be performed by client code - */ - public static function getFileKey( \OC_FilesystemView $view, $userId, $filePath ) { - - $filePath_f = ltrim( $filePath, '/' ); - - $catfilePath = '/' . $userId . '/files_encryption/keyfiles/' . $filePath_f . '.key'; - - if ( $view->file_exists( $catfilePath ) ) { - - return $view->file_get_contents( $catfilePath ); - - } else { - - return false; - - } - - } - - /** - * @brief Delete a keyfile - * + * @note The keyfile returned is asymmetrically encrypted. Decryption + * of the keyfile must be performed by client code + */ + public static function getFileKey( \OC_FilesystemView $view, $userId, $filePath ) { + + $filePath_f = ltrim( $filePath, '/' ); + + $catfilePath = '/' . $userId . '/files_encryption/keyfiles/' . $filePath_f . '.key'; + + if ( $view->file_exists( $catfilePath ) ) { + + return $view->file_get_contents( $catfilePath ); + + } else { + + return false; + + } + + } + + /** + * @brief Delete a keyfile + * * @param OC_FilesystemView $view * @param string $userId username * @param string $path path of the file the key belongs to * @return bool Outcome of unlink operation * @note $path must be relative to data/user/files. e.g. mydoc.txt NOT * /data/admin/files/mydoc.txt - */ - public static function deleteFileKey( \OC_FilesystemView $view, $userId, $path ) { - - $trimmed = ltrim( $path, '/' ); - $keyPath = '/' . $userId . '/files_encryption/keyfiles/' . $trimmed . '.key'; - - // Unlink doesn't tell us if file was deleted (not found returns - // true), so we perform our own test - if ( $view->file_exists( $keyPath ) ) { - - return $view->unlink( $keyPath ); - - } else { - - \OC_Log::write( 'Encryption library', 'Could not delete keyfile; does not exist: "' . $keyPath, \OC_Log::ERROR ); - - return false; - - } - - } - - /** - * @brief store private key from the user - * @param string key - * @return bool - * @note Encryption of the private key must be performed by client code - * as no encryption takes place here - */ - public static function setPrivateKey( $key ) { - - $user = \OCP\User::getUser(); - - $view = new \OC_FilesystemView( '/' . $user . '/files_encryption' ); - - \OC_FileProxy::$enabled = false; - - if ( !$view->file_exists( '' ) ) $view->mkdir( '' ); - - return $view->file_put_contents( $user . '.private.key', $key ); - - \OC_FileProxy::$enabled = true; - - } - - /** - * @brief store private keys from the user - * - * @param string privatekey - * @param string publickey - * @return bool true/false - */ - public static function setUserKeys($privatekey, $publickey) { - - return ( self::setPrivateKey( $privatekey ) && self::setPublicKey( $publickey ) ); - - } - - /** - * @brief store public key of the user - * - * @param string key - * @return bool true/false - */ - public static function setPublicKey( $key ) { - - $view = new \OC_FilesystemView( '/public-keys' ); - - \OC_FileProxy::$enabled = false; - - if ( !$view->file_exists( '' ) ) $view->mkdir( '' ); - - return $view->file_put_contents( \OCP\User::getUser() . '.public.key', $key ); - - \OC_FileProxy::$enabled = true; - - } - - /** + */ + public static function deleteFileKey( \OC_FilesystemView $view, $userId, $path ) { + + $trimmed = ltrim( $path, '/' ); + $keyPath = '/' . $userId . '/files_encryption/keyfiles/' . $trimmed . '.key'; + + // Unlink doesn't tell us if file was deleted (not found returns + // true), so we perform our own test + if ( $view->file_exists( $keyPath ) ) { + + return $view->unlink( $keyPath ); + + } else { + + \OC_Log::write( 'Encryption library', 'Could not delete keyfile; does not exist: "' . $keyPath, \OC_Log::ERROR ); + + return false; + + } + + } + + /** + * @brief store private key from the user + * @param string key + * @return bool + * @note Encryption of the private key must be performed by client code + * as no encryption takes place here + */ + public static function setPrivateKey( $key ) { + + $user = \OCP\User::getUser(); + + $view = new \OC_FilesystemView( '/' . $user . '/files_encryption' ); + + \OC_FileProxy::$enabled = false; + + if ( !$view->file_exists( '' ) ) $view->mkdir( '' ); + + return $view->file_put_contents( $user . '.private.key', $key ); + + \OC_FileProxy::$enabled = true; + + } + + /** + * @brief store private keys from the user + * + * @param string privatekey + * @param string publickey + * @return bool true/false + */ + public static function setUserKeys($privatekey, $publickey) { + + return ( self::setPrivateKey( $privatekey ) && self::setPublicKey( $publickey ) ); + + } + + /** + * @brief store public key of the user + * + * @param string key + * @return bool true/false + */ + public static function setPublicKey( $key ) { + + $view = new \OC_FilesystemView( '/public-keys' ); + + \OC_FileProxy::$enabled = false; + + if ( !$view->file_exists( '' ) ) $view->mkdir( '' ); + + return $view->file_put_contents( \OCP\User::getUser() . '.public.key', $key ); + + \OC_FileProxy::$enabled = true; + + } + + /** * @brief store file encryption key * * @param string $path relative path of the file, including filename @@ -271,70 +248,70 @@ class Keymanager { * @return bool true/false * @note The keyfile is not encrypted here. Client code must * asymmetrically encrypt the keyfile before passing it to this method - */ - public static function setShareKey( \OC_FilesystemView $view, $path, $userId, $shareKey ) { - - $basePath = '/' . $userId . '/files_encryption/share-keys'; - - $shareKeyPath = self::keySetPreparation( $view, $path, $basePath, $userId ); - - return $view->file_put_contents( $basePath . '/' . $shareKeyPath . '.shareKey', $shareKey ); - + */ + public static function setShareKey( \OC_FilesystemView $view, $path, $userId, $shareKey ) { + + $basePath = '/' . $userId . '/files_encryption/share-keys'; + + $shareKeyPath = self::keySetPreparation( $view, $path, $basePath, $userId ); + + return $view->file_put_contents( $basePath . '/' . $shareKeyPath . '.shareKey', $shareKey ); + } /** * @brief Make preparations to vars and filesystem for saving a keyfile */ public static function keySetPreparation( \OC_FilesystemView $view, $path, $basePath, $userId ) { - - $targetPath = ltrim( $path, '/' ); - - $path_parts = pathinfo( $targetPath ); - - // If the file resides within a subdirectory, create it + + $targetPath = ltrim( $path, '/' ); + + $path_parts = pathinfo( $targetPath ); + + // If the file resides within a subdirectory, create it if ( isset( $path_parts['dirname'] ) && ! $view->file_exists( $basePath . '/' . $path_parts['dirname'] ) - ) { - - $view->mkdir( $basePath . '/' . $path_parts['dirname'] ); - - } - + ) { + + $view->mkdir( $basePath . '/' . $path_parts['dirname'] ); + + } + return $targetPath; - } - - /** - * @brief change password of private encryption key - * - * @param string $oldpasswd old password - * @param string $newpasswd new password - * @return bool true/false - */ - public static function changePasswd($oldpasswd, $newpasswd) { - - if ( \OCP\User::checkPassword(\OCP\User::getUser(), $newpasswd) ) { - return Crypt::changekeypasscode($oldpasswd, $newpasswd); - } - return false; - - } - - /** - * @brief Fetch the legacy encryption key from user files - * @param string $login used to locate the legacy key - * @param string $passphrase used to decrypt the legacy key - * @return true / false - * - * if the key is left out, the default handeler will be used - */ - public function getLegacyKey() { - - $user = \OCP\User::getUser(); - $view = new \OC_FilesystemView( '/' . $user ); - return $view->file_get_contents( 'encryption.key' ); - - } - + } + + /** + * @brief change password of private encryption key + * + * @param string $oldpasswd old password + * @param string $newpasswd new password + * @return bool true/false + */ + public static function changePasswd($oldpasswd, $newpasswd) { + + if ( \OCP\User::checkPassword(\OCP\User::getUser(), $newpasswd) ) { + return Crypt::changekeypasscode($oldpasswd, $newpasswd); + } + return false; + + } + + /** + * @brief Fetch the legacy encryption key from user files + * @param string $login used to locate the legacy key + * @param string $passphrase used to decrypt the legacy key + * @return true / false + * + * if the key is left out, the default handeler will be used + */ + public function getLegacyKey() { + + $user = \OCP\User::getUser(); + $view = new \OC_FilesystemView( '/' . $user ); + return $view->file_get_contents( 'encryption.key' ); + + } + } \ No newline at end of file diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 7ae36e34ce..58b9bc0725 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -95,7 +95,8 @@ class Proxy extends \OC_FileProxy { if ( self::shouldEncrypt( $path ) ) { - if ( !is_resource( $data ) ) { //stream put contents should have been converted to fopen + // Stream put contents should have been converted to fopen + if ( !is_resource( $data ) ) { $userId = \OCP\USER::getUser(); @@ -107,10 +108,33 @@ class Proxy extends \OC_FileProxy { // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; - // TODO: Check if file is shared, if so, use multiKeyEncrypt + $fileOwner = \OC\Files\Filesystem::getOwner( $path ); - // Encrypt plain data and fetch key - $encrypted = Crypt::keyEncryptKeyfile( $data, Keymanager::getPublicKey( $rootView, $userId ) ); + // Check if the keyfile needs to be shared + if ( + $fileOwner !== true + or $fileOwner !== $userId + ) { + + // Shared storage backend isn't loaded + + $users = \OCP\Share::getItemShared( 'file', $path, \OC_Share_backend_File::FORMAT_SHARED_STORAGE ); +// + trigger_error("SHARE USERS = ". var_export($users, 1)); +// +// $publicKeys = Keymanager::getPublicKeys( $rootView, $users); +// +// // Encrypt plain data to multiple users +// $encrypted = Crypt::multiKeyEncrypt( $data, $publicKeys ); + + } else { + + $publicKey = Keymanager::getPublicKey( $rootView, $userId ); + + // Encrypt plain data to a single user + $encrypted = Crypt::keyEncryptKeyfile( $data, $publicKey ); + + } // Replace plain content with encrypted content by reference $data = $encrypted['data']; diff --git a/lib/public/share.php b/lib/public/share.php index af2a538e25..936f85021c 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -91,6 +91,60 @@ class Share { } return false; } + + /** + * @brief Find which users can access a shared item + * @param string Item type + * @param int Format (optional) Format type must be defined by the backend + * @param int Number of items to return (optional) Returns all by default + * @return Return depends on format + */ + public static function getUsersSharingFile( $path ) { + + // Fetch all shares of this file path from DB + $query = \OC_DB::prepare( + 'SELECT + share_type + , share_with + , permissions + FROM + `*PREFIX*share` + WHERE + file_target = ?' + ); + + $result = $query->execute( array( $path ) ); + + if ( \OC_DB::isError( $result ) ) { + + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result) . ', path=' . $path, \OC_Log::ERROR ); + + } + + $shares = array(); + + while( $row = $result->fetchRow() ) { + + // Set helpful array keys + $shares[] = array( + 'userId' => $row['share_with'] + , 'shareType' => $row['share_type'] + , 'permissions' => $row['permissions'] + ); + + } + + if ( ! empty( $shares ) ) { + + return $shares; + + } else { + + return false; + + } + + } /** * @brief Get the items of item type shared with the current user From 92f06243be62945b5ff5e7542e9984f7bb45d74b Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Mon, 11 Feb 2013 10:21:23 +0000 Subject: [PATCH 003/257] Implementing sharing support New file-specific methods in lib/public/share Changes to how keyfiles are stored --- apps/files_encryption/hooks/hooks.php | 51 +++++----- apps/files_encryption/lib/crypt.php | 41 +++++--- apps/files_encryption/lib/keymanager.php | 97 ++++++++++++++++-- apps/files_encryption/lib/proxy.php | 119 +++++++++++++---------- apps/files_encryption/test/crypt.php | 8 +- lib/public/share.php | 84 ++++++++++++++-- 6 files changed, 289 insertions(+), 111 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index c6d4c16115..9252a341fb 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -82,8 +82,12 @@ class Hooks { } + \OC_FileProxy::$enabled = false; + $publicKey = Keymanager::getPublicKey( $view, $params['uid'] ); + \OC_FileProxy::$enabled = false; + // Encrypt existing user files: // This serves to upgrade old versions of the encryption // app (see appinfo/spec.txt) @@ -175,8 +179,9 @@ class Hooks { $view = new \OC_FilesystemView( '/' ); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); + $session = new Session(); - $shares = \OCP\Share::getUsersSharingFile( $params['fileTarget'] ); + $shares = \OCP\Share::getUsersSharingFile( $params['fileTarget'], 1 ); $userIds = array(); @@ -202,41 +207,35 @@ class Hooks { } - trigger_error("UIDS = ".var_export($userIds, 1)); - $userPubKeys = Keymanager::getPublicKeys( $view, $userIds ); -// trigger_error("PUB KEYS = ".var_export($userPubKeys, 1)); + \OC_FileProxy::$enabled = false; - // TODO: Fetch path from Crypt{} getter - $plainContent = $view->file_get_contents( $userId . '/' . 'files'. '/' . $params['fileTarget'] ); + // get the keyfile + $encKeyfile = Keymanager::getFileKey( $view, $userId, $params['fileTarget'] ); - // Generate new catfile and share keys - if ( ! $encrypted = Crypt::multiKeyEncrypt( $plainContent, $userPubKeys ) ) { + $privateKey = $session->getPrivateKey(); - // If the re-encryption failed, don't risk deleting data - return false; + // decrypt the keyfile + $plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey ); + + // re-enc keyfile to sharekeys + $shareKeys = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys ); + + // save sharekeys + if ( ! Keymanager::setShareKeys( $view, $params['fileTarget'], $shareKeys['keys'] ) ) { + + trigger_error( "SET Share keys failed" ); } - trigger_error("ENCRYPTED = ". var_export($encrypted, 1)); - - // Save env keys to user folders - foreach ( $encrypted['keys'] as $key ) { - -// Keymanager::setShareKey( $view, $params['fileTarget'], $userId, $key ); - - } - - // Delete existing catfile - // Check if keyfile exists (it won't if file has been shared before) + // Delete existing keyfile // Do this last to ensure file is recoverable in case of error - if ( $util->isEncryptedPath( $params['fileTarget'] ) ) { - - // NOTE: This will trigger an error if keyfile isn't found -// Keymanager::deleteFileKey( $params['fileTarget'] ); +// Keymanager::deleteFileKey( $view, $userId, $params['fileTarget'] ); - } + \OC_FileProxy::$enabled = true; + + return true; } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index e3d23023db..fdee03eeaf 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -370,22 +370,41 @@ class Crypt { /** * @brief Create asymmetrically encrypted keyfile content using a generated key * @param string $plainContent content to be encrypted - * @returns array keys: key, encrypted - * @note symmetricDecryptFileContent() can be used to decrypt files created using this method - * - * This function decrypts a file + * @param array $publicKeys array keys must be the userId of corresponding user + * @returns array keys: keys (array, key = userId), encrypted + * @note symmetricDecryptFileContent() can decrypt files created using this method */ public static function multiKeyEncrypt( $plainContent, array $publicKeys ) { - + + // openssl_seal returns false without errors if $plainContent + // is empty, so trigger our own error + if ( empty( $plainContent ) ) { + + trigger_error( "Cannot mutliKeyEncrypt empty plain content" ); + throw new \Exception( 'Cannot mutliKeyEncrypt empty plain content' ); + + } + // Set empty vars to be set by openssl by reference $sealed = ''; - $envKeys = array(); + $shareKeys = array(); - if( openssl_seal( $plainContent, $sealed, $envKeys, $publicKeys ) ) { + if( openssl_seal( $plainContent, $sealed, $shareKeys, $publicKeys ) ) { + + $i = 0; + + // Ensure each shareKey is labelled with its + // corresponding userId + foreach ( $publicKeys as $userId => $publicKey ) { + + $mappedShareKeys[$userId] = $shareKeys[$i]; + $i++; + + } return array( - 'keys' => $envKeys - , 'encrypted' => $sealed + 'keys' => $mappedShareKeys + , 'data' => $sealed ); } else { @@ -404,7 +423,7 @@ class Crypt { * * This function decrypts a file */ - public static function multiKeyDecrypt( $encryptedContent, $envKey, $privateKey ) { + public static function multiKeyDecrypt( $encryptedContent, $shareKey, $privateKey ) { if ( !$encryptedContent ) { @@ -412,7 +431,7 @@ class Crypt { } - if ( openssl_open( $encryptedContent, $plainContent, $envKey, $privateKey ) ) { + if ( openssl_open( $encryptedContent, $plainContent, $shareKey, $privateKey ) ) { return $plainContent; diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 3160572ba1..5f9eea1a0b 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -52,8 +52,11 @@ class Keymanager { */ public static function getPublicKey( \OC_FilesystemView $view, $userId ) { + \OC_FileProxy::$enabled = false; + return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' ); + \OC_FileProxy::$enabled = true; } /** @@ -77,20 +80,16 @@ class Keymanager { * @param array $userIds * @return array of public keys for the specified users */ - public static function getPublicKeys( \OC_FilesystemView $view, $userIds ) { + public static function getPublicKeys( \OC_FilesystemView $view, array $userIds ) { - $i = 0; $keys = array(); foreach ( $userIds as $userId ) { - $i++; $keys[$userId] = self::getPublicKey( $view, $userId ); } - $keys['total'] = $i; - return $keys; } @@ -137,11 +136,11 @@ class Keymanager { $filePath_f = ltrim( $filePath, '/' ); - $catfilePath = '/' . $userId . '/files_encryption/keyfiles/' . $filePath_f . '.key'; + $keyfilePath = '/' . $userId . '/files_encryption/keyfiles/' . $filePath_f . '.key'; - if ( $view->file_exists( $catfilePath ) ) { + if ( $view->file_exists( $keyfilePath ) ) { - return $view->file_get_contents( $catfilePath ); + return $view->file_get_contents( $keyfilePath ); } else { @@ -239,7 +238,7 @@ class Keymanager { } /** - * @brief store file encryption key + * @brief store share key * * @param string $path relative path of the file, including filename * @param string $key @@ -255,7 +254,85 @@ class Keymanager { $shareKeyPath = self::keySetPreparation( $view, $path, $basePath, $userId ); - return $view->file_put_contents( $basePath . '/' . $shareKeyPath . '.shareKey', $shareKey ); + $writePath = $basePath . '/' . $shareKeyPath . '.shareKey'; + + \OC_FileProxy::$enabled = false; + + $result = $view->file_put_contents( $writePath, $shareKey ); + + if ( + is_int( $result ) + && $result > 0 + ) { + + return true; + + } else { + + return false; + + } + + } + + /** + * @brief store multiple share keys for a single file + * @return bool + */ + public static function setShareKeys( \OC_FilesystemView $view, $path, array $shareKeys ) { + + // $shareKeys must be an array with the following format: + // [userId] => [encrypted key] + + $result = true; + + foreach ( $shareKeys as $userId => $shareKey ) { + + if ( ! self::setShareKey( $view, $path, $userId, $shareKey ) ) { + + // If any of the keys are not set, flag false + $result = false; + + } + + } + + // Returns false if any of the keys weren't set + return $result; + + } + + /** + * @brief retrieve shareKey for an encrypted file + * @param \OC_FilesystemView $view + * @param $userId + * @param $filePath + * @internal param \OCA\Encryption\file $string name + * @return string file key or false + * @note The sharekey returned is encrypted. Decryption + * of the keyfile must be performed by client code + */ + public static function getShareKey( \OC_FilesystemView $view, $userId, $filePath ) { + + \OC_FileProxy::$enabled = false; + + $filePath_f = ltrim( $filePath, '/' ); + + $shareKeyPath = '/' . $userId . '/files_encryption/share-keys/' . $filePath_f . '.shareKey'; + + if ( $view->file_exists( $shareKeyPath ) ) { + + $result = $view->file_get_contents( $shareKeyPath ); + + } else { + + $result = false; + + } + + \OC_FileProxy::$enabled = true; + + return $result; } diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 58b9bc0725..b5e59e89b9 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -99,58 +99,65 @@ class Proxy extends \OC_FileProxy { if ( !is_resource( $data ) ) { $userId = \OCP\USER::getUser(); - $rootView = new \OC_FilesystemView( '/' ); - + $util = new Util( $rootView, $userId ); + $filePath = $util->stripUserFilesPath( $path ); // Set the filesize for userland, before encrypting $size = strlen( $data ); // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; - $fileOwner = \OC\Files\Filesystem::getOwner( $path ); + // Encrypt data + $encData = Crypt::symmetricEncryptFileContentKeyfile( $data ); // Check if the keyfile needs to be shared - if ( - $fileOwner !== true - or $fileOwner !== $userId - ) { + if ( \OCP\Share::isSharedFile( $filePath ) ) { + +// $fileOwner = \OC\Files\Filesystem::getOwner( $path ); + + // List everyone sharing the file + $shares = \OCP\Share::getUsersSharingFile( $filePath, 1 ); + + $userIds = array(); + + foreach ( $shares as $share ) { + + $userIds[] = $share['userId']; + + } + + $publicKeys = Keymanager::getPublicKeys( $rootView, $userIds ); + + \OC_FileProxy::$enabled = false; + + // Encrypt plain keyfile to multiple sharefiles + $multiEncrypted = Crypt::multiKeyEncrypt( $encData['key'], $publicKeys ); + + // Save sharekeys to user folders + Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] ); + + // Set encrypted keyfile as common varname + $encKey = $multiEncrypted['encrypted']; - // Shared storage backend isn't loaded - $users = \OCP\Share::getItemShared( 'file', $path, \OC_Share_backend_File::FORMAT_SHARED_STORAGE ); -// - trigger_error("SHARE USERS = ". var_export($users, 1)); -// -// $publicKeys = Keymanager::getPublicKeys( $rootView, $users); -// -// // Encrypt plain data to multiple users -// $encrypted = Crypt::multiKeyEncrypt( $data, $publicKeys ); } else { $publicKey = Keymanager::getPublicKey( $rootView, $userId ); // Encrypt plain data to a single user - $encrypted = Crypt::keyEncryptKeyfile( $data, $publicKey ); + $encKey = Crypt::keyEncrypt( $encData['key'], $publicKey ); } - // Replace plain content with encrypted content by reference - $data = $encrypted['data']; - - $filePath = explode( '/', $path ); - - $filePath = array_slice( $filePath, 3 ); - - $filePath = '/' . implode( '/', $filePath ); - - // TODO: make keyfile dir dynamic from app config - - $view = new \OC_FilesystemView( '/' ); + // TODO: Replace userID with ownerId so keyfile is saved centrally // Save keyfile for newly encrypted file in parallel directory tree - Keymanager::setFileKey( $view, $filePath, $userId, $encrypted['key'] ); + Keymanager::setFileKey( $rootView, $filePath, $userId, $encKey ); + + // Replace plain content with encrypted content by reference + $data = $encData['encrypted']; // Update the file cache with file info \OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' ); @@ -168,8 +175,6 @@ class Proxy extends \OC_FileProxy { * @param string $data Data that has been read from file */ public function postFile_get_contents( $path, $data ) { - - // TODO: Use dependency injection to add required args for view and user etc. to this method // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; @@ -180,45 +185,55 @@ class Proxy extends \OC_FileProxy { && Crypt::isCatfile( $data ) ) { - $split = explode( '/', $path ); - - $filePath = array_slice( $split, 3 ); - - $filePath = '/' . implode( '/', $filePath ); - - //$cached = \OC\Files\Filesystem::getFileInfo( $path, '' ); - - $view = new \OC_FilesystemView( '' ); - + $view = new \OC_FilesystemView( '/' ); $userId = \OCP\USER::getUser(); - - // TODO: Check if file is shared, if so, use multiKeyDecrypt - - $encryptedKeyfile = Keymanager::getFileKey( $view, $userId, $filePath ); - $session = new Session(); + $util = new Util( $view, $userId ); + $filePath = $util->stripUserFilesPath( $path ); + $privateKey = $session->getPrivateKey( $userId ); - $decrypted = Crypt::keyDecryptKeyfile( $data, $encryptedKeyfile, $session->getPrivateKey( $split[1] ) ); + // Get the encrypted keyfile + $encKeyfile = Keymanager::getFileKey( $view, $userId, $filePath ); + // Check if key is shared or not + if ( \OCP\Share::isSharedFile( $filePath ) ) { + + // If key is shared, fetch the user's shareKey + $shareKey = Keymanager::getShareKey( $view, $userId, $filePath ); + + \OC_FileProxy::$enabled = false; + + // Decrypt keyfile with shareKey + $plainKeyfile = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); + + } else { + + // If key is unshared, decrypt with user private key + $plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey ); + + } + + $plainData = Crypt::symmetricDecryptFileContent( $data, $plainKeyfile ); + } elseif ( Crypt::mode() == 'server' && isset( $_SESSION['legacyenckey'] ) && Crypt::isEncryptedMeta( $path ) ) { - $decrypted = Crypt::legacyDecrypt( $data, $_SESSION['legacyenckey'] ); + $plainData = Crypt::legacyDecrypt( $data, $session->getLegacyKey() ); } \OC_FileProxy::$enabled = true; - if ( ! isset( $decrypted ) ) { + if ( ! isset( $plainData ) ) { - $decrypted = $data; + $plainData = $data; } - return $decrypted; + return $plainData; } diff --git a/apps/files_encryption/test/crypt.php b/apps/files_encryption/test/crypt.php index aa87ec3282..48ad2ee007 100755 --- a/apps/files_encryption/test/crypt.php +++ b/apps/files_encryption/test/crypt.php @@ -439,14 +439,14 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { $this->assertTrue( strlen( $pair1['privateKey'] ) > 1 ); - $crypted = Encryption\Crypt::multiKeyEncrypt( $this->dataUrl, array( $pair1['publicKey'] ) ); + $crypted = Encryption\Crypt::multiKeyEncrypt( $this->dataShort, array( $pair1['publicKey'] ) ); - $this->assertNotEquals( $this->dataUrl, $crypted['encrypted'] ); + $this->assertNotEquals( $this->dataShort, $crypted['data'] ); - $decrypt = Encryption\Crypt::multiKeyDecrypt( $crypted['encrypted'], $crypted['keys'][0], $pair1['privateKey'] ); + $decrypt = Encryption\Crypt::multiKeyDecrypt( $crypted['data'], $crypted['keys'][0], $pair1['privateKey'] ); - $this->assertEquals( $this->dataUrl, $decrypt ); + $this->assertEquals( $this->dataShort, $decrypt ); } diff --git a/lib/public/share.php b/lib/public/share.php index 936f85021c..4170783d71 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -93,19 +93,72 @@ class Share { } /** - * @brief Find which users can access a shared item - * @param string Item type - * @param int Format (optional) Format type must be defined by the backend - * @param int Number of items to return (optional) Returns all by default - * @return Return depends on format + * @brief Prepare a path to be passed to DB as file_target + * @return string Prepared path */ - public static function getUsersSharingFile( $path ) { + public static function prepFileTarget( $path ) { + + // Paths in DB are stored with leading slashes, so add one if necessary + if ( substr( $path, 0, 1 ) !== '/' ) { + + $path = '/' . $path; + + } + + return $path; + + } + + public static function isSharedFile( $path ) { + + $fPath = self::prepFileTarget( $path ); + + // Fetch all shares of this file path from DB + $query = \OC_DB::prepare( + 'SELECT + id + FROM + `*PREFIX*share` + WHERE + file_target = ?' + ); + + $result = $query->execute( array( $fPath ) ); + + if ( \OC_DB::isError( $result ) ) { + + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage( $result ) . ', path=' . $fPath, \OC_Log::ERROR ); + + } + + if ( $result->fetchRow() !== false ) { + + return true; + + } else { + + return false; + + } + + } + + /** + * @brief Find which users can access a shared item + * @return bool / array + * @note $path needs to be relative to user data dir, e.g. 'file.txt' + * not '/admin/data/file.txt' + */ + public static function getUsersSharingFile( $path, $includeOwner = 0 ) { + + $fPath = self::prepFileTarget( $path ); // Fetch all shares of this file path from DB $query = \OC_DB::prepare( 'SELECT share_type , share_with + , uid_owner , permissions FROM `*PREFIX*share` @@ -113,11 +166,11 @@ class Share { file_target = ?' ); - $result = $query->execute( array( $path ) ); + $result = $query->execute( array( $fPath ) ); if ( \OC_DB::isError( $result ) ) { - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result) . ', path=' . $path, \OC_Log::ERROR ); + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result) . ', path=' . $fPath, \OC_Log::ERROR ); } @@ -128,6 +181,7 @@ class Share { // Set helpful array keys $shares[] = array( 'userId' => $row['share_with'] + , 'owner' => $row['uid_owner'] // we just set this so it can be used once, hugly hack :/ , 'shareType' => $row['share_type'] , 'permissions' => $row['permissions'] ); @@ -136,6 +190,20 @@ class Share { if ( ! empty( $shares ) ) { + // Include owner in list of users, if requested + if ( $includeOwner == 1 ) { + + // NOTE: The values are incorrect for shareType and + // permissions of the owner; we just include them for + // optional convenience + $shares[] = array( + 'userId' => $shares[0]['owner'] + , 'shareType' => 0 + , 'permissions' => 0 + ); + + } + return $shares; } else { From d17d838eccb4e8752fc59c2a6812d69a8a5b707e Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Mon, 11 Feb 2013 10:34:23 +0000 Subject: [PATCH 004/257] Updated specfile --- apps/files_encryption/appinfo/spec.txt | 30 +++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/apps/files_encryption/appinfo/spec.txt b/apps/files_encryption/appinfo/spec.txt index 2d22dffe08..7a937a9143 100644 --- a/apps/files_encryption/appinfo/spec.txt +++ b/apps/files_encryption/appinfo/spec.txt @@ -9,6 +9,31 @@ Encrypted files [encrypted data string][delimiter][IV][padding] [anhAAjAmcGXqj1X9g==][00iv00][MSHU5N5gECP7aAg7][xx] (square braces added) + +- Directory structure: + - Encrypted user data (catfiles) are stored in the usual /data/user/files dir + - Keyfiles are stored in /data/user/files_encryption/keyfiles + - Sharekey are stored in /data/user/files_encryption/share-files + +- File extensions: + - Catfiles have keep the file extension of the original file, pre-encryption + - Keyfiles use .keyfile + - Sharekeys have .shareKey + +Shared files +------------ + +Shared files have a centrally stored catfile and keyfile, and one sharekey for +each user that shares it. + +When sharing is used, a different encryption method is used to encrypt the +keyfile (openssl_seal). Although shared files have a keyfile, its contents +use a different format therefore. + +Each time a shared file is edited or deleted, all sharekeys for users sharing +that file must have their sharekeys changed also. The keyfile and catfile +however need only changing in the owners files, as there is only one copy of +these. Notes ----- @@ -16,4 +41,7 @@ Notes - The user passphrase is required in order to set up or upgrade the app. New keypair generation, and the re-encryption of legacy encrypted files requires it. Therefore an appinfo/update.php script cannot be used, and upgrade logic - is handled in the login hook listener. \ No newline at end of file + is handled in the login hook listener. Therefore each time the user logs in + their files are scanned to detect unencrypted and legacy encrypted files, and + they are (re)encrypted as necessary. This may present a performance issue; we + need to monitor this. \ No newline at end of file From 2787aafae6577dfad1f3db0dc70a8e0b05eaba53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 11 Feb 2013 12:12:21 +0100 Subject: [PATCH 005/257] added some TODOs --- apps/files_encryption/hooks/hooks.php | 1 + apps/files_encryption/lib/proxy.php | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 9252a341fb..b0075a3ada 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -190,6 +190,7 @@ class Hooks { $util = new Util( $view, $share['userId'] ); // Check that the user is encryption capable + // TODO create encryption key when user gets created if ( $util->ready() ) { // Construct array of just UIDs for Keymanager{} diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index b5e59e89b9..40ac411539 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -92,12 +92,13 @@ class Proxy extends \OC_FileProxy { } public function preFile_put_contents( $path, &$data ) { - + // TODO check for existing key file and reuse it if possible to avoid problems with versioning etc. if ( self::shouldEncrypt( $path ) ) { // Stream put contents should have been converted to fopen if ( !is_resource( $data ) ) { + // TODO check who is the owner of the file in case of shared folders $userId = \OCP\USER::getUser(); $rootView = new \OC_FilesystemView( '/' ); $util = new Util( $rootView, $userId ); @@ -175,7 +176,7 @@ class Proxy extends \OC_FileProxy { * @param string $data Data that has been read from file */ public function postFile_get_contents( $path, $data ) { - + // TODO check for existing key file and reuse it if possible to avoid problems with versioning etc. // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; @@ -184,8 +185,8 @@ class Proxy extends \OC_FileProxy { Crypt::mode() == 'server' && Crypt::isCatfile( $data ) ) { - $view = new \OC_FilesystemView( '/' ); + // TODO use get owner to find correct location of key files for shared files $userId = \OCP\USER::getUser(); $session = new Session(); $util = new Util( $view, $userId ); From 3e3cee98c87e90ece7a4a908b6cbbc7cbc94aac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 11 Feb 2013 13:28:37 +0100 Subject: [PATCH 006/257] - moved the enrcyption of the filekey ifg file gets shared from the post shared hook to Crypt::encKeyfileToMultipleUsers() because this can be reused if files get unshared - switch from preUnshare hook to postUnshare hook because afterward we can simply get the updated list of users with access to the file and call Crypt::encKeyfileToMultipleUsers() --- apps/files_encryption/appinfo/app.php | 4 +- apps/files_encryption/hooks/hooks.php | 55 +++++++-------------------- apps/files_encryption/lib/crypt.php | 42 ++++++++++++++++++++ 3 files changed, 58 insertions(+), 43 deletions(-) diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index f83109a18e..6778e1faa3 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -16,8 +16,8 @@ OCP\Util::connectHook( 'OC_User', 'pre_setPassword','OCA\Encryption\Hooks', 'set // Sharing-related hooks OCP\Util::connectHook( 'OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared' ); -OCP\Util::connectHook( 'OCP\Share', 'pre_unshare', 'OCA\Encryption\Hooks', 'preUnshare' ); -OCP\Util::connectHook( 'OCP\Share', 'pre_unshareAll', 'OCA\Encryption\Hooks', 'preUnshareAll' ); +OCP\Util::connectHook( 'OCP\Share', 'post_unshare', 'OCA\Encryption\Hooks', 'postUnshare' ); +OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', 'postUnshareAll' ); // Webdav-related hooks OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfile' ); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index b0075a3ada..c8565964ba 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -179,7 +179,6 @@ class Hooks { $view = new \OC_FilesystemView( '/' ); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); - $session = new Session(); $shares = \OCP\Share::getUsersSharingFile( $params['fileTarget'], 1 ); @@ -207,55 +206,29 @@ class Hooks { } } + + return Crypt::encKeyfileToMultipleUsers($shares, $params['fileTarget']); - $userPubKeys = Keymanager::getPublicKeys( $view, $userIds ); + } + + /** + * @brief + */ + public static function postUnshare( $params ) { + $shares = \OCP\Share::getUsersSharingFile( $params['fileTarget'], 1 ); - \OC_FileProxy::$enabled = false; - - // get the keyfile - $encKeyfile = Keymanager::getFileKey( $view, $userId, $params['fileTarget'] ); - - $privateKey = $session->getPrivateKey(); - - // decrypt the keyfile - $plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey ); - - // re-enc keyfile to sharekeys - $shareKeys = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys ); - - // save sharekeys - if ( ! Keymanager::setShareKeys( $view, $params['fileTarget'], $shareKeys['keys'] ) ) { - - trigger_error( "SET Share keys failed" ); - + $userIds = array(); + foreach ( $shares as $share ) { + $userIds[] = $share['userId']; } - // Delete existing keyfile - // Do this last to ensure file is recoverable in case of error -// Keymanager::deleteFileKey( $view, $userId, $params['fileTarget'] ); - - \OC_FileProxy::$enabled = true; - - return true; - + return Crypt::encKeyfileToMultipleUsers($userIDs, $params['fileTarget']); } /** * @brief */ - public static function preUnshare( $params ) { - - // Delete existing catfile - - // Generate new catfile and env keys - - // Save env keys to user folders - } - - /** - * @brief - */ - public static function preUnshareAll( $params ) { + public static function postUnshareAll( $params ) { trigger_error( "preUnshareAll" ); diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index fdee03eeaf..6704ea6bf1 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -744,4 +744,46 @@ class Crypt { } + + /** + * @brief encrypt file key to multiple users + * @param $users list of users which should be able to access the file + * @param $fileTarget target of the file + */ + public static function encKeyfileToMultipleUsers($users, $fileTarget) { + $view = new \OC_FilesystemView( '/' ); + $userId = \OCP\User::getUser(); + $util = new Util( $view, $userId ); + $session = new Session(); + + $userPubKeys = Keymanager::getPublicKeys( $view, $users ); + + \OC_FileProxy::$enabled = false; + + // get the keyfile + $encKeyfile = Keymanager::getFileKey( $view, $userId, $fileTarget ); + + $privateKey = $session->getPrivateKey(); + + // decrypt the keyfile + $plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey ); + + // re-enc keyfile to sharekeys + $shareKeys = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys ); + + // save sharekeys + if ( ! Keymanager::setShareKeys( $view, $fileTarget, $shareKeys['keys'] ) ) { + + trigger_error( "SET Share keys failed" ); + + } + + // Delete existing keyfile + // Do this last to ensure file is recoverable in case of error + // Keymanager::deleteFileKey( $view, $userId, $params['fileTarget'] ); + + \OC_FileProxy::$enabled = true; + + return true; + } } \ No newline at end of file From 9b498320903fc7d35e2e0bcfd03ebf69e7c90720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 11 Feb 2013 13:50:11 +0100 Subject: [PATCH 007/257] unshare all should work the same like unshare single users --- apps/files_encryption/hooks/hooks.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index c8565964ba..550593daf6 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -229,9 +229,7 @@ class Hooks { * @brief */ public static function postUnshareAll( $params ) { - - trigger_error( "preUnshareAll" ); - + return self::postUnshare($params); } } From 5a64c96d06db50c3ca13bb3c6c10c3a0e32a3380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 11 Feb 2013 15:13:42 +0100 Subject: [PATCH 008/257] go back to preUnshare hooks since sharing doesn't trigger post unshare hooks --- apps/files_encryption/appinfo/app.php | 4 ++-- apps/files_encryption/hooks/hooks.php | 19 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 6778e1faa3..f83109a18e 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -16,8 +16,8 @@ OCP\Util::connectHook( 'OC_User', 'pre_setPassword','OCA\Encryption\Hooks', 'set // Sharing-related hooks OCP\Util::connectHook( 'OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared' ); -OCP\Util::connectHook( 'OCP\Share', 'post_unshare', 'OCA\Encryption\Hooks', 'postUnshare' ); -OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', 'postUnshareAll' ); +OCP\Util::connectHook( 'OCP\Share', 'pre_unshare', 'OCA\Encryption\Hooks', 'preUnshare' ); +OCP\Util::connectHook( 'OCP\Share', 'pre_unshareAll', 'OCA\Encryption\Hooks', 'preUnshareAll' ); // Webdav-related hooks OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfile' ); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 550593daf6..17bcb9238a 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -157,8 +157,6 @@ class Hooks { , \OC_Log::ERROR ); - error_log( "Client side encryption is enabled but the client doesn't provide an encryption key for the file!" ); - } } @@ -169,7 +167,7 @@ class Hooks { * @brief */ public static function postShared( $params ) { - + error_log("post shared triggered!"); // NOTE: $params is an array with these keys: // itemSource -> int, filecache file ID // shareWith -> string, uid of user being shared to @@ -214,22 +212,27 @@ class Hooks { /** * @brief */ - public static function postUnshare( $params ) { - $shares = \OCP\Share::getUsersSharingFile( $params['fileTarget'], 1 ); + public static function preUnshare( $params ) { + $items = \OCP\Share::getItemSharedWithBySource($params['itemType'], $params['itemSource']); + $shares = \OCP\Share::getUsersSharingFile( $item[0]['file_target'], 1 ); $userIds = array(); foreach ( $shares as $share ) { $userIds[] = $share['userId']; } - return Crypt::encKeyfileToMultipleUsers($userIDs, $params['fileTarget']); + // remove the user from the list from which the file will be unshared + unset($userIds[$params['shareWith']]); + + return Crypt::encKeyfileToMultipleUsers($userIDs, $item[0]['file_target']); } /** * @brief */ - public static function postUnshareAll( $params ) { - return self::postUnshare($params); + public static function preUnshareAll( $params ) { + $items = \OCP\Share::getItemSharedWithBySource($params['itemType'], $params['itemSource']); + return Crypt::encKeyfileToMultipleUsers(array($items[0]['uid_owner']), $items[0]['file_target']); } } From 8eef919a754ff3404df1065d616e66cb9b1ff437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 12 Feb 2013 12:08:34 +0100 Subject: [PATCH 009/257] take group shares into account if we retrieve the list a all recipients --- apps/files_encryption/hooks/hooks.php | 35 +++----------- apps/files_encryption/lib/crypt.php | 30 ++++++++++-- lib/public/share.php | 69 +++++++++++++-------------- 3 files changed, 65 insertions(+), 69 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 17bcb9238a..c14ce3e91d 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -167,44 +167,21 @@ class Hooks { * @brief */ public static function postShared( $params ) { - error_log("post shared triggered!"); + // NOTE: $params is an array with these keys: // itemSource -> int, filecache file ID // shareWith -> string, uid of user being shared to // fileTarget -> path of file being shared // uidOwner -> owner of the original file being shared + //TODO: We don't deal with shared folder yet, need to recursively update every file in the folder + $view = new \OC_FilesystemView( '/' ); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); - $shares = \OCP\Share::getUsersSharingFile( $params['fileTarget'], 1 ); + $shares = \OCP\Share::getUsersSharingFile( $params['itemSource'], 1 ); - $userIds = array(); - - foreach ( $shares as $share ) { - - $util = new Util( $view, $share['userId'] ); - - // Check that the user is encryption capable - // TODO create encryption key when user gets created - if ( $util->ready() ) { - - // Construct array of just UIDs for Keymanager{} - $userIds[] = $share['userId']; - - } else { - - // Log warning; we can't do necessary setup here - // because we don't have the user passphrase - // TODO: Provide user feedback indicating that - // sharing failed - \OC_Log::write( 'Encryption library', 'File cannot be shared: user "'.$share['userId'].'" is not setup for encryption', \OC_Log::WARN ); - - } - - } - return Crypt::encKeyfileToMultipleUsers($shares, $params['fileTarget']); } @@ -213,11 +190,11 @@ class Hooks { * @brief */ public static function preUnshare( $params ) { - $items = \OCP\Share::getItemSharedWithBySource($params['itemType'], $params['itemSource']); - $shares = \OCP\Share::getUsersSharingFile( $item[0]['file_target'], 1 ); + $shares = \OCP\Share::getUsersSharingFile( $params['itemSource'], 1 ); $userIds = array(); foreach ( $shares as $share ) { + error_log("keek user id: " . $share['userId']); $userIds[] = $share['userId']; } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 6704ea6bf1..a8cc2b3726 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -752,16 +752,40 @@ class Crypt { */ public static function encKeyfileToMultipleUsers($users, $fileTarget) { $view = new \OC_FilesystemView( '/' ); - $userId = \OCP\User::getUser(); + $owner = \OCP\User::getUser(); $util = new Util( $view, $userId ); $session = new Session(); + + $userIds = array(); + + foreach ( $users as $user ) { + + $util = new Util( $view, $user ); + + // Check that the user is encryption capable + if ( $util->ready() ) { + // Construct array of just UIDs for Keymanager{} + $userIds[] = $user; + + } else { + + // Log warning; we can't do necessary setup here + // because we don't have the user passphrase + // TODO: Provide user feedback indicating that + // sharing failed + \OC_Log::write( 'Encryption library', 'File cannot be shared: user "'.$user.'" is not setup for encryption', \OC_Log::WARN ); + + } + + } + - $userPubKeys = Keymanager::getPublicKeys( $view, $users ); + $userPubKeys = Keymanager::getPublicKeys( $view, $userIds ); \OC_FileProxy::$enabled = false; // get the keyfile - $encKeyfile = Keymanager::getFileKey( $view, $userId, $fileTarget ); + $encKeyfile = Keymanager::getFileKey( $view, $owner, $fileTarget ); $privateKey = $session->getPrivateKey(); diff --git a/lib/public/share.php b/lib/public/share.php index 4170783d71..841240692d 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -149,62 +149,57 @@ class Share { * @note $path needs to be relative to user data dir, e.g. 'file.txt' * not '/admin/data/file.txt' */ - public static function getUsersSharingFile( $path, $includeOwner = 0 ) { - - $fPath = self::prepFileTarget( $path ); - + public static function getUsersSharingFile( $source, $includeOwner = 0 ) { + //TODO get also the recipients from folders which are shared above the current file // Fetch all shares of this file path from DB $query = \OC_DB::prepare( - 'SELECT - share_type - , share_with - , uid_owner - , permissions + 'SELECT share_with FROM `*PREFIX*share` WHERE - file_target = ?' + item_source = ? AND share_type = ? AND uid_owner = ?' ); - $result = $query->execute( array( $fPath ) ); + $result = $query->execute( array( $source, self::SHARE_TYPE_USER, \OCP\User::getUser() ) ); if ( \OC_DB::isError( $result ) ) { - - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result) . ', path=' . $fPath, \OC_Log::ERROR ); - + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); } $shares = array(); while( $row = $result->fetchRow() ) { - - // Set helpful array keys - $shares[] = array( - 'userId' => $row['share_with'] - , 'owner' => $row['uid_owner'] // we just set this so it can be used once, hugly hack :/ - , 'shareType' => $row['share_type'] - , 'permissions' => $row['permissions'] - ); - + $shares[] = $row['share_with']; } - if ( ! empty( $shares ) ) { + // We also need to take group shares into account + $query = \OC_DB::prepare( + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ? AND uid_owner = ?' + ); + + $result = $query->execute( array( $source, self::SHARE_TYPE_GROUP, \OCP\User::getUser() ) ); + + if ( \OC_DB::isError( $result ) ) { + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); + } + + while( $row = $result->fetchRow() ) { + $usersInGroup = \OC_Group::usersInGroup($row['share_with']); + $shares = array_merge($shares, $usersInGroup); + } + + if ( ! empty( $shares ) ) { // Include owner in list of users, if requested if ( $includeOwner == 1 ) { - - // NOTE: The values are incorrect for shareType and - // permissions of the owner; we just include them for - // optional convenience - $shares[] = array( - 'userId' => $shares[0]['owner'] - , 'shareType' => 0 - , 'permissions' => 0 - ); - + $shares[] = \OCP\User::getUser(); } - - return $shares; + + return array_unique($shares); } else { @@ -235,7 +230,7 @@ class Share { public static function getItemSharedWith($itemType, $itemTarget, $format = self::FORMAT_NONE, $parameters = null, $includeCollections = false) { return self::getItems($itemType, $itemTarget, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format, $parameters, 1, $includeCollections); } - + /** * @brief Get the item of item type shared with the current user by source * @param string Item type From 1e5d03da800e5ad36e7b5adbab7eef03a2add80c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 12 Feb 2013 12:45:54 +0100 Subject: [PATCH 010/257] use right location of the file is the source and not the target it is shared to --- apps/files_encryption/hooks/hooks.php | 32 ++++++++++++++++----------- apps/files_encryption/lib/crypt.php | 6 ++--- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index c14ce3e91d..ebc345a47e 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -163,6 +163,20 @@ class Hooks { } + /** + * @brief get path of a file. + * @param $fileId id of the file + * @return path of the file + */ + private static function getFilePath($fileId) { + $query = \OC_DB::prepare('SELECT `path`' + .' FROM `*PREFIX*filecache`' + .' WHERE `fileid` = ?'); + $result = $query->execute(array($fileId)); + $row = $result->fetchRow(); + return $row['path']; + } + /** * @brief */ @@ -182,7 +196,7 @@ class Hooks { $shares = \OCP\Share::getUsersSharingFile( $params['itemSource'], 1 ); - return Crypt::encKeyfileToMultipleUsers($shares, $params['fileTarget']); + return Crypt::encKeyfileToMultipleUsers($shares, self::getFilePath($params['itemSource'])); } @@ -191,25 +205,17 @@ class Hooks { */ public static function preUnshare( $params ) { $shares = \OCP\Share::getUsersSharingFile( $params['itemSource'], 1 ); - - $userIds = array(); - foreach ( $shares as $share ) { - error_log("keek user id: " . $share['userId']); - $userIds[] = $share['userId']; - } - // remove the user from the list from which the file will be unshared - unset($userIds[$params['shareWith']]); - - return Crypt::encKeyfileToMultipleUsers($userIDs, $item[0]['file_target']); + unset($shares[$params['shareWith']]); + + return Crypt::encKeyfileToMultipleUsers($shares, self::getFilePath($params['itemSource'])); } /** * @brief */ public static function preUnshareAll( $params ) { - $items = \OCP\Share::getItemSharedWithBySource($params['itemType'], $params['itemSource']); - return Crypt::encKeyfileToMultipleUsers(array($items[0]['uid_owner']), $items[0]['file_target']); + return Crypt::encKeyfileToMultipleUsers(array(\OCP\User::getUser()), self::getFilePath($params['itemSource'])); } } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index a8cc2b3726..cbdae323e5 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -750,7 +750,7 @@ class Crypt { * @param $users list of users which should be able to access the file * @param $fileTarget target of the file */ - public static function encKeyfileToMultipleUsers($users, $fileTarget) { + public static function encKeyfileToMultipleUsers($users, $filePath) { $view = new \OC_FilesystemView( '/' ); $owner = \OCP\User::getUser(); $util = new Util( $view, $userId ); @@ -785,7 +785,7 @@ class Crypt { \OC_FileProxy::$enabled = false; // get the keyfile - $encKeyfile = Keymanager::getFileKey( $view, $owner, $fileTarget ); + $encKeyfile = Keymanager::getFileKey( $view, $owner, $filePath ); $privateKey = $session->getPrivateKey(); @@ -796,7 +796,7 @@ class Crypt { $shareKeys = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys ); // save sharekeys - if ( ! Keymanager::setShareKeys( $view, $fileTarget, $shareKeys['keys'] ) ) { + if ( ! Keymanager::setShareKeys( $view, $filePath, $shareKeys['keys'] ) ) { trigger_error( "SET Share keys failed" ); From d1bbb30385260d77b01bc5998465ebe68ccd83d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 12 Feb 2013 16:48:04 +0100 Subject: [PATCH 011/257] also find users with access to the file if a folder above the actual file was already shared --- apps/files_encryption/hooks/hooks.php | 30 +++------ apps/files_encryption/lib/crypt.php | 2 - apps/files_encryption/lib/util.php | 14 ++++ lib/public/share.php | 97 ++++++++++++++------------- 4 files changed, 75 insertions(+), 68 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index ebc345a47e..ffd3e4544f 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -164,21 +164,7 @@ class Hooks { } /** - * @brief get path of a file. - * @param $fileId id of the file - * @return path of the file - */ - private static function getFilePath($fileId) { - $query = \OC_DB::prepare('SELECT `path`' - .' FROM `*PREFIX*filecache`' - .' WHERE `fileid` = ?'); - $result = $query->execute(array($fileId)); - $row = $result->fetchRow(); - return $row['path']; - } - - /** - * @brief + * @brief get all users with access to the file and encrypt the file key to each of them */ public static function postShared( $params ) { @@ -194,9 +180,11 @@ class Hooks { $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); - $shares = \OCP\Share::getUsersSharingFile( $params['itemSource'], 1 ); + $path = Util::getFilePath($params['itemSource']); + + $shares = \OCP\Share::getUsersSharingFile( $path, 1 ); - return Crypt::encKeyfileToMultipleUsers($shares, self::getFilePath($params['itemSource'])); + return Crypt::encKeyfileToMultipleUsers($shares, $path); } @@ -204,18 +192,20 @@ class Hooks { * @brief */ public static function preUnshare( $params ) { - $shares = \OCP\Share::getUsersSharingFile( $params['itemSource'], 1 ); + + $path = Util::getFilePath($params['itemSource']); + $shares = \OCP\Share::getUsersSharingFile( $path, 1 ); // remove the user from the list from which the file will be unshared unset($shares[$params['shareWith']]); - return Crypt::encKeyfileToMultipleUsers($shares, self::getFilePath($params['itemSource'])); + return Crypt::encKeyfileToMultipleUsers($shares, $path ); } /** * @brief */ public static function preUnshareAll( $params ) { - return Crypt::encKeyfileToMultipleUsers(array(\OCP\User::getUser()), self::getFilePath($params['itemSource'])); + return Crypt::encKeyfileToMultipleUsers(array(\OCP\User::getUser()), Util::getFilePath($params['itemSource'])); } } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index cbdae323e5..ba9f0cb9a2 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -450,9 +450,7 @@ class Crypt { * @returns encrypted file */ public static function keyEncrypt( $plainContent, $publicKey ) { - openssl_public_encrypt( $plainContent, $encryptedContent, $publicKey ); - return $encryptedContent; } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 52bc74db27..843727d7ab 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -472,5 +472,19 @@ class Util { } } + + /** + * @brief get path of a file. + * @param $fileId id of the file + * @return path of the file + */ + public static function getFilePath($fileId) { + $query = \OC_DB::prepare('SELECT `path`' + .' FROM `*PREFIX*filecache`' + .' WHERE `fileid` = ?'); + $result = $query->execute(array($fileId)); + $row = $result->fetchRow(); + return substr($row['path'], 5); + } } diff --git a/lib/public/share.php b/lib/public/share.php index 841240692d..55ff4d4738 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -149,64 +149,69 @@ class Share { * @note $path needs to be relative to user data dir, e.g. 'file.txt' * not '/admin/data/file.txt' */ - public static function getUsersSharingFile( $source, $includeOwner = 0 ) { - //TODO get also the recipients from folders which are shared above the current file - // Fetch all shares of this file path from DB - $query = \OC_DB::prepare( - 'SELECT share_with - FROM - `*PREFIX*share` - WHERE - item_source = ? AND share_type = ? AND uid_owner = ?' - ); - - $result = $query->execute( array( $source, self::SHARE_TYPE_USER, \OCP\User::getUser() ) ); - - if ( \OC_DB::isError( $result ) ) { - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); - } - + public static function getUsersSharingFile( $path, $includeOwner = 0 ) { + + $user = \OCP\User::getUser(); + $path_parts = explode(DIRECTORY_SEPARATOR, trim($path, DIRECTORY_SEPARATOR)); + $path = ''; $shares = array(); - while( $row = $result->fetchRow() ) { - $shares[] = $row['share_with']; - } - - // We also need to take group shares into account - - $query = \OC_DB::prepare( - 'SELECT share_with - FROM - `*PREFIX*share` - WHERE - item_source = ? AND share_type = ? AND uid_owner = ?' - ); + foreach ($path_parts as $p) { + $path .= '/'.$p; + $meta = \OC\Files\Filesystem::getFileInfo(\OC_Filesystem::normalizePath($path)); + $source = $meta['fileid']; - $result = $query->execute( array( $source, self::SHARE_TYPE_GROUP, \OCP\User::getUser() ) ); - - if ( \OC_DB::isError( $result ) ) { - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); + // Fetch all shares of this file path from DB + $query = \OC_DB::prepare( + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ? AND uid_owner = ?' + ); + + $result = $query->execute( array( $source, self::SHARE_TYPE_USER, $user ) ); + + if ( \OC_DB::isError( $result ) ) { + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); + } + + while( $row = $result->fetchRow() ) { + $shares[] = $row['share_with']; + } + + // We also need to take group shares into account + + $query = \OC_DB::prepare( + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ? AND uid_owner = ?' + ); + + $result = $query->execute( array( $source, self::SHARE_TYPE_GROUP, $user ) ); + + if ( \OC_DB::isError( $result ) ) { + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); + } + + while( $row = $result->fetchRow() ) { + $usersInGroup = \OC_Group::usersInGroup($row['share_with']); + $shares = array_merge($shares, $usersInGroup); + } } - - while( $row = $result->fetchRow() ) { - $usersInGroup = \OC_Group::usersInGroup($row['share_with']); - $shares = array_merge($shares, $usersInGroup); - } - + if ( ! empty( $shares ) ) { // Include owner in list of users, if requested if ( $includeOwner == 1 ) { - $shares[] = \OCP\User::getUser(); + $shares[] = $user; } - return array_unique($shares); - } else { - return false; - } - + } /** From a692264fa416fec44d774bd955a06a65c7c0d158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 12 Feb 2013 17:00:33 +0100 Subject: [PATCH 012/257] add option to keep duplicates in the list of users with access to a file, e.g. for the unshare operation we need to know if access was granted more than once, for example as group share and as individual share --- apps/files_encryption/hooks/hooks.php | 6 +++--- apps/files_encryption/lib/proxy.php | 11 ++--------- lib/public/share.php | 19 ++++++++++++------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index ffd3e4544f..5e06948aa5 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -182,7 +182,7 @@ class Hooks { $path = Util::getFilePath($params['itemSource']); - $shares = \OCP\Share::getUsersSharingFile( $path, 1 ); + $shares = \OCP\Share::getUsersSharingFile( $path, true ); return Crypt::encKeyfileToMultipleUsers($shares, $path); @@ -194,11 +194,11 @@ class Hooks { public static function preUnshare( $params ) { $path = Util::getFilePath($params['itemSource']); - $shares = \OCP\Share::getUsersSharingFile( $path, 1 ); + $shares = \OCP\Share::getUsersSharingFile( $path, true, false ); // remove the user from the list from which the file will be unshared unset($shares[$params['shareWith']]); - return Crypt::encKeyfileToMultipleUsers($shares, $path ); + return Crypt::encKeyfileToMultipleUsers(array_unique($shares), $path ); } /** diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 40ac411539..3e4178e8a8 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -118,15 +118,8 @@ class Proxy extends \OC_FileProxy { // $fileOwner = \OC\Files\Filesystem::getOwner( $path ); // List everyone sharing the file - $shares = \OCP\Share::getUsersSharingFile( $filePath, 1 ); - - $userIds = array(); - - foreach ( $shares as $share ) { - - $userIds[] = $share['userId']; - - } + //TODO check, is this path always the path to the source file? + $userIds = \OCP\Share::getUsersSharingFile( $filePath, true ); $publicKeys = Keymanager::getPublicKeys( $rootView, $userIds ); diff --git a/lib/public/share.php b/lib/public/share.php index 55ff4d4738..68f5e93baa 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -145,11 +145,14 @@ class Share { /** * @brief Find which users can access a shared item - * @return bool / array + * @param $path to the file + * @param include owner to the list of users with access to the file + * @param remove duplicates in the result + * @return array * @note $path needs to be relative to user data dir, e.g. 'file.txt' * not '/admin/data/file.txt' */ - public static function getUsersSharingFile( $path, $includeOwner = 0 ) { + public static function getUsersSharingFile( $path, $includeOwner = false, $removeDuplicates = true ) { $user = \OCP\User::getUser(); $path_parts = explode(DIRECTORY_SEPARATOR, trim($path, DIRECTORY_SEPARATOR)); @@ -204,14 +207,16 @@ class Share { if ( ! empty( $shares ) ) { // Include owner in list of users, if requested - if ( $includeOwner == 1 ) { + if ( $includeOwner ) { $shares[] = $user; } - return array_unique($shares); - } else { - return false; } - + + if ( $removeDuplicates ) + return array_unique($shares); + else { + return $shares; + } } /** From 4952dfe95657ba52f1b39f958100659539831ba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 13 Feb 2013 14:56:39 +0100 Subject: [PATCH 013/257] add post_unshare hook, also add public link shares to the list of user with access to a file --- apps/files_encryption/appinfo/app.php | 2 +- apps/files_encryption/hooks/hooks.php | 9 +++---- apps/files_encryption/lib/crypt.php | 4 ++- lib/public/share.php | 35 +++++++++++++++++++++------ 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index f83109a18e..932e8855d0 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -16,7 +16,7 @@ OCP\Util::connectHook( 'OC_User', 'pre_setPassword','OCA\Encryption\Hooks', 'set // Sharing-related hooks OCP\Util::connectHook( 'OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared' ); -OCP\Util::connectHook( 'OCP\Share', 'pre_unshare', 'OCA\Encryption\Hooks', 'preUnshare' ); +OCP\Util::connectHook( 'OCP\Share', 'post_unshare', 'OCA\Encryption\Hooks', 'postUnshare' ); OCP\Util::connectHook( 'OCP\Share', 'pre_unshareAll', 'OCA\Encryption\Hooks', 'preUnshareAll' ); // Webdav-related hooks diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 5e06948aa5..ae05ba7801 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -176,6 +176,8 @@ class Hooks { //TODO: We don't deal with shared folder yet, need to recursively update every file in the folder + if ($params['shareType'] == \OCP\Share::SHARE_TYPE_LINK) + $view = new \OC_FilesystemView( '/' ); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); @@ -191,12 +193,9 @@ class Hooks { /** * @brief */ - public static function preUnshare( $params ) { - + public static function postUnshare( $params ) { $path = Util::getFilePath($params['itemSource']); - $shares = \OCP\Share::getUsersSharingFile( $path, true, false ); - // remove the user from the list from which the file will be unshared - unset($shares[$params['shareWith']]); + $shares = \OCP\Share::getUsersSharingFile( $path, true ); return Crypt::encKeyfileToMultipleUsers(array_unique($shares), $path ); } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index ba9f0cb9a2..0f465d7d95 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -450,7 +450,9 @@ class Crypt { * @returns encrypted file */ public static function keyEncrypt( $plainContent, $publicKey ) { - openssl_public_encrypt( $plainContent, $encryptedContent, $publicKey ); + + if (openssl_public_encrypt( $plainContent, $encryptedContent, $publicKey )) error_log("feinifeine"); else error_log("ups"); + return $encryptedContent; } diff --git a/lib/public/share.php b/lib/public/share.php index 68f5e93baa..f691ae9b39 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -147,7 +147,6 @@ class Share { * @brief Find which users can access a shared item * @param $path to the file * @param include owner to the list of users with access to the file - * @param remove duplicates in the result * @return array * @note $path needs to be relative to user data dir, e.g. 'file.txt' * not '/admin/data/file.txt' @@ -203,6 +202,25 @@ class Share { $usersInGroup = \OC_Group::usersInGroup($row['share_with']); $shares = array_merge($shares, $usersInGroup); } + + //check for public link shares + $query = \OC_DB::prepare( + 'SELECT share_with + FROM + `*PREFIX*share` + WHERE + item_source = ? AND share_type = ? AND uid_owner = ?' + ); + + $result = $query->execute( array( $source, self::SHARE_TYPE_LINK, $user ) ); + + if ( \OC_DB::isError( $result ) ) { + \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); + } + + if ($result->fetchRow()) { + $shares[] = self::SHARE_TYPE_LINK; + } } if ( ! empty( $shares ) ) { @@ -212,11 +230,8 @@ class Share { } } - if ( $removeDuplicates ) - return array_unique($shares); - else { - return $shares; - } + return array_unique($shares); + } /** @@ -475,8 +490,14 @@ class Share { 'itemSource' => $itemSource, 'shareType' => $shareType, 'shareWith' => $shareWith, - )); + )); self::delete($item['id']); + \OC_Hook::emit('OCP\Share', 'post_unshare', array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'shareType' => $shareType, + 'shareWith' => $shareWith, + )); return true; } return false; From 9356f9a6bf6e9bd048e31e787d5fcb621de8eebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 13 Feb 2013 17:23:27 +0100 Subject: [PATCH 014/257] add post_unshareALll hook, update recursively all keyfiles if a folder was shared/unshared --- apps/files_encryption/appinfo/app.php | 2 +- apps/files_encryption/hooks/hooks.php | 15 +++++------ apps/files_encryption/lib/crypt.php | 36 ++++++++++++++++++++++++++- lib/public/share.php | 5 ++++ 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 932e8855d0..6778e1faa3 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -17,7 +17,7 @@ OCP\Util::connectHook( 'OC_User', 'pre_setPassword','OCA\Encryption\Hooks', 'set // Sharing-related hooks OCP\Util::connectHook( 'OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared' ); OCP\Util::connectHook( 'OCP\Share', 'post_unshare', 'OCA\Encryption\Hooks', 'postUnshare' ); -OCP\Util::connectHook( 'OCP\Share', 'pre_unshareAll', 'OCA\Encryption\Hooks', 'preUnshareAll' ); +OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', 'postUnshareAll' ); // Webdav-related hooks OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfile' ); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index ae05ba7801..34ed11c7e2 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -176,17 +176,13 @@ class Hooks { //TODO: We don't deal with shared folder yet, need to recursively update every file in the folder - if ($params['shareType'] == \OCP\Share::SHARE_TYPE_LINK) - $view = new \OC_FilesystemView( '/' ); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); $path = Util::getFilePath($params['itemSource']); - $shares = \OCP\Share::getUsersSharingFile( $path, true ); - - return Crypt::encKeyfileToMultipleUsers($shares, $path); + return Crypt::updateKeyfile($path); } @@ -195,16 +191,17 @@ class Hooks { */ public static function postUnshare( $params ) { $path = Util::getFilePath($params['itemSource']); - $shares = \OCP\Share::getUsersSharingFile( $path, true ); - return Crypt::encKeyfileToMultipleUsers(array_unique($shares), $path ); + return Crypt::updateKeyfile($path); } /** * @brief */ - public static function preUnshareAll( $params ) { - return Crypt::encKeyfileToMultipleUsers(array(\OCP\User::getUser()), Util::getFilePath($params['itemSource'])); + public static function postUnshareAll( $params ) { + $path = Util::getFilePath($params['itemSource']); + + return Crypt::updateKeyfile($path); } } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 0f465d7d95..18e9535bf3 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -750,7 +750,7 @@ class Crypt { * @param $users list of users which should be able to access the file * @param $fileTarget target of the file */ - public static function encKeyfileToMultipleUsers($users, $filePath) { + private static function encKeyfileToMultipleUsers($users, $filePath) { $view = new \OC_FilesystemView( '/' ); $owner = \OCP\User::getUser(); $util = new Util( $view, $userId ); @@ -810,4 +810,38 @@ class Crypt { return true; } + + /** + * @brief update keyfile encryption for given path and all sub folders/files + * @param path which needs to be updated + * @return bool success + */ + public static function updateKeyfile($path) { + + $filesView = \OCP\Files::getStorage('files'); + + $result = true; + + if ( $filesView->is_dir($path) ) { + $content = $filesView->getDirectoryContent($path); + foreach ( $content as $c) { + $path = substr($c['path'], 5); + if ( $filesView->is_dir($path) ) { + error_log("dive into $path"); + $result &= self::updateKeyfile($path); + } else { + error_log("encKeyFileToMultipleUsers $path"); + $shares = \OCP\Share::getUsersSharingFile( $path, true ); + $result &= self::encKeyfileToMultipleUsers($shares, $path); + } + } + } else { + error_log("encKeyFileToMultipleUsers single file: " . $path); + $shares = \OCP\Share::getUsersSharingFile( $path, true ); + $result = self::encKeyfileToMultipleUsers($shares, $path); + } + + return $result; + + } } \ No newline at end of file diff --git a/lib/public/share.php b/lib/public/share.php index f691ae9b39..d1297c6e59 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -520,6 +520,11 @@ class Share { foreach ($shares as $share) { self::delete($share['id']); } + \OC_Hook::emit('OCP\Share', 'post_unshareAll', array( + 'itemType' => $itemType, + 'itemSource' => $itemSource, + 'shares' => $shares + )); return true; } return false; From 5005195db005fd0d7c8fdf1a73e12c4a4619acb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 13 Feb 2013 17:57:45 +0100 Subject: [PATCH 015/257] create keypair for ownCloud with empty passphrase, will be used for public link shares --- apps/files_encryption/lib/crypt.php | 5 +---- apps/files_encryption/lib/session.php | 28 +++++++++++++++++++++++++++ lib/public/share.php | 2 +- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 18e9535bf3..2e5912a868 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -763,7 +763,7 @@ class Crypt { $util = new Util( $view, $user ); // Check that the user is encryption capable - if ( $util->ready() ) { + if ( $util->ready() && $user == 'ownCloud' ) { // Construct array of just UIDs for Keymanager{} $userIds[] = $user; @@ -827,16 +827,13 @@ class Crypt { foreach ( $content as $c) { $path = substr($c['path'], 5); if ( $filesView->is_dir($path) ) { - error_log("dive into $path"); $result &= self::updateKeyfile($path); } else { - error_log("encKeyFileToMultipleUsers $path"); $shares = \OCP\Share::getUsersSharingFile( $path, true ); $result &= self::encKeyfileToMultipleUsers($shares, $path); } } } else { - error_log("encKeyFileToMultipleUsers single file: " . $path); $shares = \OCP\Share::getUsersSharingFile( $path, true ); $result = self::encKeyfileToMultipleUsers($shares, $path); } diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index 769a40b359..ebf7edcd71 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -27,6 +27,34 @@ namespace OCA\Encryption; */ class Session { + + /** + * @brief if session is started, check if ownCloud key pair is set up, if not create it + * + * The ownCloud key pair is used to allow public link sharing even if encryption is enabled + */ + public function __construct() { + $view = new \OC\Files\View('/'); + if (!$view->is_dir('owncloud_private_key')) { + $view->mkdir('owncloud_private_key'); + } + + if (!$view->file_exists("/public-keys/owncloud.public.key") || !$view->file_exists("/owncloud_private_key/owncloud.private.key") ) { + + $keypair = Crypt::createKeypair(); + + \OC_FileProxy::$enabled = false; + // Save public key + $view->file_put_contents( '/public-keys/owncloud.public.key', $keypair['publicKey'] ); + // Encrypt private key empthy passphrase + $encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $keypair['privateKey'], '' ); + // Save private key + error_log("encrypted private key: " . $encryptedPrivateKey ); + $view->file_put_contents( '/owncloud_private_key/owncloud.private.key', $encryptedPrivateKey ); + + \OC_FileProxy::$enabled = true; + } + } /** * @brief Sets user private key to session diff --git a/lib/public/share.php b/lib/public/share.php index d1297c6e59..720337c3c3 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -219,7 +219,7 @@ class Share { } if ($result->fetchRow()) { - $shares[] = self::SHARE_TYPE_LINK; + $shares[] = "ownCloud"; } } From 8c35bbcba75590d5f66ecf08a4dd07db3fd23732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 14 Feb 2013 16:33:57 +0100 Subject: [PATCH 016/257] remove debug output, fix typo in file names --- apps/files_encryption/lib/session.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index ebf7edcd71..171a6900f0 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -34,23 +34,23 @@ class Session { * The ownCloud key pair is used to allow public link sharing even if encryption is enabled */ public function __construct() { + $view = new \OC\Files\View('/'); if (!$view->is_dir('owncloud_private_key')) { $view->mkdir('owncloud_private_key'); } if (!$view->file_exists("/public-keys/owncloud.public.key") || !$view->file_exists("/owncloud_private_key/owncloud.private.key") ) { - + $keypair = Crypt::createKeypair(); \OC_FileProxy::$enabled = false; // Save public key - $view->file_put_contents( '/public-keys/owncloud.public.key', $keypair['publicKey'] ); + $view->file_put_contents( '/public-keys/ownCloud.public.key', $keypair['publicKey'] ); // Encrypt private key empthy passphrase $encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $keypair['privateKey'], '' ); // Save private key - error_log("encrypted private key: " . $encryptedPrivateKey ); - $view->file_put_contents( '/owncloud_private_key/owncloud.private.key', $encryptedPrivateKey ); + $view->file_put_contents( '/owncloud_private_key/ownCloud.private.key', $encryptedPrivateKey ); \OC_FileProxy::$enabled = true; } From 109fee7673f1c3f395da47ae7114fba3354fa22f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 19 Feb 2013 14:47:45 +0100 Subject: [PATCH 017/257] remove todo, it is already solved --- apps/files_encryption/hooks/hooks.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 34ed11c7e2..5020724657 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -174,8 +174,6 @@ class Hooks { // fileTarget -> path of file being shared // uidOwner -> owner of the original file being shared - //TODO: We don't deal with shared folder yet, need to recursively update every file in the folder - $view = new \OC_FilesystemView( '/' ); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); From fd629983fa61ad7fdc1c6696e6b2fa1739ae6f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 19 Feb 2013 17:10:32 +0100 Subject: [PATCH 018/257] remove debug output --- apps/files_encryption/lib/crypt.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 2e5912a868..a1684fc95f 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -451,7 +451,7 @@ class Crypt { */ public static function keyEncrypt( $plainContent, $publicKey ) { - if (openssl_public_encrypt( $plainContent, $encryptedContent, $publicKey )) error_log("feinifeine"); else error_log("ups"); + openssl_public_encrypt( $plainContent, $encryptedContent, $publicKey ); return $encryptedContent; From 14ae373dfe86b34b3e027306b5f857a3f38ff418 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 19 Feb 2013 17:41:38 +0000 Subject: [PATCH 019/257] Fixed wrong array key reference --- apps/files_encryption/lib/crypt.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index a1684fc95f..49b75c17f6 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -371,7 +371,7 @@ class Crypt { * @brief Create asymmetrically encrypted keyfile content using a generated key * @param string $plainContent content to be encrypted * @param array $publicKeys array keys must be the userId of corresponding user - * @returns array keys: keys (array, key = userId), encrypted + * @returns array keys: keys (array, key = userId), data * @note symmetricDecryptFileContent() can decrypt files created using this method */ public static function multiKeyEncrypt( $plainContent, array $publicKeys ) { From 1b880f2f96df514c68a17e90141cff9620c2ddb5 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 19 Feb 2013 19:16:50 +0000 Subject: [PATCH 020/257] Moved dependencies out of Crypt methods (encKeyfileToMultipleUsers)(DI) Fixed bug preventing sharing with users other than 'ownCloud' Added comments Moved functionality into filterShareReadyUsers() Other changes --- apps/files_encryption/appinfo/app.php | 2 +- apps/files_encryption/hooks/hooks.php | 23 ++++-- apps/files_encryption/lib/crypt.php | 103 ++++++++++++++------------ apps/files_encryption/lib/util.php | 41 ++++++++++ 4 files changed, 112 insertions(+), 57 deletions(-) diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 6778e1faa3..742e4add8f 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -20,7 +20,7 @@ OCP\Util::connectHook( 'OCP\Share', 'post_unshare', 'OCA\Encryption\Hooks', 'pos OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', 'postUnshareAll' ); // Webdav-related hooks -OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfile' ); +OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfileFromClient' ); stream_wrapper_register( 'crypt', 'OCA\Encryption\Stream' ); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 5020724657..1ebfdb1ae0 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -139,7 +139,7 @@ class Hooks { /** * @brief update the encryption key of the file uploaded by the client */ - public static function updateKeyfile( $params ) { + public static function updateKeyfileFromClient( $params ) { if ( Crypt::mode() == 'client' ) { @@ -175,12 +175,13 @@ class Hooks { // uidOwner -> owner of the original file being shared $view = new \OC_FilesystemView( '/' ); + $session = new Session(); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); - $path = Util::getFilePath($params['itemSource']); + $path = Util::getFilePath( $params['itemSource'] ); - return Crypt::updateKeyfile($path); + return Crypt::updateKeyfile( $view, $session, $path ); } @@ -188,18 +189,26 @@ class Hooks { * @brief */ public static function postUnshare( $params ) { - $path = Util::getFilePath($params['itemSource']); + + $view = new \OC_FilesystemView( '/' ); + $session = new Session(); + $path = Util::getFilePath( $params['itemSource'] ); + + return Crypt::updateKeyfile( $view, $session, $path ); - return Crypt::updateKeyfile($path); } /** * @brief */ public static function postUnshareAll( $params ) { - $path = Util::getFilePath($params['itemSource']); + + $view = new \OC_FilesystemView( '/' ); + $session = new Session(); + $path = Util::getFilePath( $params['itemSource'] ); + + return Crypt::updateKeyfile( $view, $session, $path ); - return Crypt::updateKeyfile($path); } } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 49b75c17f6..1b0167834e 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -746,52 +746,44 @@ class Crypt { /** - * @brief encrypt file key to multiple users - * @param $users list of users which should be able to access the file - * @param $fileTarget target of the file + * @brief Encrypt keyfile to multiple users + * @param array $users list of users which should be able to access the file + * @param string $filePath path of the file to be shared */ - private static function encKeyfileToMultipleUsers($users, $filePath) { - $view = new \OC_FilesystemView( '/' ); - $owner = \OCP\User::getUser(); - $util = new Util( $view, $userId ); - $session = new Session(); + private static function encKeyfileToMultipleUsers( \OC_FilesystemView $view, Util $util, Session $session, $userId, array $users, $filePath ) { + + // Make sure users are capable of sharing + $filteredUids = $util->filterShareReadyUsers( $users ); - $userIds = array(); - - foreach ( $users as $user ) { - - $util = new Util( $view, $user ); - - // Check that the user is encryption capable - if ( $util->ready() && $user == 'ownCloud' ) { - // Construct array of just UIDs for Keymanager{} - $userIds[] = $user; - - } else { - - // Log warning; we can't do necessary setup here - // because we don't have the user passphrase - // TODO: Provide user feedback indicating that - // sharing failed - \OC_Log::write( 'Encryption library', 'File cannot be shared: user "'.$user.'" is not setup for encryption', \OC_Log::WARN ); - - } - - } - - - $userPubKeys = Keymanager::getPublicKeys( $view, $userIds ); + // Get public keys for each user, ready for generating sharekeys + $userPubKeys = Keymanager::getPublicKeys( $view, $filteredUids ); // TODO: check this includes the owner's public key \OC_FileProxy::$enabled = false; - // get the keyfile + // Get the current users's private key for decrypting existing keyfile + $privateKey = $session->getPrivateKey(); + + // We need to get a decrypted key for the file + // Determine how to decrypt the keyfile by checking if current user is owner + if ( $userId == \OC\Files\Filesystem::getOwner( $filePath ) ) { + + // If current user is owner, decrypt without using sharekey + + } else { + + // Current user is resharing a file they don't own + // Decrypt keyfile using sharekey + + } + + // get the existing keyfile $encKeyfile = Keymanager::getFileKey( $view, $owner, $filePath ); - $privateKey = $session->getPrivateKey(); - - // decrypt the keyfile + // decrypt the existing keyfile $plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey ); - + + trigger_error("PUBKEYS = ". var_export($userPubKeys, 1)); + // re-enc keyfile to sharekeys $shareKeys = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys ); @@ -816,29 +808,42 @@ class Crypt { * @param path which needs to be updated * @return bool success */ - public static function updateKeyfile($path) { + public static function updateKeyfile( \OC_FilesystemView $view, Util $util, Session $session, $path ) { - $filesView = \OCP\Files::getStorage('files'); + // Make path include 'files' dir for OC_FSV operations + $fPath = 'files' . $path; $result = true; - if ( $filesView->is_dir($path) ) { - $content = $filesView->getDirectoryContent($path); - foreach ( $content as $c) { + if ( ! $view->is_dir( $fPath ) ) { + + $shares = \OCP\Share::getUsersSharingFile( $path, true ); + $result = self::encKeyfileToMultipleUsers( $view, $util, $session, $shares, $path ); + + } else { + + $content = $view->getDirectoryContent( $fPath ); + + foreach ( $content as $c ) { + $path = substr($c['path'], 5); - if ( $filesView->is_dir($path) ) { - $result &= self::updateKeyfile($path); + + if ( $view->is_dir( $fPath ) ) { + + $result &= self::updateKeyfile( $path ); + } else { + $shares = \OCP\Share::getUsersSharingFile( $path, true ); - $result &= self::encKeyfileToMultipleUsers($shares, $path); + $result &= self::encKeyfileToMultipleUsers( $view, $util, $session, $shares, $path ); + } } - } else { - $shares = \OCP\Share::getUsersSharingFile( $path, true ); - $result = self::encKeyfileToMultipleUsers($shares, $path); + } return $result; } + } \ No newline at end of file diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 843727d7ab..8ca51c95d7 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -486,5 +486,46 @@ class Util { $row = $result->fetchRow(); return substr($row['path'], 5); } + + /** + * @brief Filter an array of UIDs to return only ones ready for sharing + * @param array $unfilteredUsers users to be checked for sharing readiness + * @return array $userIds filtered users + */ + public function filterShareReadyUsers( $unfilteredUsers ) { + + // This array will collect the filtered IDs + $userIds = array(); + + // Loop through users and create array of UIDs that need new keyfiles + foreach ( $unfilteredUsers as $user ) { + + $util = new Util( $this->view, $user ); + + // Check that the user is encryption capable, or is the + // public system user 'ownCloud' (for public shares) + if ( + $util->ready() + or $user == 'ownCloud' + ) { + + // Construct array of just UIDs for Keymanager{} + $userIds[] = $user; + + } else { + + // Log warning; we can't do necessary setup here + // because we don't have the user passphrase + // TODO: Provide user feedback indicating that + // sharing failed + \OC_Log::write( 'Encryption library', '"'.$user.'" is not setup for encryption', \OC_Log::WARN ); + + } + + } + + return $userIds; + + } } From 2d267501a10642e5c601ca87748b692ca58e4094 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Wed, 20 Feb 2013 19:18:00 +0000 Subject: [PATCH 021/257] Development snapshot Added comments Added methods --- apps/files_encryption/hooks/hooks.php | 54 ++++++-- apps/files_encryption/lib/crypt.php | 102 -------------- apps/files_encryption/lib/keymanager.php | 4 +- apps/files_encryption/lib/proxy.php | 43 ++++-- apps/files_encryption/lib/util.php | 169 +++++++++++++++++++++-- apps/files_encryption/test/util.php | 4 +- 6 files changed, 240 insertions(+), 136 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 1ebfdb1ae0..6d982b2c3b 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -178,10 +178,34 @@ class Hooks { $session = new Session(); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); + $path = $util->fileIdToPath( $params['itemSource'] ); - $path = Util::getFilePath( $params['itemSource'] ); - - return Crypt::updateKeyfile( $view, $session, $path ); + $usersSharing = \OCP\Share::getUsersSharingFile( $path, true ); + + $allPaths = $util->getPaths( $path ); + + $failed = array(); + + foreach ( $allPaths as $path ) { + + if ( ! $util->setSharedFileKeyfiles( $session, $usersSharing, $path ) ) { + + $failed[] = $path; + + } + + } + + // If no attempts to set keyfiles failed + if ( empty( $failed ) ) { + + return true; + + } else { + + return false; + + } } @@ -190,11 +214,13 @@ class Hooks { */ public static function postUnshare( $params ) { - $view = new \OC_FilesystemView( '/' ); - $session = new Session(); - $path = Util::getFilePath( $params['itemSource'] ); - - return Crypt::updateKeyfile( $view, $session, $path ); +// $view = new \OC_FilesystemView( '/' ); +// $session = new Session(); +// $userId = \OCP\User::getUser(); +// $util = new Util( $view, $userId ); +// $path = $util->fileIdToPath( $params['itemSource'] ); +// +// return Crypt::updateKeyfile( $view, $util, $session, $userId, $path ); } @@ -203,11 +229,13 @@ class Hooks { */ public static function postUnshareAll( $params ) { - $view = new \OC_FilesystemView( '/' ); - $session = new Session(); - $path = Util::getFilePath( $params['itemSource'] ); - - return Crypt::updateKeyfile( $view, $session, $path ); +// $view = new \OC_FilesystemView( '/' ); +// $session = new Session(); +// $userId = \OCP\User::getUser(); +// $util = new Util( $view, $userId ); +// $path = $util->fileIdToPath( $params['itemSource'] ); +// +// return Crypt::updateKeyfile( $view, $util, $session, $userId, $path ); } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 1b0167834e..a677de950a 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -744,106 +744,4 @@ class Crypt { } - - /** - * @brief Encrypt keyfile to multiple users - * @param array $users list of users which should be able to access the file - * @param string $filePath path of the file to be shared - */ - private static function encKeyfileToMultipleUsers( \OC_FilesystemView $view, Util $util, Session $session, $userId, array $users, $filePath ) { - - // Make sure users are capable of sharing - $filteredUids = $util->filterShareReadyUsers( $users ); - - // Get public keys for each user, ready for generating sharekeys - $userPubKeys = Keymanager::getPublicKeys( $view, $filteredUids ); // TODO: check this includes the owner's public key - - \OC_FileProxy::$enabled = false; - - // Get the current users's private key for decrypting existing keyfile - $privateKey = $session->getPrivateKey(); - - // We need to get a decrypted key for the file - // Determine how to decrypt the keyfile by checking if current user is owner - if ( $userId == \OC\Files\Filesystem::getOwner( $filePath ) ) { - - // If current user is owner, decrypt without using sharekey - - } else { - - // Current user is resharing a file they don't own - // Decrypt keyfile using sharekey - - } - - // get the existing keyfile - $encKeyfile = Keymanager::getFileKey( $view, $owner, $filePath ); - - // decrypt the existing keyfile - $plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey ); - - trigger_error("PUBKEYS = ". var_export($userPubKeys, 1)); - - // re-enc keyfile to sharekeys - $shareKeys = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys ); - - // save sharekeys - if ( ! Keymanager::setShareKeys( $view, $filePath, $shareKeys['keys'] ) ) { - - trigger_error( "SET Share keys failed" ); - - } - - // Delete existing keyfile - // Do this last to ensure file is recoverable in case of error - // Keymanager::deleteFileKey( $view, $userId, $params['fileTarget'] ); - - \OC_FileProxy::$enabled = true; - - return true; - } - - /** - * @brief update keyfile encryption for given path and all sub folders/files - * @param path which needs to be updated - * @return bool success - */ - public static function updateKeyfile( \OC_FilesystemView $view, Util $util, Session $session, $path ) { - - // Make path include 'files' dir for OC_FSV operations - $fPath = 'files' . $path; - - $result = true; - - if ( ! $view->is_dir( $fPath ) ) { - - $shares = \OCP\Share::getUsersSharingFile( $path, true ); - $result = self::encKeyfileToMultipleUsers( $view, $util, $session, $shares, $path ); - - } else { - - $content = $view->getDirectoryContent( $fPath ); - - foreach ( $content as $c ) { - - $path = substr($c['path'], 5); - - if ( $view->is_dir( $fPath ) ) { - - $result &= self::updateKeyfile( $path ); - - } else { - - $shares = \OCP\Share::getUsersSharingFile( $path, true ); - $result &= self::encKeyfileToMultipleUsers( $view, $util, $session, $shares, $path ); - - } - } - - } - - return $result; - - } - } \ No newline at end of file diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 5f9eea1a0b..ec1fdd1fd5 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -305,8 +305,8 @@ class Keymanager { /** * @brief retrieve shareKey for an encrypted file * @param \OC_FilesystemView $view - * @param $userId - * @param $filePath + * @param string $userId + * @param string $filePath * @internal param \OCA\Encryption\file $string name * @return string file key or false * @note The sharekey returned is encrypted. Decryption diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 3e4178e8a8..9e6a11d9d4 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -169,6 +169,24 @@ class Proxy extends \OC_FileProxy { * @param string $data Data that has been read from file */ public function postFile_get_contents( $path, $data ) { + + // FIXME: $path for shared files is just /uid/files/Shared/filepath + + $userId = \OCP\USER::getUser(); + $view = new \OC_FilesystemView( '/' ); + $util = new Util( $view, $userId ); + + if ( $util->isSharedPath( $path ) ) { + + $relPath = $util->stripSharedFilePath( $path ); + + } else { + + $relPath = $util->stripUserFilesPath( $path ); + + } + + // TODO check for existing key file and reuse it if possible to avoid problems with versioning etc. // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; @@ -178,27 +196,34 @@ class Proxy extends \OC_FileProxy { Crypt::mode() == 'server' && Crypt::isCatfile( $data ) ) { - $view = new \OC_FilesystemView( '/' ); + // TODO use get owner to find correct location of key files for shared files - $userId = \OCP\USER::getUser(); $session = new Session(); - $util = new Util( $view, $userId ); - $filePath = $util->stripUserFilesPath( $path ); $privateKey = $session->getPrivateKey( $userId ); + // Get the file owner so we can retrieve its keyfile + $fileOwner = \OC\Files\Filesystem::getOwner( $relPath ); //NOTE: This might be false! make sure the path passed to it is right + $fileOwner = 'admin'; // FIXME: Manually set the correct UID for now + // Get the encrypted keyfile - $encKeyfile = Keymanager::getFileKey( $view, $userId, $filePath ); + $encKeyfile = Keymanager::getFileKey( $view, $fileOwner, $relPath ); + + trigger_error("\$encKeyfile = ". var_export($encKeyfile, 1)); + + // Attempt to fetch the user's shareKey + $shareKey = Keymanager::getShareKey( $view, $userId, $relPath ); + + trigger_error("\$shareKey = ".var_export($shareKey, 1)); // Check if key is shared or not - if ( \OCP\Share::isSharedFile( $filePath ) ) { - - // If key is shared, fetch the user's shareKey - $shareKey = Keymanager::getShareKey( $view, $userId, $filePath ); + if ( $shareKey ) { \OC_FileProxy::$enabled = false; // Decrypt keyfile with shareKey $plainKeyfile = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); + + trigger_error("PROXY plainkeyfile = ". var_export($plainKeyfile, 1)); } else { diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 8ca51c95d7..ac098cd877 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -224,7 +224,7 @@ class Util { * @note $directory needs to be a path relative to OC data dir. e.g. * /admin/files NOT /backup OR /home/www/oc/data/admin/files */ - public function findFiles( $directory ) { + public function findEncFiles( $directory ) { // Disable proxy - we don't want files to be decrypted before // we handle them @@ -251,7 +251,7 @@ class Util { // its contents if ( $this->view->is_dir( $filePath ) ) { - $this->findFiles( $filePath ); + $this->findEncFiles( $filePath ); // If the path is a file, determine // its encryption status @@ -348,6 +348,38 @@ class Util { } + /** + * @brief Format a shared path to be relative to the /user/files/ directory + * @note Expects a path like /uid/files/Shared/filepath + */ + public function stripSharedFilePath( $path ) { + + $trimmed = ltrim( $path, '/' ); + $split = explode( '/', $trimmed ); + $sliced = array_slice( $split, 3 ); + $relPath = implode( '/', $sliced ); + + return $relPath; + + } + + public function isSharedPath( $path ) { + + $trimmed = ltrim( $path, '/' ); + $split = explode( '/', $trimmed ); + + if ( $split[2] == "Shared" ) { + + return true; + + } else { + + return false; + + } + + } + /** * @brief Encrypt all files in a directory * @param string $publicKey the public key to encrypt files with @@ -356,7 +388,7 @@ class Util { */ public function encryptAll( $publicKey, $dirPath, $legacyPassphrase = null, $newPassphrase = null ) { - if ( $found = $this->findFiles( $dirPath ) ) { + if ( $found = $this->findEncFiles( $dirPath ) ) { // Disable proxy to prevent file being encrypted twice \OC_FileProxy::$enabled = false; @@ -478,13 +510,18 @@ class Util { * @param $fileId id of the file * @return path of the file */ - public static function getFilePath($fileId) { - $query = \OC_DB::prepare('SELECT `path`' + public static function fileIdToPath( $fileId ) { + + $query = \OC_DB::prepare( 'SELECT `path`' .' FROM `*PREFIX*filecache`' - .' WHERE `fileid` = ?'); - $result = $query->execute(array($fileId)); + .' WHERE `fileid` = ?' ); + + $result = $query->execute( array( $fileId ) ); + $row = $result->fetchRow(); - return substr($row['path'], 5); + + return substr( $row['path'], 5 ); + } /** @@ -527,5 +564,121 @@ class Util { return $userIds; } + + /** + * @brief Expand given path to all sub files & folders + * @param Session $session + * @param string $path path which needs to be updated + * @return bool outcome of attempt to set keyfiles + */ + public function getPaths( $path ) { + + // Default return value is success + $result = true; + + // Make path include 'files' dir for OC_FSV operations + $fPath = 'files' . $path; + + // If we're handling a single file + if ( ! $this->view->is_dir( $fPath ) ) { + + $pathsArray[] = $path; + + // If we're handling a folder (recursively) + } else { + + $subFiles = $this->view->getDirectoryContent( $fPath ); + + foreach ( $subFiles as $file ) { + + $filePath = substr( $file['path'], 5 ); + + // If this is a nested file + if ( ! $this->view->is_dir( $fPath ) ) { + + // Add the file path to array + $pathsArray[] = $path; + + } else { + + // If this is a nested folder + $dirPaths = $this->getPaths( $filePath ); + + // Add all subfiles & folders to the array + $pathsArray = array_merge( $dirPaths, $pathsArray ); + + } + } + + } + + return $pathsArray; + + } + + /** + * @brief Encrypt keyfile to multiple users + * @param array $users list of users which should be able to access the file + * @param string $filePath path of the file to be shared + */ + public function setSharedFileKeyfiles( Session $session, array $users, $filePath ) { + + // Make sure users are capable of sharing + $filteredUids = $this->filterShareReadyUsers( $users ); + + // Get public keys for each user, ready for generating sharekeys + $userPubKeys = Keymanager::getPublicKeys( $this->view, $filteredUids ); // TODO: check this includes the owner's public key + + \OC_FileProxy::$enabled = false; + + // Get the current users's private key for decrypting existing keyfile + $privateKey = $session->getPrivateKey(); + + $fileOwner = \OC\Files\Filesystem::getOwner( $filePath ); + + // Get the encrypted keyfile + // NOTE: the keyfile format depends on how it was encrypted! At + // this stage we don't know how it was encrypted + $encKeyfile = Keymanager::getFileKey( $this->view, $this->userId, $filePath ); + + // We need to decrypt the keyfile + // Has the file been shared yet? + if ( + $this->userId == $fileOwner + && ! Keymanager::getShareKey( $this->view, $this->userId, $filePath ) // NOTE: we can't use isShared() here because it's a post share hook so it always returns true + ) { + + // The file has no shareKey, and its keyfile must be + // decrypted conventionally + $plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey ); + + + } else { + + // The file has a shareKey and must use it for decryption + $shareKey = Keymanager::getShareKey( $this->view, $this->userId, $filePath ); + + $plainKeyfile = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); + + } + + // Re-enc keyfile to (additional) sharekeys + $newShareKeys = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys ); + + // Save new sharekeys to all necessary user folders + if ( ! Keymanager::setShareKeys( $this->view, $filePath, $newShareKeys['keys'] ) ) { + + trigger_error( "SET Share keys failed" ); + + } + + // Delete existing keyfile + // Do this last to ensure file is recoverable in case of error + // Keymanager::deleteFileKey( $this->view, $this->userId, $params['fileTarget'] ); + + \OC_FileProxy::$enabled = true; + + return true; + } } diff --git a/apps/files_encryption/test/util.php b/apps/files_encryption/test/util.php index 1cdeff8008..275e60f4bd 100755 --- a/apps/files_encryption/test/util.php +++ b/apps/files_encryption/test/util.php @@ -150,13 +150,13 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase { } - function testFindFiles() { + function testFindEncFiles() { // $this->view->chroot( "/data/{$this->userId}/files" ); $util = new Encryption\Util( $this->view, $this->userId ); - $files = $util->findFiles( '/', 'encrypted' ); + $files = $util->findEncFiles( '/', 'encrypted' ); var_dump( $files ); From 40efeb91878e72eb5c2eb1ab50574cda9435e0fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 22 Feb 2013 16:02:27 +0100 Subject: [PATCH 022/257] isSharedFile() doesn't detect all shares, just use getUsersSharingFile() directly either you get a list of users or not --- apps/files_encryption/lib/proxy.php | 6 +---- lib/public/share.php | 34 ----------------------------- 2 files changed, 1 insertion(+), 39 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 9e6a11d9d4..ebe09dc075 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -113,14 +113,10 @@ class Proxy extends \OC_FileProxy { $encData = Crypt::symmetricEncryptFileContentKeyfile( $data ); // Check if the keyfile needs to be shared - if ( \OCP\Share::isSharedFile( $filePath ) ) { + if ( ($userIds = \OCP\Share::getUsersSharingFile( $filePath, true )) ) { // $fileOwner = \OC\Files\Filesystem::getOwner( $path ); - // List everyone sharing the file - //TODO check, is this path always the path to the source file? - $userIds = \OCP\Share::getUsersSharingFile( $filePath, true ); - $publicKeys = Keymanager::getPublicKeys( $rootView, $userIds ); \OC_FileProxy::$enabled = false; diff --git a/lib/public/share.php b/lib/public/share.php index 720337c3c3..7630c8ae6c 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -108,41 +108,7 @@ class Share { return $path; } - - public static function isSharedFile( $path ) { - - $fPath = self::prepFileTarget( $path ); - - // Fetch all shares of this file path from DB - $query = \OC_DB::prepare( - 'SELECT - id - FROM - `*PREFIX*share` - WHERE - file_target = ?' - ); - - $result = $query->execute( array( $fPath ) ); - if ( \OC_DB::isError( $result ) ) { - - \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage( $result ) . ', path=' . $fPath, \OC_Log::ERROR ); - - } - - if ( $result->fetchRow() !== false ) { - - return true; - - } else { - - return false; - - } - - } - /** * @brief Find which users can access a shared item * @param $path to the file From 31c434b79560c3c45e6202cecc635ad6cb887390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 22 Feb 2013 16:08:08 +0100 Subject: [PATCH 023/257] the default should be to encrypt all files if the user/admin doesn't specify a blacklist explicitely --- apps/files_encryption/lib/proxy.php | 2 +- apps/files_encryption/settings-personal.php | 2 +- apps/files_encryption/settings.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index ebe09dc075..56c9000bfb 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -70,7 +70,7 @@ class Proxy extends \OC_FileProxy { if ( is_null(self::$blackList ) ) { - self::$blackList = explode(',', \OCP\Config::getAppValue( 'files_encryption', 'type_blacklist', 'jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg' ) ); + self::$blackList = explode(',', \OCP\Config::getAppValue( 'files_encryption', 'type_blacklist', '' ) ); } diff --git a/apps/files_encryption/settings-personal.php b/apps/files_encryption/settings-personal.php index 6fe4ea6d56..94e37ebe96 100644 --- a/apps/files_encryption/settings-personal.php +++ b/apps/files_encryption/settings-personal.php @@ -8,7 +8,7 @@ $tmpl = new OCP\Template( 'files_encryption', 'settings-personal'); -$blackList = explode( ',', \OCP\Config::getAppValue( 'files_encryption', 'type_blacklist', 'jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg' ) ); +$blackList = explode( ',', \OCP\Config::getAppValue( 'files_encryption', 'type_blacklist', '' ) ); $tmpl->assign( 'blacklist', $blackList ); diff --git a/apps/files_encryption/settings.php b/apps/files_encryption/settings.php index d1260f44e9..85c616bca7 100644 --- a/apps/files_encryption/settings.php +++ b/apps/files_encryption/settings.php @@ -10,7 +10,7 @@ $tmpl = new OCP\Template( 'files_encryption', 'settings' ); -$blackList = explode( ',', \OCP\Config::getAppValue( 'files_encryption', 'type_blacklist', 'jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg' ) ); +$blackList = explode( ',', \OCP\Config::getAppValue( 'files_encryption', 'type_blacklist', '' ) ); $tmpl->assign( 'blacklist', $blackList ); $tmpl->assign( 'encryption_mode', \OC_Appconfig::getValue( 'files_encryption', 'mode', 'none' ) ); From ca1b94d890c281507c31082f1116f15d246341dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 25 Feb 2013 12:29:07 +0100 Subject: [PATCH 024/257] make sure that home folders are mounted correctly before write/read keyfile --- apps/files_encryption/lib/keymanager.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index ec1fdd1fd5..d35ad8f4d5 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -105,6 +105,7 @@ class Keymanager { */ public static function setFileKey( \OC_FilesystemView $view, $path, $userId, $catfile ) { + \OC\Files\Filesystem::initMountPoints($userId); $basePath = '/' . $userId . '/files_encryption/keyfiles'; $targetPath = self::keySetPreparation( $view, $path, $basePath, $userId ); @@ -134,6 +135,7 @@ class Keymanager { */ public static function getFileKey( \OC_FilesystemView $view, $userId, $filePath ) { + \OC\Files\Filesystem::initMountPoints($userId); $filePath_f = ltrim( $filePath, '/' ); $keyfilePath = '/' . $userId . '/files_encryption/keyfiles/' . $filePath_f . '.key'; From 4550ae6a69c00aeab2f54d0210ae5dee90f7ee82 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 26 Feb 2013 18:11:29 +0000 Subject: [PATCH 025/257] Shared encrypted files now readable by both sharer and sharee --- apps/files_encryption/lib/crypt.php | 2 ++ apps/files_encryption/lib/keymanager.php | 20 ++++++++++--- apps/files_encryption/lib/proxy.php | 15 ++++++---- apps/files_encryption/lib/util.php | 37 +++++++++++++++++------- 4 files changed, 53 insertions(+), 21 deletions(-) diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index a677de950a..5a2d99df54 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -391,6 +391,8 @@ class Crypt { if( openssl_seal( $plainContent, $sealed, $shareKeys, $publicKeys ) ) { +// trigger_error("SEALED = $sealed"); + $i = 0; // Ensure each shareKey is labelled with its diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index d35ad8f4d5..ec4057d098 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -105,6 +105,8 @@ class Keymanager { */ public static function setFileKey( \OC_FilesystemView $view, $path, $userId, $catfile ) { + \OC_FileProxy::$enabled = false; + \OC\Files\Filesystem::initMountPoints($userId); $basePath = '/' . $userId . '/files_encryption/keyfiles'; @@ -112,15 +114,19 @@ class Keymanager { if ( $view->is_dir( $basePath . '/' . $targetPath ) ) { - + // FIXME: write me } else { // Save the keyfile in parallel directory - return $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile ); + $result = $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile ); } + \OC_FileProxy::$enabled = true; + + return $result; + } /** @@ -140,16 +146,22 @@ class Keymanager { $keyfilePath = '/' . $userId . '/files_encryption/keyfiles/' . $filePath_f . '.key'; + \OC_FileProxy::$enabled = false; + if ( $view->file_exists( $keyfilePath ) ) { - return $view->file_get_contents( $keyfilePath ); + $result = $view->file_get_contents( $keyfilePath ); } else { - return false; + $result = false; } + \OC_FileProxy::$enabled = true; + + return $result; + } /** diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 56c9000bfb..29207dce07 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -91,7 +91,8 @@ class Proxy extends \OC_FileProxy { return false; } - public function preFile_put_contents( $path, &$data ) { + public function preFile_put_contents( $path, &$data ) { + // TODO check for existing key file and reuse it if possible to avoid problems with versioning etc. if ( self::shouldEncrypt( $path ) ) { @@ -204,22 +205,22 @@ class Proxy extends \OC_FileProxy { // Get the encrypted keyfile $encKeyfile = Keymanager::getFileKey( $view, $fileOwner, $relPath ); - trigger_error("\$encKeyfile = ". var_export($encKeyfile, 1)); - // Attempt to fetch the user's shareKey $shareKey = Keymanager::getShareKey( $view, $userId, $relPath ); - trigger_error("\$shareKey = ".var_export($shareKey, 1)); - // Check if key is shared or not if ( $shareKey ) { \OC_FileProxy::$enabled = false; +// trigger_error("\$encKeyfile = $encKeyfile, \$shareKey = $shareKey, \$privateKey = $privateKey"); + // Decrypt keyfile with shareKey $plainKeyfile = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); - trigger_error("PROXY plainkeyfile = ". var_export($plainKeyfile, 1)); +// $plainKeyfile = $encKeyfile; + +// trigger_error("PROXY plainkeyfile = ". var_export($plainKeyfile, 1)); } else { @@ -229,6 +230,8 @@ class Proxy extends \OC_FileProxy { } $plainData = Crypt::symmetricDecryptFileContent( $data, $plainKeyfile ); + +// trigger_error("PLAINDATA = ". var_export($plainData, 1)); } elseif ( Crypt::mode() == 'server' diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index ac098cd877..920ff3eb15 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -21,17 +21,28 @@ * */ -// Todo: +# Bugs +# ---- +# Sharing a file to a user without encryption set up will not provide them with access but won't notify the sharer +# Deleting files if keyfile is missing fails +# When encryption app is disabled files become unreadable +# Timeouts on first login due to encryption of very large files +# MultiKeyEncrypt() may be failing + + +# Missing features +# ---------------- +# Unshare a file +# Re-use existing keyfiles so they don't need version control +# Make sure user knows if large files weren't encrypted +# Trashbin support + + +// Old Todo: // - Crypt/decrypt button in the userinterface // - Setting if crypto should be on by default // - Add a setting "Don´t encrypt files larger than xx because of performance // reasons" -// - Transparent decrypt/encrypt in filesystem.php. Autodetect if a file is -// encrypted (.encrypted extension) -// - Don't use a password directly as encryption key. but a key which is -// stored on the server and encrypted with the user password. -> password -// change faster -// - IMPORTANT! Check if the block lenght of the encrypted data stays the same namespace OCA\Encryption; @@ -663,10 +674,14 @@ class Util { } // Re-enc keyfile to (additional) sharekeys - $newShareKeys = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys ); - - // Save new sharekeys to all necessary user folders - if ( ! Keymanager::setShareKeys( $this->view, $filePath, $newShareKeys['keys'] ) ) { + $multiEncKey = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys ); + + // Save the recrypted key to it's owner's keyfiles directory + // Save new sharekeys to all necessary user directory + if ( + ! Keymanager::setFileKey( $this->view, $filePath, $fileOwner, $multiEncKey['data'] ) + || ! Keymanager::setShareKeys( $this->view, $filePath, $multiEncKey['keys'] ) + ) { trigger_error( "SET Share keys failed" ); From aae9b0b1bfc95d60bcc7c4a4b85a387a94ac9caa Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 26 Feb 2013 18:33:31 +0000 Subject: [PATCH 026/257] Started work on post unshare hook Development snapshot --- apps/files_encryption/hooks/hooks.php | 116 ++++++++++++++++------- apps/files_encryption/lib/keymanager.php | 24 +++++ apps/files_encryption/lib/util.php | 3 +- 3 files changed, 108 insertions(+), 35 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 6d982b2c3b..bf16a492e3 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -167,44 +167,60 @@ class Hooks { * @brief get all users with access to the file and encrypt the file key to each of them */ public static function postShared( $params ) { - - // NOTE: $params is an array with these keys: + + // NOTE: $params has keys: + // [itemType] => file // itemSource -> int, filecache file ID + // [parent] => + // [itemTarget] => /13 // shareWith -> string, uid of user being shared to // fileTarget -> path of file being shared // uidOwner -> owner of the original file being shared + // [shareType] => 0 + // [shareWith] => test1 + // [uidOwner] => admin + // [permissions] => 17 + // [fileSource] => 13 + // [fileTarget] => /test8 + // [id] => 10 + // [token] => - $view = new \OC_FilesystemView( '/' ); - $session = new Session(); - $userId = \OCP\User::getUser(); - $util = new Util( $view, $userId ); - $path = $util->fileIdToPath( $params['itemSource'] ); + // TODO: Should other kinds of item be encrypted too? + if ( $params['itemType'] === 'file' ) { - $usersSharing = \OCP\Share::getUsersSharingFile( $path, true ); - - $allPaths = $util->getPaths( $path ); - - $failed = array(); - - foreach ( $allPaths as $path ) { - - if ( ! $util->setSharedFileKeyfiles( $session, $usersSharing, $path ) ) { + $view = new \OC_FilesystemView( '/' ); + $session = new Session(); + $userId = \OCP\User::getUser(); + $util = new Util( $view, $userId ); + $path = $util->fileIdToPath( $params['itemSource'] ); - $failed[] = $path; + $usersSharing = \OCP\Share::getUsersSharingFile( $path, true ); + + $allPaths = $util->getPaths( $path ); + + $failed = array(); + + foreach ( $allPaths as $path ) { + + if ( ! $util->setSharedFileKeyfiles( $session, $usersSharing, $path ) ) { + + $failed[] = $path; + + } } - } - - // If no attempts to set keyfiles failed - if ( empty( $failed ) ) { - - return true; + // If no attempts to set keyfiles failed + if ( empty( $failed ) ) { - } else { - - return false; + return true; + + } else { + return false; + + } + } } @@ -213,15 +229,47 @@ class Hooks { * @brief */ public static function postUnshare( $params ) { - -// $view = new \OC_FilesystemView( '/' ); -// $session = new Session(); -// $userId = \OCP\User::getUser(); -// $util = new Util( $view, $userId ); -// $path = $util->fileIdToPath( $params['itemSource'] ); -// -// return Crypt::updateKeyfile( $view, $util, $session, $userId, $path ); + // NOTE: $params has keys: + // [itemType] => file + // [itemSource] => 13 + // [shareType] => 0 + // [shareWith] => test1 + + // TODO: Should other kinds of item be encrypted too? + if ( $params['itemType'] === 'file' ) { + + $view = new \OC_FilesystemView( '/' ); + $session = new Session(); + $userId = \OCP\User::getUser(); + $util = new Util( $view, $userId ); + $path = $util->fileIdToPath( $params['itemSource'] ); + + $allPaths = $util->getPaths( $path ); + + foreach ( $allPaths as $path ) { + + if ( ! Keymanager::delShareKey( $view, $userId, $path ) ) { + + $failed[] = $path; + + } + + } + + // If no attempts to set keyfiles failed + if ( empty( $failed ) ) { + + return true; + + } else { + + return false; + + } + + } + } /** diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index ec4057d098..22e2ffa500 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -350,6 +350,30 @@ class Keymanager { } + /** + * @brief Delete a single user's shareKey for a single file + */ + public static function delShareKey( \OC_FilesystemView $view, $userId, $filePath ) { + + $trimmed = ltrim( $filePath, '/' ); + $shareKeyPath = '/' . $userId . '/files_encryption/share-keys/' . $trimmed . '.shareKey'; + + // Unlink doesn't tell us if file was deleted (not found returns + // true), so we perform our own test + if ( $view->file_exists( $shareKeyPath ) ) { + + return $view->unlink( $shareKeyPath ); + + } else { + + \OC_Log::write( 'Encryption library', 'Could not delete shareKey; does not exist: "' . $shareKeyPath, \OC_Log::ERROR ); + + return false; + + } + + } + /** * @brief Make preparations to vars and filesystem for saving a keyfile */ diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 920ff3eb15..02c62e160c 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -580,7 +580,8 @@ class Util { * @brief Expand given path to all sub files & folders * @param Session $session * @param string $path path which needs to be updated - * @return bool outcome of attempt to set keyfiles + * @return array $pathsArray all found file paths + * @note Paths of directories excluded, only *file* paths are returned */ public function getPaths( $path ) { From 14eae441eb77ee53304d8a164deb146bda4020f4 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Wed, 27 Feb 2013 15:31:23 +0000 Subject: [PATCH 027/257] Unsharing a single file now works --- apps/files_encryption/hooks/hooks.php | 4 +++- apps/files_encryption/lib/keymanager.php | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index bf16a492e3..fb3545208d 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -245,11 +245,13 @@ class Hooks { $util = new Util( $view, $userId ); $path = $util->fileIdToPath( $params['itemSource'] ); + // If path is a folder, get all children $allPaths = $util->getPaths( $path ); foreach ( $allPaths as $path ) { - if ( ! Keymanager::delShareKey( $view, $userId, $path ) ) { + // Unshare each child path + if ( ! Keymanager::delShareKey( $view, $params['shareWith'], $path ) ) { $failed[] = $path; diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 22e2ffa500..62bb12bf90 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -355,6 +355,8 @@ class Keymanager { */ public static function delShareKey( \OC_FilesystemView $view, $userId, $filePath ) { + \OC_FileProxy::$enabled = false; + $trimmed = ltrim( $filePath, '/' ); $shareKeyPath = '/' . $userId . '/files_encryption/share-keys/' . $trimmed . '.shareKey'; @@ -362,16 +364,22 @@ class Keymanager { // true), so we perform our own test if ( $view->file_exists( $shareKeyPath ) ) { - return $view->unlink( $shareKeyPath ); + $result = $view->unlink( $shareKeyPath ); } else { + trigger_error("Could not delete shareKey; does not exist: $shareKeyPath"); + \OC_Log::write( 'Encryption library', 'Could not delete shareKey; does not exist: "' . $shareKeyPath, \OC_Log::ERROR ); - return false; + $result = false; } + \OC_FileProxy::$enabled = false; + + return $result; + } /** From 69bc42f920324ef02ade5dff6bd52f2ddde113a2 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Wed, 27 Feb 2013 16:15:03 +0000 Subject: [PATCH 028/257] Deleting encrypted files with missing keyfiles/shareKeys now succeeds --- apps/files_encryption/hooks/hooks.php | 9 ++------- apps/files_encryption/lib/crypt.php | 2 -- apps/files_encryption/lib/proxy.php | 27 +++++++++++++++++++++------ apps/files_encryption/lib/util.php | 3 --- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index fb3545208d..590ba7b1b9 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -279,13 +279,8 @@ class Hooks { */ public static function postUnshareAll( $params ) { -// $view = new \OC_FilesystemView( '/' ); -// $session = new Session(); -// $userId = \OCP\User::getUser(); -// $util = new Util( $view, $userId ); -// $path = $util->fileIdToPath( $params['itemSource'] ); -// -// return Crypt::updateKeyfile( $view, $util, $session, $userId, $path ); + // NOTE: It appears that this is never called for files, so + // we may not need to implement it } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 5a2d99df54..a138f5f3cb 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -390,8 +390,6 @@ class Crypt { $shareKeys = array(); if( openssl_seal( $plainContent, $sealed, $shareKeys, $publicKeys ) ) { - -// trigger_error("SEALED = $sealed"); $i = 0; diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 29207dce07..92a7049936 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -272,23 +272,38 @@ class Proxy extends \OC_FileProxy { $split = explode( '/', $trimmed ); $sliced = array_slice( $split, 2 ); $relPath = implode( '/', $sliced ); + $filePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/'. $relPath; if ( $view->is_dir( $path ) ) { // Dirs must be handled separately as deleteFileKey // doesn't handle them - $view->unlink( $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/'. $relPath ); + $view->unlink( $filePath ); } else { - // Delete keyfile so it isn't orphaned - $result = Keymanager::deleteFileKey( $view, $userId, $relPath ); - - \OC_FileProxy::$enabled = true; + // Delete keyfile & shareKey so it isn't orphaned + if ( + ! ( + Keymanager::deleteFileKey( $view, $userId, $relPath ) + && Keymanager::delShareKey( $view, $userId, $relPath ) + ) + ) { + + \OC_Log::write( 'Encryption library', 'Keyfile or shareKey could not be deleted for file "'.$filePath.'"', \OC_Log::ERROR ); + + + } + - return $result; } + + \OC_FileProxy::$enabled = true; + + // If we don't return true then file delete will fail; better + // to leave orphaned keyfiles than to disallow file deletion + return true; } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 02c62e160c..31ce3a413c 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -24,15 +24,12 @@ # Bugs # ---- # Sharing a file to a user without encryption set up will not provide them with access but won't notify the sharer -# Deleting files if keyfile is missing fails # When encryption app is disabled files become unreadable # Timeouts on first login due to encryption of very large files -# MultiKeyEncrypt() may be failing # Missing features # ---------------- -# Unshare a file # Re-use existing keyfiles so they don't need version control # Make sure user knows if large files weren't encrypted # Trashbin support From 953319a2c3d85bf0d5eb86511c7466188b5ca45f Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Wed, 27 Feb 2013 18:46:44 +0000 Subject: [PATCH 029/257] Made proxy class reuse existing keyfiles not gen new ones; Added notes about reusing shareKeys --- apps/files_encryption/lib/keymanager.php | 2 - apps/files_encryption/lib/proxy.php | 46 +++++++++++++++------- apps/files_encryption/lib/util.php | 50 ++++++++++++++++-------- 3 files changed, 65 insertions(+), 33 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 62bb12bf90..0c2db2be32 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -368,8 +368,6 @@ class Keymanager { } else { - trigger_error("Could not delete shareKey; does not exist: $shareKeyPath"); - \OC_Log::write( 'Encryption library', 'Could not delete shareKey; does not exist: "' . $shareKeyPath, \OC_Log::ERROR ); $result = false; diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 92a7049936..c5b1c8154c 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -93,16 +93,17 @@ class Proxy extends \OC_FileProxy { public function preFile_put_contents( $path, &$data ) { - // TODO check for existing key file and reuse it if possible to avoid problems with versioning etc. if ( self::shouldEncrypt( $path ) ) { // Stream put contents should have been converted to fopen if ( !is_resource( $data ) ) { - // TODO check who is the owner of the file in case of shared folders $userId = \OCP\USER::getUser(); $rootView = new \OC_FilesystemView( '/' ); $util = new Util( $rootView, $userId ); + $session = new Session(); + $fileOwner = \OC\Files\Filesystem::getOwner( $path ); + $privateKey = $session->getPrivateKey(); $filePath = $util->stripUserFilesPath( $path ); // Set the filesize for userland, before encrypting $size = strlen( $data ); @@ -110,45 +111,62 @@ class Proxy extends \OC_FileProxy { // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; + // Check if there is an existing key we can reuse + if ( $encKeyfile = Keymanager::getFileKey( $rootView, $fileOwner, $filePath ) ) { + + $keyPreExists = true; + + // Decrypt the keyfile + $plainKey = $util->decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey ); + + } else { + + $keyPreExists = false; + + // Make a new key + $plainKey = Crypt::generateKey(); + + } + // Encrypt data - $encData = Crypt::symmetricEncryptFileContentKeyfile( $data ); + $encData = Crypt::symmetricEncryptFileContent( $data, $plainKey ); // Check if the keyfile needs to be shared - if ( ($userIds = \OCP\Share::getUsersSharingFile( $filePath, true )) ) { - -// $fileOwner = \OC\Files\Filesystem::getOwner( $path ); + if ( $userIds = \OCP\Share::getUsersSharingFile( $filePath, true ) ) { $publicKeys = Keymanager::getPublicKeys( $rootView, $userIds ); \OC_FileProxy::$enabled = false; // Encrypt plain keyfile to multiple sharefiles - $multiEncrypted = Crypt::multiKeyEncrypt( $encData['key'], $publicKeys ); + $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys ); // Save sharekeys to user folders + // TODO: openssl_seal generates new shareKeys (envelope keys) each time data is encrypted, but will data still be decryptable using old shareKeys? If so we don't need to replace the old shareKeys here, we only need to set the new ones Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] ); // Set encrypted keyfile as common varname $encKey = $multiEncrypted['encrypted']; - - } else { $publicKey = Keymanager::getPublicKey( $rootView, $userId ); // Encrypt plain data to a single user - $encKey = Crypt::keyEncrypt( $encData['key'], $publicKey ); + $encKey = Crypt::keyEncrypt( $plainKey, $publicKey ); } - // TODO: Replace userID with ownerId so keyfile is saved centrally + // Save the key if its new + if ( ! $keyPreExists ) { - // Save keyfile for newly encrypted file in parallel directory tree - Keymanager::setFileKey( $rootView, $filePath, $userId, $encKey ); + // Save keyfile for newly encrypted file in parallel directory tree + Keymanager::setFileKey( $rootView, $filePath, $fileOwner, $encKey ); + + } // Replace plain content with encrypted content by reference - $data = $encData['encrypted']; + $data = $encData; // Update the file cache with file info \OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' ); diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 31ce3a413c..cd223bd702 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -626,25 +626,15 @@ class Util { } /** - * @brief Encrypt keyfile to multiple users - * @param array $users list of users which should be able to access the file - * @param string $filePath path of the file to be shared + * @brief Decrypt a keyfile without knowing how it was encrypted + * @param string $filePath + * @param string $fileOwner + * @param string $privateKey + * @note Checks whether file was encrypted with openssl_seal or + * openssl_encrypt, and decrypts accrdingly */ - public function setSharedFileKeyfiles( Session $session, array $users, $filePath ) { - - // Make sure users are capable of sharing - $filteredUids = $this->filterShareReadyUsers( $users ); - - // Get public keys for each user, ready for generating sharekeys - $userPubKeys = Keymanager::getPublicKeys( $this->view, $filteredUids ); // TODO: check this includes the owner's public key + public function decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey ) { - \OC_FileProxy::$enabled = false; - - // Get the current users's private key for decrypting existing keyfile - $privateKey = $session->getPrivateKey(); - - $fileOwner = \OC\Files\Filesystem::getOwner( $filePath ); - // Get the encrypted keyfile // NOTE: the keyfile format depends on how it was encrypted! At // this stage we don't know how it was encrypted @@ -671,6 +661,32 @@ class Util { } + return $plainKeyfile; + + } + + /** + * @brief Encrypt keyfile to multiple users + * @param array $users list of users which should be able to access the file + * @param string $filePath path of the file to be shared + */ + public function setSharedFileKeyfiles( Session $session, array $users, $filePath ) { + + // Make sure users are capable of sharing + $filteredUids = $this->filterShareReadyUsers( $users ); + + // Get public keys for each user, ready for generating sharekeys + $userPubKeys = Keymanager::getPublicKeys( $this->view, $filteredUids ); // TODO: check this includes the owner's public key + + \OC_FileProxy::$enabled = false; + + // Get the current users's private key for decrypting existing keyfile + $privateKey = $session->getPrivateKey(); + + $fileOwner = \OC\Files\Filesystem::getOwner( $filePath ); + + $plainKeyfile = $this->decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey ); + // Re-enc keyfile to (additional) sharekeys $multiEncKey = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys ); From 0bc7d3bcf833e257fa4b2ae3b74d60bef63218b8 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Wed, 27 Feb 2013 18:50:57 +0000 Subject: [PATCH 030/257] Added notes where to reuse old keys instead of generating new ones --- apps/files_encryption/lib/stream.php | 1 + apps/files_encryption/lib/util.php | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index d4b993b4c0..f4bd6f1b6b 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -318,6 +318,7 @@ class Stream { // one), save the newly generated keyfile if ( ! $this->getKey() ) { + // TODO: Reuse the keyfile, it it exists, instead of making a new one $this->keyfile = Crypt::generateKey(); $this->publicKey = Keymanager::getPublicKey( $this->rootView, $this->userId ); diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index cd223bd702..6a18feea7d 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -692,6 +692,7 @@ class Util { // Save the recrypted key to it's owner's keyfiles directory // Save new sharekeys to all necessary user directory + // TODO: Reuse the keyfile, it it exists, instead of making a new one if ( ! Keymanager::setFileKey( $this->view, $filePath, $fileOwner, $multiEncKey['data'] ) || ! Keymanager::setShareKeys( $this->view, $filePath, $multiEncKey['keys'] ) From e65e6a12f1270faec377363f02f27ddd7d68b8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 4 Mar 2013 15:33:38 +0100 Subject: [PATCH 031/257] define key size in constructor, otherwise the key size will depend on the servers openssl conf --- apps/files_encryption/lib/crypt.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index a138f5f3cb..2be6e3ae5d 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -56,7 +56,7 @@ class Crypt { */ public static function createKeypair() { - $res = openssl_pkey_new(); + $res = openssl_pkey_new(array('private_key_bits' => 4096)); // Get private key openssl_pkey_export( $res, $privateKey ); @@ -450,7 +450,7 @@ class Crypt { * @returns encrypted file */ public static function keyEncrypt( $plainContent, $publicKey ) { - + openssl_public_encrypt( $plainContent, $encryptedContent, $publicKey ); return $encryptedContent; From f2b86d0227d080dd4395efaf5fb086b024af0c95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 4 Mar 2013 17:58:56 +0100 Subject: [PATCH 032/257] make sure that $this->userId is initialized before using it as a parameter --- apps/files_encryption/lib/stream.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index f4bd6f1b6b..6074638ab3 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -68,6 +68,8 @@ class Stream { private $rootView; // a fsview object set to '/' public function stream_open( $path, $mode, $options, &$opened_path ) { + + $this->userId = \OCP\User::getUser(); // Get access to filesystem via filesystemview object if ( !self::$view ) { @@ -82,9 +84,7 @@ class Stream { $this->rootView = new \OC_FilesystemView( $this->userId . '/' ); } - - $this->userId = \OCP\User::getUser(); - + // Get the bare file path $path = str_replace( 'crypt://', '', $path ); From c1f1fbda08b464b286e309283ed81d16f30a5ca6 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Sat, 9 Mar 2013 19:18:34 +0100 Subject: [PATCH 033/257] Fixed stream wrapper bugs Switched encryptAll() to use stream-based instead of file-at-a-time encryption Development snapshot --- apps/files_encryption/lib/crypt.php | 4 +- apps/files_encryption/lib/proxy.php | 10 ++-- apps/files_encryption/lib/stream.php | 60 +++++++++------------ apps/files_encryption/lib/util.php | 78 +++++++++++++++++++++++----- apps/files_encryption/test/crypt.php | 6 +-- 5 files changed, 99 insertions(+), 59 deletions(-) diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 2be6e3ae5d..f92930c2cb 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -114,7 +114,7 @@ class Crypt { * @return true / false * @note see also OCA\Encryption\Util->isEncryptedPath() */ - public static function isCatfile( $content ) { + public static function isCatfileContent( $content ) { if ( !$content ) { @@ -179,7 +179,7 @@ class Crypt { if ( isset( $metadata['encrypted'] ) and $metadata['encrypted'] === true - and ! self::isCatfile( $data ) + and ! self::isCatfileContent( $data ) ) { return true; diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index c5b1c8154c..2a738c80e3 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -74,7 +74,7 @@ class Proxy extends \OC_FileProxy { } - if ( Crypt::isCatfile( $path ) ) { + if ( Crypt::isCatfileContent( $path ) ) { return true; @@ -209,7 +209,7 @@ class Proxy extends \OC_FileProxy { // If data is a catfile if ( Crypt::mode() == 'server' - && Crypt::isCatfile( $data ) + && Crypt::isCatfileContent( $data ) ) { // TODO use get owner to find correct location of key files for shared files @@ -439,7 +439,7 @@ class Proxy extends \OC_FileProxy { public function postGetMimeType( $path, $mime ) { - if ( Crypt::isCatfile( $path ) ) { + if ( Crypt::isCatfileContent( $path ) ) { $mime = \OCP\Files::getMimeType( 'crypt://' . $path, 'w' ); @@ -451,7 +451,7 @@ class Proxy extends \OC_FileProxy { public function postStat( $path, $data ) { - if ( Crypt::isCatfile( $path ) ) { + if ( Crypt::isCatfileContent( $path ) ) { $cached = \OC\Files\Filesystem::getFileInfo( $path, '' ); @@ -464,7 +464,7 @@ class Proxy extends \OC_FileProxy { public function postFileSize( $path, $size ) { - if ( Crypt::isCatfile( $path ) ) { + if ( Crypt::isCatfileContent( $path ) ) { $cached = \OC\Files\Filesystem::getFileInfo( $path, '' ); diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 6074638ab3..0b2e6ab3e6 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -68,42 +68,33 @@ class Stream { private $rootView; // a fsview object set to '/' public function stream_open( $path, $mode, $options, &$opened_path ) { - + $this->userId = \OCP\User::getUser(); - // Get access to filesystem via filesystemview object - if ( !self::$view ) { + if ( ! isset( $this->rootView ) ) { - self::$view = new \OC_FilesystemView( $this->userId . '/' ); - - } - - // Set rootview object if necessary - if ( ! $this->rootView ) { - - $this->rootView = new \OC_FilesystemView( $this->userId . '/' ); + $this->rootView = new \OC_FilesystemView( '/' ); } - // Get the bare file path - $path = str_replace( 'crypt://', '', $path ); + // Strip identifier text from path + $this->rawPath = str_replace( 'crypt://', '', $path ); - $this->rawPath = $path; - - $this->path_f = $this->userId . '/files/' . $path; + // Set file path relative to user files dir + $this->relPath = $this->userId . '/files/' . $this->rawPath; if ( - dirname( $path ) == 'streams' - and isset( self::$sourceStreams[basename( $path )] ) + dirname( $this->rawPath ) == 'streams' + and isset( self::$sourceStreams[basename( $this->rawPath )] ) ) { // Is this just for unit testing purposes? - $this->handle = self::$sourceStreams[basename( $path )]['stream']; + $this->handle = self::$sourceStreams[basename( $this->rawPath )]['stream']; - $this->path = self::$sourceStreams[basename( $path )]['path']; + $this->path = self::$sourceStreams[basename( $this->rawPath )]['path']; - $this->size = self::$sourceStreams[basename( $path )]['size']; + $this->size = self::$sourceStreams[basename( $this->rawPath )]['size']; } else { @@ -114,41 +105,38 @@ class Stream { or $mode == 'wb+' ) { + // We're writing a new file so start write counter with 0 bytes $this->size = 0; } else { + $this->size = $this->rootView->filesize( $this->relPath, $mode ); - - $this->size = self::$view->filesize( $this->path_f, $mode ); - - //$this->size = filesize( $path ); + //$this->size = filesize( $this->rawPath ); } // Disable fileproxies so we can open the source file without recursive encryption \OC_FileProxy::$enabled = false; - //$this->handle = fopen( $path, $mode ); + //$this->handle = fopen( $this->rawPath, $mode ); - $this->handle = self::$view->fopen( $this->path_f, $mode ); + $this->handle = $this->rootView->fopen( $this->relPath, $mode ); \OC_FileProxy::$enabled = true; - if ( !is_resource( $this->handle ) ) { + if ( ! is_resource( $this->handle ) ) { - \OCP\Util::writeLog( 'files_encryption', 'failed to open '.$path, \OCP\Util::ERROR ); + \OCP\Util::writeLog( 'files_encryption', 'failed to open file "'.$this->rootView . '"', \OCP\Util::ERROR ); + } else { + + $this->meta = stream_get_meta_data( $this->handle ); + } } - if ( is_resource( $this->handle ) ) { - - $this->meta = stream_get_meta_data( $this->handle ); - - } - return is_resource( $this->handle ); } @@ -238,7 +226,7 @@ class Stream { // If a keyfile already exists for a file named identically to // file to be written - if ( self::$view->file_exists( $this->userId . '/'. 'files_encryption' . '/' . 'keyfiles' . '/' . $this->rawPath . '.key' ) ) { + if ( $this->rootView->file_exists( $this->userId . '/'. 'files_encryption' . '/' . 'keyfiles' . '/' . $this->rawPath . '.key' ) ) { // TODO: add error handling for when file exists but no // keyfile diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 6a18feea7d..e8b5be2de1 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -24,13 +24,12 @@ # Bugs # ---- # Sharing a file to a user without encryption set up will not provide them with access but won't notify the sharer -# When encryption app is disabled files become unreadable # Timeouts on first login due to encryption of very large files # Missing features # ---------------- -# Re-use existing keyfiles so they don't need version control +# Re-use existing keyfiles so they don't need version control (part implemented, stream{} and util{} remain) # Make sure user knows if large files weren't encrypted # Trashbin support @@ -280,14 +279,14 @@ class Util { // will eat server resources :( if ( Keymanager::getFileKey( $this->view, $this->userId, $file ) - && Crypt::isCatfile( $data ) + && Crypt::isCatfileContent( $data ) ) { $found['encrypted'][] = array( 'name' => $file, 'path' => $filePath ); // If the file uses old // encryption system - } elseif ( Crypt::isLegacyEncryptedContent( $this->view->file_get_contents( $filePath ), $relPath ) ) { + } elseif ( Crypt::isLegacyEncryptedContent( $this->tail( $filePath, 3 ), $relPath ) ) { $found['legacy'][] = array( 'name' => $file, 'path' => $filePath ); @@ -324,6 +323,49 @@ class Util { } + /** + * @brief Fetch the last lines of a file efficiently + * @note Safe to use on large files; does not read entire file to memory + * @note Derivative of http://tekkie.flashbit.net/php/tail-functionality-in-php + */ + public function tail( $filename, $numLines ) { + + \OC_FileProxy::$enabled = false; + + $text = ''; + $pos = -1; + $handle = $this->view->fopen( $filename, 'r' ); + + while ( $numLines > 0 ) { + + --$pos; + + if( fseek( $handle, $pos, SEEK_END ) !== 0 ) { + + rewind( $handle ); + $numLines = 0; + + } elseif ( fgetc( $handle ) === "\n" ) { + + --$numLines; + + } + + $block_size = ( -$pos ) % 8192; + if ( $block_size === 0 || $numLines === 0 ) { + + $text = fread( $handle, ( $block_size === 0 ? 8192 : $block_size ) ) . $text; + + } + } + + fclose( $handle ); + + \OC_FileProxy::$enabled = true; + + return $text; + } + /** * @brief Check if a given path identifies an encrypted file * @return true / false @@ -338,7 +380,7 @@ class Util { \OC_FileProxy::$enabled = true; - return Crypt::isCatfile( $data ); + return Crypt::isCatfileContent( $data ); } @@ -403,22 +445,32 @@ class Util { // Encrypt unencrypted files foreach ( $found['plain'] as $plainFile ) { + + // Open plain file handle - // Fetch data from file - $plainData = $this->view->file_get_contents( $plainFile['path'] ); - // Encrypt data, generate catfile - $encrypted = Crypt::keyEncryptKeyfile( $plainData, $publicKey ); + // Open enc file handle + + + // Read plain file in chunks + $relPath = $this->stripUserFilesPath( $plainFile['path'] ); - // Save keyfile - Keymanager::setFileKey( $this->view, $relPath, $this->userId, $encrypted['key'] ); + // Open handle with for binary reading + $plainHandle = $this->view->fopen( $plainFile['path'], 'rb' ); + // Open handle with for binary writing + $encHandle = fopen( 'crypt://' . 'var/www/oc6/data/' . $plainFile['path'] . '.tmp', 'ab' ); // Overwrite the existing file with the encrypted one - $this->view->file_put_contents( $plainFile['path'], $encrypted['data'] ); + //$this->view->file_put_contents( $plainFile['path'], $encrypted['data'] ); + $size = stream_copy_to_stream( $plainHandle, $encHandle ); - $size = strlen( $encrypted['data'] ); + // Fetch the key that has just been set/updated by the stream + $encKey = Keymanager::getFileKey( $relPath ); + + // Save keyfile + Keymanager::setFileKey( $this->view, $relPath, $this->userId, $encKey ); // Add the file to the cache \OC\Files\Filesystem::putFileInfo( $plainFile['path'], array( 'encrypted'=>true, 'size' => $size ), '' ); diff --git a/apps/files_encryption/test/crypt.php b/apps/files_encryption/test/crypt.php index 48ad2ee007..b02e63b2ff 100755 --- a/apps/files_encryption/test/crypt.php +++ b/apps/files_encryption/test/crypt.php @@ -416,13 +416,13 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { function testIsEncryptedContent() { - $this->assertFalse( Encryption\Crypt::isCatfile( $this->dataUrl ) ); + $this->assertFalse( Encryption\Crypt::isCatfileContent( $this->dataUrl ) ); - $this->assertFalse( Encryption\Crypt::isCatfile( $this->legacyEncryptedData ) ); + $this->assertFalse( Encryption\Crypt::isCatfileContent( $this->legacyEncryptedData ) ); $keyfileContent = Encryption\Crypt::symmetricEncryptFileContent( $this->dataUrl, 'hat' ); - $this->assertTrue( Encryption\Crypt::isCatfile( $keyfileContent ) ); + $this->assertTrue( Encryption\Crypt::isCatfileContent( $keyfileContent ) ); } From c89fd49870e3bdd66b73ab6d8d64895e870de260 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 19 Mar 2013 19:53:15 +0100 Subject: [PATCH 034/257] Improved folder creation code Created stub method for checking user pwd recovery preference from db Added pwd recovery column to db Added comments --- apps/files_encryption/appinfo/database.xml | 8 +++ apps/files_encryption/hooks/hooks.php | 6 +- apps/files_encryption/lib/util.php | 68 ++++++++++------------ 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/apps/files_encryption/appinfo/database.xml b/apps/files_encryption/appinfo/database.xml index d294c35d63..b144b6cb2a 100644 --- a/apps/files_encryption/appinfo/database.xml +++ b/apps/files_encryption/appinfo/database.xml @@ -18,6 +18,14 @@ text true 64 + What client-side / server-side configuration is used + + + recovery + boolean + true + 0 + Whether encryption key recovery is enabled diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 590ba7b1b9..8db7539706 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -29,9 +29,6 @@ namespace OCA\Encryption; class Hooks { - // TODO: use passphrase for encrypting private key that is separate to - // the login password - /** * @brief Startup encryption backend upon user login * @note This method should never be called for users using client side encryption @@ -196,12 +193,15 @@ class Hooks { $usersSharing = \OCP\Share::getUsersSharingFile( $path, true ); + // Recursively expand path to include subfiles $allPaths = $util->getPaths( $path ); $failed = array(); + // Loop through all subfiles foreach ( $allPaths as $path ) { + // Attempt to set shareKey if ( ! $util->setSharedFileKeyfiles( $session, $usersSharing, $path ) ) { $failed[] = $path; diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index e8b5be2de1..a80da73a4b 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -153,45 +153,24 @@ class Util { */ public function setupServerSide( $passphrase = null ) { - // Create user dir - if( !$this->view->file_exists( $this->userDir ) ) { + // Set directories to check / create + $setUpDirs = array( + $this->userDir + , $this->userFilesDir + , $this->publicKeyDir + , $this->encryptionDir + , $this->keyfilesPath + , $this->shareKeysPath + ); - $this->view->mkdir( $this->userDir ); + // Check / create all necessary dirs + foreach ( $setUpDirs as $dirPath ) { - } - - // Create user files dir - if( !$this->view->file_exists( $this->userFilesDir ) ) { - - $this->view->mkdir( $this->userFilesDir ); - - } - - // Create shared public key directory - if( !$this->view->file_exists( $this->publicKeyDir ) ) { - - $this->view->mkdir( $this->publicKeyDir ); - - } - - // Create encryption app directory - if( !$this->view->file_exists( $this->encryptionDir ) ) { - - $this->view->mkdir( $this->encryptionDir ); - - } - - // Create mirrored keyfile directory - if( !$this->view->file_exists( $this->keyfilesPath ) ) { - - $this->view->mkdir( $this->keyfilesPath ); - - } - - // Create mirrored share env keys directory - if( !$this->view->file_exists( $this->shareKeysPath ) ) { - - $this->view->mkdir( $this->shareKeysPath ); + if( !$this->view->file_exists( $dirPath ) ) { + + $this->view->mkdir( $dirPath ); + + } } @@ -223,6 +202,20 @@ class Util { } + public function recoveryEnabled( ) { + + $sql = 'SELECT * FROM `*PREFIX*myusers` WHERE id = ?'; + $args = array(1); + + $query = \OCP\DB::prepare($sql); + $result = $query->execute($args); + + while($row = $result->fetchRow()) { + $userName = $row['username']; + } + + } + /** * @brief Find all files and their encryption status within a directory * @param string $directory The path of the parent directory to search @@ -737,6 +730,7 @@ class Util { $fileOwner = \OC\Files\Filesystem::getOwner( $filePath ); + // Decrypt keyfile $plainKeyfile = $this->decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey ); // Re-enc keyfile to (additional) sharekeys From fd4e59b748d2d22e4aea4a7583139b5a4e4b65d7 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Wed, 20 Mar 2013 19:26:59 +0100 Subject: [PATCH 035/257] Added method for setting user keyfile recovery preference Fixed method for checking if keyfile recovery is enabled for a user Added unit test for above 2 methods Made proxy{} always use sharing Made proxy{} work regardless of sharing API enabled or not Implemented proxy-based sharing to admin if user keyfile recovery is enabled --- apps/files_encryption/hooks/hooks.php | 2 - apps/files_encryption/lib/keymanager.php | 1 + apps/files_encryption/lib/proxy.php | 58 ++++++++++++------ apps/files_encryption/lib/util.php | 78 +++++++++++++++++++++--- apps/files_encryption/test/util.php | 20 ++++++ 5 files changed, 127 insertions(+), 32 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 8db7539706..82e650c417 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -40,7 +40,6 @@ class Hooks { \OC\Files\Filesystem::init( $params['uid'] . '/' . 'files' . '/' ); $view = new \OC_FilesystemView( '/' ); - $util = new Util( $view, $params['uid'] ); // Check files_encryption infrastructure is ready for action @@ -61,7 +60,6 @@ class Hooks { $privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] ); $session = new Session(); - $session->setPrivateKey( $privateKey, $params['uid'] ); $view1 = new \OC_FilesystemView( '/' . $params['uid'] ); diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 0c2db2be32..6837dcf67b 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -57,6 +57,7 @@ class Keymanager { return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' ); \OC_FileProxy::$enabled = true; + } /** diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 2a738c80e3..f469422e22 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -131,32 +131,50 @@ class Proxy extends \OC_FileProxy { // Encrypt data $encData = Crypt::symmetricEncryptFileContent( $data, $plainKey ); - // Check if the keyfile needs to be shared - if ( $userIds = \OCP\Share::getUsersSharingFile( $filePath, true ) ) { - - $publicKeys = Keymanager::getPublicKeys( $rootView, $userIds ); - - \OC_FileProxy::$enabled = false; - - // Encrypt plain keyfile to multiple sharefiles - $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys ); - - // Save sharekeys to user folders - // TODO: openssl_seal generates new shareKeys (envelope keys) each time data is encrypted, but will data still be decryptable using old shareKeys? If so we don't need to replace the old shareKeys here, we only need to set the new ones - Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] ); - - // Set encrypted keyfile as common varname - $encKey = $multiEncrypted['encrypted']; + // Check if key recovery is enabled + $recoveryEnabled = $util->recoveryEnabled(); - } else { + // Make sure that a share key is generated for the owner too + $userIds = array( $userId ); - $publicKey = Keymanager::getPublicKey( $rootView, $userId ); + if ( \OCP\Share::isEnabled() ) { - // Encrypt plain data to a single user - $encKey = Crypt::keyEncrypt( $plainKey, $publicKey ); + // Find out who, if anyone, is sharing the file + $shareUids = \OCP\Share::getUsersSharingFile( $filePath, true ); + + $userIds = array_merge( $userIds, $shareUids ); } + // If recovery is enabled, add the + // Admin UID to list of users to share to + if ( $recoveryEnabled ) { + + // FIXME: Create a separate admin user purely for recovery, and create method in util for fetching this id from DB? + $adminUid = 'recoveryAdmin'; + + $userIds[] = $adminUid; + + } + + // Remove duplicate UIDs + $uniqueUserIds = array_unique ( $userIds ); + + // Fetch public keys for all users who will share the file + $publicKeys = Keymanager::getPublicKeys( $rootView, $uniqueUserIds ); + + \OC_FileProxy::$enabled = false; + + // Encrypt plain keyfile to multiple sharefiles + $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys ); + + // Save sharekeys to user folders + // TODO: openssl_seal generates new shareKeys (envelope keys) each time data is encrypted, but will data still be decryptable using old shareKeys? If so we don't need to replace the old shareKeys here, we only need to set the new ones + Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] ); + + // Set encrypted keyfile as common varname + $encKey = $multiEncrypted['data']; + // Save the key if its new if ( ! $keyPreExists ) { diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index a80da73a4b..b86e7f421b 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -31,7 +31,12 @@ # ---------------- # Re-use existing keyfiles so they don't need version control (part implemented, stream{} and util{} remain) # Make sure user knows if large files weren't encrypted -# Trashbin support + + +# Test +# ---- +# Test that writing files works when recovery is enabled, and sharing API is disabled +# Test trashbin support // Old Todo: @@ -202,20 +207,73 @@ class Util { } - public function recoveryEnabled( ) { + /** + * @brief Check whether pwd recovery is enabled for a given user + * @return bool + * @note If records are not being returned, check for a hidden space + * at the start of the uid in db + */ + public function recoveryEnabled() { - $sql = 'SELECT * FROM `*PREFIX*myusers` WHERE id = ?'; - $args = array(1); + $sql = 'SELECT + recovery + FROM + `*PREFIX*encryption` + WHERE + uid = ?'; + + $args = array( $this->userId ); - $query = \OCP\DB::prepare($sql); - $result = $query->execute($args); - - while($row = $result->fetchRow()) { - $userName = $row['username']; - } + $query = \OCP\DB::prepare( $sql ); + + $result = $query->execute( $args ); + + // Set default in case no records found + $recoveryEnabled = 0; + + while( $row = $result->fetchRow() ) { + + $recoveryEnabled = $row['recovery']; + + } + + return $recoveryEnabled; } + /** + * @brief Enable / disable pwd recovery for a given user + * @param bool $enabled Whether to enable or disable recovery + * @return bool + */ + public function setRecovery( $enabled ) { + + $sql = 'UPDATE + *PREFIX*encryption + SET + recovery = ? + WHERE + uid = ?'; + + // Ensure value is an integer + $enabled = intval( $enabled ); + + $args = array( $enabled, $this->userId ); + + $query = \OCP\DB::prepare( $sql ); + + if ( $query->execute( $args ) ) { + + return true; + + } else { + + return false; + + } + + } + /** * @brief Find all files and their encryption status within a directory * @param string $directory The path of the parent directory to search diff --git a/apps/files_encryption/test/util.php b/apps/files_encryption/test/util.php index 275e60f4bd..e2767a2ec3 100755 --- a/apps/files_encryption/test/util.php +++ b/apps/files_encryption/test/util.php @@ -164,6 +164,26 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase { # then false will be returned. Use strict ordering? } + + function testRecoveryEnabled() { + + $util = new Encryption\Util( $this->view, $this->userId ); + + // Record the value so we can return it to it's original state later + $enabled = $util->recoveryEnabled(); + + $this->assertTrue( $util->setRecovery( 1 ) ); + + $this->assertEquals( 1, $util->recoveryEnabled() ); + + $this->assertTrue( $util->setRecovery( 0 ) ); + + $this->assertEquals( 0, $util->recoveryEnabled() ); + + // Return the setting to it's previous state + $this->assertTrue( $util->setRecovery( $enabled ) ); + + } // /** // * @brief test decryption using legacy blowfish method From f10be4ea17b08059103627fb97716672bdff4fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 26 Mar 2013 11:58:54 +0100 Subject: [PATCH 036/257] new file structure for share keys; sub-folder need to be generated each by one (we don't have a recursive mkdir) --- apps/files_encryption/lib/keymanager.php | 41 ++++++++++++++++++------ 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 6837dcf67b..6ef256553d 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -28,6 +28,22 @@ namespace OCA\Encryption; * @note Where a method requires a view object, it's root must be '/' */ class Keymanager { + + /** + * @brief get uid of the owners of the file and the path to the file + * @param $filename + * @return array + */ + public static function getUidAndFilename($filename) { + $uid = \OC\Files\Filesystem::getOwner($filename); + \OC\Files\Filesystem::initMountPoints($uid); + if ( $uid != \OCP\User::getUser() ) { + $info = \OC\Files\Filesystem::getFileInfo($filename); + $ownerView = new \OC\Files\View('/'.$uid.'/files'); + $filename = $ownerView->getPath($info['fileid']); + } + return array($uid, $filename); + } /** * @brief retrieve the ENCRYPTED private key from a user @@ -264,15 +280,17 @@ class Keymanager { * asymmetrically encrypt the keyfile before passing it to this method */ public static function setShareKey( \OC_FilesystemView $view, $path, $userId, $shareKey ) { + + list($owner, $filename) = self::getUidAndFilename($path); + + $basePath = '/' . $owner . '/files_encryption/share-keys'; - $basePath = '/' . $userId . '/files_encryption/share-keys'; + $shareKeyPath = self::keySetPreparation( $view, $filename, $basePath, $owner ); - $shareKeyPath = self::keySetPreparation( $view, $path, $basePath, $userId ); - - $writePath = $basePath . '/' . $shareKeyPath . '.shareKey'; + $writePath = $basePath . '/' . $shareKeyPath . '.' . $userId . '.shareKey'; \OC_FileProxy::$enabled = false; - + $result = $view->file_put_contents( $writePath, $shareKey ); if ( @@ -295,7 +313,7 @@ class Keymanager { * @return bool */ public static function setShareKeys( \OC_FilesystemView $view, $path, array $shareKeys ) { - + // $shareKeys must be an array with the following format: // [userId] => [encrypted key] @@ -395,9 +413,14 @@ class Keymanager { isset( $path_parts['dirname'] ) && ! $view->file_exists( $basePath . '/' . $path_parts['dirname'] ) ) { - - $view->mkdir( $basePath . '/' . $path_parts['dirname'] ); - + $sub_dirs = explode(DIRECTORY_SEPARATOR, $basePath . '/' . $path_parts['dirname']); + $dir = ''; + foreach ($sub_dirs as $sub_dir) { + $dir .= '/' . $sub_dir; + if (!$view->is_dir($dir)) { + $view->mkdir($dir); + } + } } return $targetPath; From 5995b6996b113145da65fd0b44cdb498ae6e56a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 26 Mar 2013 12:23:28 +0100 Subject: [PATCH 037/257] always call stripUserFilesPath(), we need to keep the Shared/ to find the correct owner of the file later --- apps/files_encryption/lib/proxy.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index f469422e22..4dc2bfd749 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -202,22 +202,14 @@ class Proxy extends \OC_FileProxy { * @param string $data Data that has been read from file */ public function postFile_get_contents( $path, $data ) { - + // FIXME: $path for shared files is just /uid/files/Shared/filepath $userId = \OCP\USER::getUser(); $view = new \OC_FilesystemView( '/' ); $util = new Util( $view, $userId ); - if ( $util->isSharedPath( $path ) ) { - - $relPath = $util->stripSharedFilePath( $path ); - - } else { - - $relPath = $util->stripUserFilesPath( $path ); - - } + $relPath = $util->stripUserFilesPath( $path ); // TODO check for existing key file and reuse it if possible to avoid problems with versioning etc. From 890f0142a25c4f4a2e66738360e4c70d86147a9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 26 Mar 2013 12:24:04 +0100 Subject: [PATCH 038/257] get shared keys from new location --- apps/files_encryption/lib/keymanager.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 6ef256553d..19c9de3ece 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -36,6 +36,7 @@ class Keymanager { */ public static function getUidAndFilename($filename) { $uid = \OC\Files\Filesystem::getOwner($filename); + \OC\Files\Filesystem::initMountPoints($uid); if ( $uid != \OCP\User::getUser() ) { $info = \OC\Files\Filesystem::getFileInfo($filename); @@ -348,11 +349,9 @@ class Keymanager { public static function getShareKey( \OC_FilesystemView $view, $userId, $filePath ) { \OC_FileProxy::$enabled = false; - - $filePath_f = ltrim( $filePath, '/' ); - - $shareKeyPath = '/' . $userId . '/files_encryption/share-keys/' . $filePath_f . '.shareKey'; - + list($owner, $filename) = self::getUidAndFilename($filePath); + + $shareKeyPath = '/' . $owner . '/files_encryption/share-keys/' . $filename . '.' . $userId . '.shareKey'; if ( $view->file_exists( $shareKeyPath ) ) { $result = $view->file_get_contents( $shareKeyPath ); From a65d741a3fda0a35326e0dee7627a69c00e3d0f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 26 Mar 2013 12:39:55 +0100 Subject: [PATCH 039/257] move getUidAndFilename() tu util.php --- apps/files_encryption/lib/keymanager.php | 26 +++++++----------------- apps/files_encryption/lib/util.php | 17 ++++++++++++++++ 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 19c9de3ece..23c061b8e6 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -28,23 +28,6 @@ namespace OCA\Encryption; * @note Where a method requires a view object, it's root must be '/' */ class Keymanager { - - /** - * @brief get uid of the owners of the file and the path to the file - * @param $filename - * @return array - */ - public static function getUidAndFilename($filename) { - $uid = \OC\Files\Filesystem::getOwner($filename); - - \OC\Files\Filesystem::initMountPoints($uid); - if ( $uid != \OCP\User::getUser() ) { - $info = \OC\Files\Filesystem::getFileInfo($filename); - $ownerView = new \OC\Files\View('/'.$uid.'/files'); - $filename = $ownerView->getPath($info['fileid']); - } - return array($uid, $filename); - } /** * @brief retrieve the ENCRYPTED private key from a user @@ -282,7 +265,9 @@ class Keymanager { */ public static function setShareKey( \OC_FilesystemView $view, $path, $userId, $shareKey ) { - list($owner, $filename) = self::getUidAndFilename($path); + $util = new Util( $view, $userId ); + + list($owner, $filename) = $util->getUidAndFilename($path); $basePath = '/' . $owner . '/files_encryption/share-keys'; @@ -349,7 +334,10 @@ class Keymanager { public static function getShareKey( \OC_FilesystemView $view, $userId, $filePath ) { \OC_FileProxy::$enabled = false; - list($owner, $filename) = self::getUidAndFilename($filePath); + + $util = new Util( $view, $userId ); + + list($owner, $filename) = $util->getUidAndFilename($filePath); $shareKeyPath = '/' . $owner . '/files_encryption/share-keys/' . $filename . '.' . $userId . '.shareKey'; if ( $view->file_exists( $shareKeyPath ) ) { diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index b86e7f421b..5276dae99a 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -815,4 +815,21 @@ class Util { return true; } + /** + * @brief get uid of the owners of the file and the path to the file + * @param $filename + * @return array + */ + public function getUidAndFilename($filename) { + $uid = \OC\Files\Filesystem::getOwner($filename); + + \OC\Files\Filesystem::initMountPoints($uid); + if ( $uid != \OCP\User::getUser() ) { + $info = \OC\Files\Filesystem::getFileInfo($filename); + $ownerView = new \OC\Files\View('/'.$uid.'/files'); + $filename = $ownerView->getPath($info['fileid']); + } + return array($uid, $filename); + } + } From 5f233ee8140476d02e1c20325b83362c0d54d237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 26 Mar 2013 12:40:31 +0100 Subject: [PATCH 040/257] get the correct paths and owner to access shared files --- apps/files_encryption/lib/proxy.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 4dc2bfd749..7c981d4fc4 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -227,11 +227,10 @@ class Proxy extends \OC_FileProxy { $privateKey = $session->getPrivateKey( $userId ); // Get the file owner so we can retrieve its keyfile - $fileOwner = \OC\Files\Filesystem::getOwner( $relPath ); //NOTE: This might be false! make sure the path passed to it is right - $fileOwner = 'admin'; // FIXME: Manually set the correct UID for now - + list($fileOwner, $ownerPath) = $util->getUidAndFilename($relPath); + // Get the encrypted keyfile - $encKeyfile = Keymanager::getFileKey( $view, $fileOwner, $relPath ); + $encKeyfile = Keymanager::getFileKey( $view, $fileOwner, $ownerPath ); // Attempt to fetch the user's shareKey $shareKey = Keymanager::getShareKey( $view, $userId, $relPath ); From b1d620300e0671d5a7f24e994b62be310688d13b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 26 Mar 2013 14:22:18 +0100 Subject: [PATCH 041/257] delete share keys if file gets deleted --- apps/files_encryption/lib/keymanager.php | 27 +++++++++++++++--------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 23c061b8e6..9022ed2cac 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -362,16 +362,23 @@ class Keymanager { public static function delShareKey( \OC_FilesystemView $view, $userId, $filePath ) { \OC_FileProxy::$enabled = false; - - $trimmed = ltrim( $filePath, '/' ); - $shareKeyPath = '/' . $userId . '/files_encryption/share-keys/' . $trimmed . '.shareKey'; - - // Unlink doesn't tell us if file was deleted (not found returns - // true), so we perform our own test - if ( $view->file_exists( $shareKeyPath ) ) { - - $result = $view->unlink( $shareKeyPath ); - + + $util = new Util( $view, $userId ); + + list($owner, $filename) = $util->getUidAndFilename($filePath); + + $shareKeyPath = '/' . $owner . '/files_encryption/share-keys/' . $filename; + + $absPath = $view->getLocalFile($shareKeyPath); + + $matches = glob(preg_quote($absPath).'.*.shareKey' ); + + if ( $matches ) { + + foreach ( $matches as $ma ) { + unlink($ma); + } + } else { \OC_Log::write( 'Encryption library', 'Could not delete shareKey; does not exist: "' . $shareKeyPath, \OC_Log::ERROR ); From 6beeb2466f08dbed95f69761668efa6d27fc4d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 26 Mar 2013 16:17:26 +0100 Subject: [PATCH 042/257] also delete share keys if a different user than the owner deletes a shared file --- apps/files_encryption/lib/keymanager.php | 6 +----- apps/files_encryption/lib/proxy.php | 17 +++++++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 9022ed2cac..49c6ffa8a5 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -363,11 +363,7 @@ class Keymanager { \OC_FileProxy::$enabled = false; - $util = new Util( $view, $userId ); - - list($owner, $filename) = $util->getUidAndFilename($filePath); - - $shareKeyPath = '/' . $owner . '/files_encryption/share-keys/' . $filename; + $shareKeyPath = '/' . $userId . '/files_encryption/share-keys/' . $filePath; $absPath = $view->getLocalFile($shareKeyPath); diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 7c981d4fc4..7c23336b3d 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -291,17 +291,22 @@ class Proxy extends \OC_FileProxy { \OC_FileProxy::$enabled = false; $view = new \OC_FilesystemView( '/' ); - + $userId = \OCP\USER::getUser(); - + + $util = new Util( $view, $userId ); + // Format path to be relative to user files dir $trimmed = ltrim( $path, '/' ); $split = explode( '/', $trimmed ); $sliced = array_slice( $split, 2 ); $relPath = implode( '/', $sliced ); - $filePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/'. $relPath; + + list($owner, $ownerPath) = $util->getUidAndFilename($relPath); + + $filePath = $owner . '/' . 'files_encryption' . '/' . 'keyfiles' . '/'. $ownerPath; - if ( $view->is_dir( $path ) ) { + if ( $view->is_dir( $ownerPath ) ) { // Dirs must be handled separately as deleteFileKey // doesn't handle them @@ -312,8 +317,8 @@ class Proxy extends \OC_FileProxy { // Delete keyfile & shareKey so it isn't orphaned if ( ! ( - Keymanager::deleteFileKey( $view, $userId, $relPath ) - && Keymanager::delShareKey( $view, $userId, $relPath ) + Keymanager::deleteFileKey( $view, $owner, $ownerPath ) + && Keymanager::delShareKey( $view, $owner, $ownerPath ) ) ) { From 73157133e825ff3d66b83091e2b4ebeec0b83e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 26 Mar 2013 16:22:26 +0100 Subject: [PATCH 043/257] reuse function provided in util.php --- apps/files_encryption/lib/proxy.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 7c23336b3d..a904294659 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -297,10 +297,7 @@ class Proxy extends \OC_FileProxy { $util = new Util( $view, $userId ); // Format path to be relative to user files dir - $trimmed = ltrim( $path, '/' ); - $split = explode( '/', $trimmed ); - $sliced = array_slice( $split, 2 ); - $relPath = implode( '/', $sliced ); + $relPath = $util->stripUserFilesPath($path); list($owner, $ownerPath) = $util->getUidAndFilename($relPath); From e717f7150e703821fc98a30ff80b953b737785e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 26 Mar 2013 16:52:58 +0100 Subject: [PATCH 044/257] check for dir in deleteFileKey() and delShareKey(), to always handle all share keys and file keys on delete --- apps/files_encryption/lib/keymanager.php | 56 ++++++++++++++---------- apps/files_encryption/lib/proxy.php | 31 ++++--------- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 49c6ffa8a5..cac5ab262d 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -178,21 +178,27 @@ class Keymanager { public static function deleteFileKey( \OC_FilesystemView $view, $userId, $path ) { $trimmed = ltrim( $path, '/' ); - $keyPath = '/' . $userId . '/files_encryption/keyfiles/' . $trimmed . '.key'; - - // Unlink doesn't tell us if file was deleted (not found returns - // true), so we perform our own test - if ( $view->file_exists( $keyPath ) ) { - - return $view->unlink( $keyPath ); - - } else { + $keyPath = '/' . $userId . '/files_encryption/keyfiles/' . $trimmed; + + $result = false; + + if ( $view->is_dir($keyPath) ) { + + $result = $view->unlink($keyPath); + + } else if ( $view->file_exists( $keyPath.'.key' ) ) { + + $result = $view->unlink( $keyPath.'.key' ); + + } + + if ( !$result ) { \OC_Log::write( 'Encryption library', 'Could not delete keyfile; does not exist: "' . $keyPath, \OC_Log::ERROR ); - - return false; - + } + + return $result; } @@ -365,22 +371,28 @@ class Keymanager { $shareKeyPath = '/' . $userId . '/files_encryption/share-keys/' . $filePath; - $absPath = $view->getLocalFile($shareKeyPath); + $result = false; - $matches = glob(preg_quote($absPath).'.*.shareKey' ); + if ( $view->is_dir($shareKeyPath) ) { + $result = $view->unlink($shareKeyPath); + } else { + $absPath = $view->getLocalFile($shareKeyPath); - if ( $matches ) { + $matches = glob(preg_quote($absPath).'.*.shareKey' ); + + if ( $matches ) { + + foreach ( $matches as $ma ) { + unlink($ma); + } - foreach ( $matches as $ma ) { - unlink($ma); } - } else { - + $result = true; + } + + if ( !result ) { \OC_Log::write( 'Encryption library', 'Could not delete shareKey; does not exist: "' . $shareKeyPath, \OC_Log::ERROR ); - - $result = false; - } \OC_FileProxy::$enabled = false; diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index a904294659..a1eb76666d 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -302,30 +302,17 @@ class Proxy extends \OC_FileProxy { list($owner, $ownerPath) = $util->getUidAndFilename($relPath); $filePath = $owner . '/' . 'files_encryption' . '/' . 'keyfiles' . '/'. $ownerPath; + + // Delete keyfile & shareKey so it isn't orphaned + if ( + ! ( + Keymanager::deleteFileKey( $view, $owner, $ownerPath ) + && Keymanager::delShareKey( $view, $owner, $ownerPath ) + ) + ) { - if ( $view->is_dir( $ownerPath ) ) { - - // Dirs must be handled separately as deleteFileKey - // doesn't handle them - $view->unlink( $filePath ); - - } else { - - // Delete keyfile & shareKey so it isn't orphaned - if ( - ! ( - Keymanager::deleteFileKey( $view, $owner, $ownerPath ) - && Keymanager::delShareKey( $view, $owner, $ownerPath ) - ) - ) { - - \OC_Log::write( 'Encryption library', 'Keyfile or shareKey could not be deleted for file "'.$filePath.'"', \OC_Log::ERROR ); + \OC_Log::write( 'Encryption library', 'Keyfile or shareKey could not be deleted for file "'.$filePath.'"', \OC_Log::ERROR ); - - } - - - } \OC_FileProxy::$enabled = true; From 9ecfd07f23e7fe2924bee6103792c00c6ec3cb0a Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Thu, 28 Mar 2013 18:29:18 +0100 Subject: [PATCH 045/257] Added ajax scripts for setting pwd recovery preferences --- apps/files_encryption/ajax/adminrecovery.php | 72 ++++++++++++++++++++ apps/files_encryption/ajax/userrecovery.php | 42 ++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 apps/files_encryption/ajax/adminrecovery.php create mode 100644 apps/files_encryption/ajax/userrecovery.php diff --git a/apps/files_encryption/ajax/adminrecovery.php b/apps/files_encryption/ajax/adminrecovery.php new file mode 100644 index 0000000000..f22114f851 --- /dev/null +++ b/apps/files_encryption/ajax/adminrecovery.php @@ -0,0 +1,72 @@ +setValue( $app, $key, $value ) + + + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + * + * @brief Script to handle admin settings for encrypted key recovery + */ + +use OCA\Encryption; + +\OCP\JSON::checkAdminUser(); +\OCP\JSON::checkAppEnabled( 'files_encryption' ); +\OCP\JSON::callCheck(); + +if ( + isset( $_POST['adminEnableRecovery'] ) + && $_POST['adminEnableRecovery'] == 1 + && isset( $_POST['recoveryPassword'] ) + && ! empty ( $_POST['recoveryPassword'] ) +) { + + // TODO: Let the admin set this themselves + $recoveryAdminUid = 'recoveryAdmin'; + + // If desired recoveryAdmin UID is already in use + if ( ! \OC_User::userExists( $recoveryAdminUid ) ) { + + // Create new recoveryAdmin user + \OC_User::createUser( $recoveryAdminUid, $_POST['recoveryPassword'] ); + + $doSetup = true; + + } else { + + // Get list of admin users + $admins = OC_Group::usersInGroup( 'admin' ); + + // If the existing recoveryAdmin UID is an admin + if ( in_array( $recoveryAdminUid, $admins ) ) { + + // The desired recoveryAdmi UID pre-exists and can be used + $doSetup = true; + + // If the recoveryAdmin UID exists but doesn't have admin rights + } else { + + \OCP\JSON::error(); + + } + + } + + // If recoveryAdmin has passed other checks + if ( $doSetup ) { + + $view = new \OC_FilesystemView( '/' ); + $util = new Util( $view, $recoveryAdminUid ); + + // Ensure recoveryAdmin is ready for encryption (has usable keypair etc.) + $util->setupServerSide( $_POST['recoveryPassword'] ); + + // Store the UID in the DB + OC_Appconfig::setValue( 'encryption', 'recoveryAdminUid', $recoveryAdminUid ); + + \OCP\JSON::success(); + + } + +} \ No newline at end of file diff --git a/apps/files_encryption/ajax/userrecovery.php b/apps/files_encryption/ajax/userrecovery.php new file mode 100644 index 0000000000..56c18f7ad5 --- /dev/null +++ b/apps/files_encryption/ajax/userrecovery.php @@ -0,0 +1,42 @@ +setValue( $app, $key, $value ) + + + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + * + * @brief Script to handle admin settings for encrypted key recovery + */ + +use OCA\Encryption; + +\OCP\JSON::checkLoggedIn(); +\OCP\JSON::checkAppEnabled( 'files_encryption' ); +\OCP\JSON::callCheck(); + +if ( + isset( $_POST['userEnableRecovery'] ) +) { + + // Ensure preference is an integer + $recoveryEnabled = intval( $_POST['userEnableRecovery'] ); + + $userId = \OCP\USER::getUser(); + $view = new \OC_FilesystemView( '/' ); + $util = new Util( $view, $userId ); + + // Save recovery preference to DB + $result = $util->setRecovery( $recoveryEnabled ); + + if ( $result ) { + + \OCP\JSON::success(); + + } else { + + \OCP\JSON::error(); + + } + +} \ No newline at end of file From 14451bdaf07f88c6ac46092c74b987a360b04547 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Fri, 29 Mar 2013 21:11:29 +0100 Subject: [PATCH 046/257] Development snapshot; Fixed errors from Hooks::login(); Work on enable/disable recoveryAdmin for lost passwords in settings page (template, ajax, js); Work on fixing sharing files to users (still broken); --- apps/files_encryption/appinfo/spec.txt | 12 +++++ apps/files_encryption/hooks/hooks.php | 5 +- apps/files_encryption/js/settings.js | 14 +++++ apps/files_encryption/lib/keymanager.php | 4 +- apps/files_encryption/lib/proxy.php | 2 +- apps/files_encryption/lib/stream.php | 2 +- apps/files_encryption/lib/util.php | 56 ++++++++++++++++---- apps/files_encryption/settings.php | 6 +++ apps/files_encryption/templates/settings.php | 19 +++++++ 9 files changed, 106 insertions(+), 14 deletions(-) diff --git a/apps/files_encryption/appinfo/spec.txt b/apps/files_encryption/appinfo/spec.txt index 7a937a9143..bb15864cbb 100644 --- a/apps/files_encryption/appinfo/spec.txt +++ b/apps/files_encryption/appinfo/spec.txt @@ -35,6 +35,18 @@ that file must have their sharekeys changed also. The keyfile and catfile however need only changing in the owners files, as there is only one copy of these. +Publicly shared files (public links) +------------------------------------ + +Files shared via public links use a separate system user account called 'ownCloud'. All public files are shared to that user's public key, and the private key is used to access the files when the public link is used in browser. + +This means that files shared via public links are accessible only to users who know the shared URL, or to admins who know the 'ownCloud' user password. + +Lost password recovery +---------------------- + +In order to enable users to read their encrypted files in the event of a password loss/reset scenario, administrators can choose to enable a 'recoveryAdmin' account. This is a user that all user files will automatically be shared to of the option is enabled. This allows the recoveryAdmin user to generate new keyfiles for the user. By default the UID of the recoveryAdmin is 'recoveryAdmin'. + Notes ----- diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 302671889d..43d3dfb5a6 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -40,7 +40,7 @@ class Hooks { // Manually initialise Filesystem{} singleton with correct // fake root path, in order to avoid fatal webdav errors - \OC\Files\Filesystem::init( $params['uid'] . '/' . 'files' . '/' ); + \OC\Files\Filesystem::init( $params['uid'], '/' . 'files' . '/' ); $view = new \OC_FilesystemView( '/' ); @@ -194,7 +194,8 @@ class Hooks { $util = new Util( $view, $userId ); $path = $util->fileIdToPath( $params['itemSource'] ); - $usersSharing = \OCP\Share::getUsersSharingFile( $path, true ); + // Note: this currently doesn't include the owner due to \OC\Files\Filesystem::getOwner() + $usersSharing = $util->getUsersSharingFile( $path ); // Recursively expand path to include subfiles $allPaths = $util->getPaths( $path ); diff --git a/apps/files_encryption/js/settings.js b/apps/files_encryption/js/settings.js index 0be857bb73..4f367f880d 100644 --- a/apps/files_encryption/js/settings.js +++ b/apps/files_encryption/js/settings.js @@ -6,12 +6,26 @@ $(document).ready(function(){ + // Trigger ajax on filetype blacklist change $('#encryption_blacklist').multiSelect({ oncheck:blackListChange, onuncheck:blackListChange, createText:'...' }); + // Trigger ajax on recoveryAdmin status change + $( 'input:radio[name="adminEnableRecovery"]' ).change( + function() { + $.post( + '../ajax/adminrecovery.php' + , $( this ).val() + , function( data ) { + // TODO: provide user with feedback of outcome + } + ); + } + ); + function blackListChange(){ var blackList=$('#encryption_blacklist').val().join(','); OC.AppConfig.setValue('files_encryption','type_blacklist',blackList); diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 99516949af..9bb062d0fd 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -391,8 +391,10 @@ class Keymanager { $result = true; } - if ( !result ) { + if ( ! $result ) { + \OC_Log::write( 'Encryption library', 'Could not delete shareKey; does not exist: "' . $shareKeyPath, \OC_Log::ERROR ); + } \OC_FileProxy::$enabled = false; diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index a1eb76666d..d5aa0f74f1 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -140,7 +140,7 @@ class Proxy extends \OC_FileProxy { if ( \OCP\Share::isEnabled() ) { // Find out who, if anyone, is sharing the file - $shareUids = \OCP\Share::getUsersSharingFile( $filePath, true ); + $shareUids = \OCP\Share::getUsersSharingFile( $filePath, true, true, true ); $userIds = array_merge( $userIds, $shareUids ); diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 86439b4864..9d01c2ca6c 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -127,7 +127,7 @@ class Stream { if ( ! is_resource( $this->handle ) ) { - \OCP\Util::writeLog( 'files_encryption', 'failed to open file "'.$this->rootView . '"', \OCP\Util::ERROR ); + \OCP\Util::writeLog( 'files_encryption', 'failed to open file "' . $this->relPath . '"', \OCP\Util::ERROR ); } else { diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 5276dae99a..f6386ad84d 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -638,7 +638,7 @@ class Util { /** * @brief Filter an array of UIDs to return only ones ready for sharing * @param array $unfilteredUsers users to be checked for sharing readiness - * @return array $userIds filtered users + * @return multi-dimensional array. keys: ready, unready */ public function filterShareReadyUsers( $unfilteredUsers ) { @@ -649,6 +649,8 @@ class Util { foreach ( $unfilteredUsers as $user ) { $util = new Util( $this->view, $user ); + + $readyIds = $unreadyIds = array(); // Check that the user is encryption capable, or is the // public system user 'ownCloud' (for public shares) @@ -657,22 +659,26 @@ class Util { or $user == 'ownCloud' ) { - // Construct array of just UIDs for Keymanager{} - $userIds[] = $user; + // Construct array of ready UIDs for Keymanager{} + $readyIds[] = $user; } else { - + + // Construct array of unready UIDs for Keymanager{} + $unreadyIds[] = $user; + // Log warning; we can't do necessary setup here // because we don't have the user passphrase - // TODO: Provide user feedback indicating that - // sharing failed \OC_Log::write( 'Encryption library', '"'.$user.'" is not setup for encryption', \OC_Log::WARN ); } } - return $userIds; + return array ( + 'ready' => $userIds + , 'unready' => $unreadyIds + ); } @@ -778,8 +784,18 @@ class Util { // Make sure users are capable of sharing $filteredUids = $this->filterShareReadyUsers( $users ); +// trigger_error( print_r($filteredUids, 1) ); + + if ( ! empty( $filteredUids['unready'] ) ) { + + // Notify user of unready userDir + // TODO: Move this out of here; it belongs somewhere else + \OCP\JSON::error(); + + } + // Get public keys for each user, ready for generating sharekeys - $userPubKeys = Keymanager::getPublicKeys( $this->view, $filteredUids ); // TODO: check this includes the owner's public key + $userPubKeys = Keymanager::getPublicKeys( $this->view, $filteredUids['ready'] ); // TODO: check this includes the owner's public key \OC_FileProxy::$enabled = false; @@ -814,8 +830,30 @@ class Util { return true; } + + /** + * @brief Returns the users who are sharing a file, including the file owner + * @param $path Relative path of the file, like files/file.txt + * @return $users array of UIDs + * @note This wraps the OCP\Share method, but includes the owner even if + * the file isn't registered in sharing API + */ + public function getUsersSharingFile( $path ) { + + $users = \OCP\Share::getUsersSharingFile( $path, true, true ); + + // FIXME: this is returning empty :/ + $owner = \OC\Files\Filesystem::getOwner( $path ); + +// trigger_error( var_export( $owner, 1)); + + $users[] = $owner; + + return array_unique( $users ); + + } - /** + /** * @brief get uid of the owners of the file and the path to the file * @param $filename * @return array diff --git a/apps/files_encryption/settings.php b/apps/files_encryption/settings.php index 85c616bca7..71d47f061a 100644 --- a/apps/files_encryption/settings.php +++ b/apps/files_encryption/settings.php @@ -12,8 +12,14 @@ $tmpl = new OCP\Template( 'files_encryption', 'settings' ); $blackList = explode( ',', \OCP\Config::getAppValue( 'files_encryption', 'type_blacklist', '' ) ); +// Check if an adminRecovery account is enabled for recovering files after lost pwd +$view = new OC_FilesystemView( '' ); +$util = new \OCA\Encryption\Util( $view, \OCP\USER::getUser() ); +$recoveryEnabled = $util->recoveryEnabled(); + $tmpl->assign( 'blacklist', $blackList ); $tmpl->assign( 'encryption_mode', \OC_Appconfig::getValue( 'files_encryption', 'mode', 'none' ) ); +$tmpl->assign( 'recoveryEnabled', $recoveryEnabled ); \OCP\Util::addscript( 'files_encryption', 'settings' ); \OCP\Util::addscript( 'core', 'multiselect' ); diff --git a/apps/files_encryption/templates/settings.php b/apps/files_encryption/templates/settings.php index b873d7f5aa..6499d0c8e8 100644 --- a/apps/files_encryption/templates/settings.php +++ b/apps/files_encryption/templates/settings.php @@ -3,6 +3,7 @@

t( 'Encryption' )); ?> +
t( "Exclude the following file types from encryption:" )); ?>
@@ -16,5 +17,23 @@

+

+ t( "Enable encryption passwords recovery account (allow sharing to recovery account):" )); ?> +
+ /> + t( "Enabled" )); ?> +
+ + /> + t( "Disabled" )); ?> +

From 400cf5beb30de7475520192e840ddb899d0f742e Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 9 Apr 2013 19:11:38 +0200 Subject: [PATCH 047/257] Fixed naming bug of public owncloud key dir, which caused new keypair to be generated on each pageload --- apps/files_encryption/lib/session.php | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index 171a6900f0..7bfea7bed4 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -27,32 +27,44 @@ namespace OCA\Encryption; */ class Session { + + private $view; /** * @brief if session is started, check if ownCloud key pair is set up, if not create it * * The ownCloud key pair is used to allow public link sharing even if encryption is enabled */ - public function __construct() { + public function __construct( \OC_FilesystemView $view ) { - $view = new \OC\Files\View('/'); - if (!$view->is_dir('owncloud_private_key')) { - $view->mkdir('owncloud_private_key'); + $this->view = $view; + + if ( ! $this->view->is_dir( 'owncloud_private_key' ) ) { + + $this->view->mkdir('owncloud_private_key'); } - if (!$view->file_exists("/public-keys/owncloud.public.key") || !$view->file_exists("/owncloud_private_key/owncloud.private.key") ) { + + if ( + ! $this->view->file_exists("/public-keys/owncloud.public.key") + || ! $this->view->file_exists("/owncloud_private_key/owncloud.private.key" ) + ) { $keypair = Crypt::createKeypair(); \OC_FileProxy::$enabled = false; + // Save public key - $view->file_put_contents( '/public-keys/ownCloud.public.key', $keypair['publicKey'] ); + $this->view->file_put_contents( '/public-keys/owncloud.public.key', $keypair['publicKey'] ); + // Encrypt private key empthy passphrase $encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $keypair['privateKey'], '' ); + // Save private key - $view->file_put_contents( '/owncloud_private_key/ownCloud.private.key', $encryptedPrivateKey ); + $this->view->file_put_contents( '/owncloud_private_key/owncloud.private.key', $encryptedPrivateKey ); \OC_FileProxy::$enabled = true; + } } From 109fe198c3b8ffd5a4f7f4a4aba6639480895644 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 9 Apr 2013 19:19:27 +0200 Subject: [PATCH 048/257] Added info about filesystem method access conventions --- apps/files_encryption/appinfo/spec.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/apps/files_encryption/appinfo/spec.txt b/apps/files_encryption/appinfo/spec.txt index bb15864cbb..a1846ca47f 100644 --- a/apps/files_encryption/appinfo/spec.txt +++ b/apps/files_encryption/appinfo/spec.txt @@ -47,6 +47,20 @@ Lost password recovery In order to enable users to read their encrypted files in the event of a password loss/reset scenario, administrators can choose to enable a 'recoveryAdmin' account. This is a user that all user files will automatically be shared to of the option is enabled. This allows the recoveryAdmin user to generate new keyfiles for the user. By default the UID of the recoveryAdmin is 'recoveryAdmin'. +OC_FilesystemView +----------------- + +files_encryption deals extensively with paths and the filesystem. In order to minimise bugs, it makes calls to filesystem methods in a consistent way: OC_FilesystemView{} objects always use '/' as their root, and specify paths each time particular methods are called. e.g. do this: + +$view->file_exists( 'path/to/file' ); + +Not: + +$view->chroot( 'path/to' ); +$view->file_exists( 'file' ); + +Using this convention means that $view objects are more predictable and less likely to break. Problems with paths are the #1 cause of bugs in this app, and consistent $view handling is an important way to prevent them. + Notes ----- From 98de385b8adf748bc1f7d9b527b253624575e370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 10 Apr 2013 15:08:28 +0200 Subject: [PATCH 049/257] add $view as parameter for session constructor --- apps/files_encryption/appinfo/app.php | 4 ++-- apps/files_encryption/hooks/hooks.php | 10 +++++----- apps/files_encryption/lib/proxy.php | 4 ++-- apps/files_encryption/lib/stream.php | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index b095f79c0c..47f4120fb3 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -24,8 +24,8 @@ OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', ' OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfileFromClient' ); stream_wrapper_register( 'crypt', 'OCA\Encryption\Stream' ); - -$session = new OCA\Encryption\Session(); +$view = new OC\Files\View('/'); +$session = new OCA\Encryption\Session($view); if ( ! $session->getPrivateKey( \OCP\USER::getUser() ) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 43d3dfb5a6..82de80a1cf 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -63,7 +63,7 @@ class Hooks { $privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] ); - $session = new Session(); + $session = new Session($view); $session->setPrivateKey( $privateKey, $params['uid'] ); @@ -116,8 +116,8 @@ class Hooks { // is in use (client-side encryption does not have access to // the necessary keys) if ( Crypt::mode() == 'server' ) { - - $session = new Session(); + $view = new \OC_FilesystemView( '/' ); + $session = new Session($view); // Get existing decrypted private key $privateKey = $session->getPrivateKey(); @@ -189,7 +189,7 @@ class Hooks { if ( $params['itemType'] === 'file' ) { $view = new \OC_FilesystemView( '/' ); - $session = new Session(); + $session = new Session($view); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); $path = $util->fileIdToPath( $params['itemSource'] ); @@ -244,7 +244,7 @@ class Hooks { if ( $params['itemType'] === 'file' ) { $view = new \OC_FilesystemView( '/' ); - $session = new Session(); + $session = new Session($view); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); $path = $util->fileIdToPath( $params['itemSource'] ); diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index d5aa0f74f1..7e18ec9b10 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -101,7 +101,7 @@ class Proxy extends \OC_FileProxy { $userId = \OCP\USER::getUser(); $rootView = new \OC_FilesystemView( '/' ); $util = new Util( $rootView, $userId ); - $session = new Session(); + $session = new Session($rootView); $fileOwner = \OC\Files\Filesystem::getOwner( $path ); $privateKey = $session->getPrivateKey(); $filePath = $util->stripUserFilesPath( $path ); @@ -223,7 +223,7 @@ class Proxy extends \OC_FileProxy { ) { // TODO use get owner to find correct location of key files for shared files - $session = new Session(); + $session = new Session($view); $privateKey = $session->getPrivateKey( $userId ); // Get the file owner so we can retrieve its keyfile diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 9d01c2ca6c..8bacb98126 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -236,7 +236,7 @@ class Stream { $this->getUser(); - $session = new Session(); + $session = new Session($this->rootView); $privateKey = $session->getPrivateKey( $this->userId ); From fff979a5907cd3d3ff018e541c50c6bd8c095c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 10 Apr 2013 15:14:44 +0200 Subject: [PATCH 050/257] add $view as parameter for getFileKey() call --- apps/files_encryption/lib/util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index f6386ad84d..815f2594ce 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -518,7 +518,7 @@ class Util { $size = stream_copy_to_stream( $plainHandle, $encHandle ); // Fetch the key that has just been set/updated by the stream - $encKey = Keymanager::getFileKey( $relPath ); + $encKey = Keymanager::getFileKey( $this->view, $this->userId, $relPath ); // Save keyfile Keymanager::setFileKey( $this->view, $relPath, $this->userId, $encKey ); From 4303d6318ebf04929a74e1b08e3fad82e1be3a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 10 Apr 2013 15:31:19 +0200 Subject: [PATCH 051/257] Session expect OC_FilesystemView() --- apps/files_encryption/appinfo/app.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 47f4120fb3..9747fb20ad 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -24,7 +24,7 @@ OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', ' OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfileFromClient' ); stream_wrapper_register( 'crypt', 'OCA\Encryption\Stream' ); -$view = new OC\Files\View('/'); +$view = new OC_FilesystemView('/'); $session = new OCA\Encryption\Session($view); if ( From c3a284569b5a6f83104cf3b5f0a52b2ecfffd8c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 10 Apr 2013 16:46:02 +0200 Subject: [PATCH 052/257] make sure that public-keys dir exists --- apps/files_encryption/lib/session.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index 7bfea7bed4..0c6a7131fd 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -38,7 +38,8 @@ class Session { public function __construct( \OC_FilesystemView $view ) { $this->view = $view; - + + if ( ! $this->view->is_dir( 'owncloud_private_key' ) ) { $this->view->mkdir('owncloud_private_key'); @@ -55,6 +56,11 @@ class Session { \OC_FileProxy::$enabled = false; // Save public key + + if (!$view->is_dir('/public-keys')) { + $view->mkdir('/public-keys'); + } + $this->view->file_put_contents( '/public-keys/owncloud.public.key', $keypair['publicKey'] ); // Encrypt private key empthy passphrase From 8f0bbdc5cbd17d8fdaa773a5a3558b7af7f0a734 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 11 Apr 2013 22:55:48 +0200 Subject: [PATCH 053/257] fix performance issues --- apps/files_encryption/lib/stream.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 8bacb98126..dcc12c9f9e 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -224,6 +224,11 @@ class Stream { */ public function getKey() { + // fix performance issues + if(isset($this->keyfile) && isset($this->encKeyfile)) { + return true; + } + // If a keyfile already exists for a file named identically to // file to be written if ( $this->rootView->file_exists( $this->userId . '/'. 'files_encryption' . '/' . 'keyfiles' . '/' . $this->rawPath . '.key' ) ) { From f87229ddafff57980bfc93f52d6aff3427e9a0e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 12 Apr 2013 14:13:38 +0200 Subject: [PATCH 054/257] fix stream wrapper to make initial encryption work --- apps/files_encryption/lib/keymanager.php | 18 ++++++++++-------- apps/files_encryption/lib/stream.php | 19 ++++++++++--------- apps/files_encryption/lib/util.php | 11 +++++++---- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 9bb062d0fd..3e26e6bb69 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -113,17 +113,19 @@ class Keymanager { $targetPath = self::keySetPreparation( $view, $path, $basePath, $userId ); - if ( $view->is_dir( $basePath . '/' . $targetPath ) ) { - - // FIXME: write me - - } else { + if ( !$view->is_dir( $basePath . '/' . $targetPath ) ) { - // Save the keyfile in parallel directory - $result = $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile ); - + // create all parent folders + $info=pathinfo($basePath . '/' . $targetPath); + $keyfileFolderName=$view->getLocalFolder($info['dirname']); + if(!file_exists($keyfileFolderName)) { + mkdir($keyfileFolderName, 0750, true); + } } + $result = $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile ); + + \OC_FileProxy::$enabled = true; return $result; diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 8bacb98126..3bad43de2e 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -52,7 +52,7 @@ class Stream { // TODO: make all below properties private again once unit testing is // configured correctly public $rawPath; // The raw path received by stream_open - public $path_f; // The raw path formatted to include username and data dir + public $relPath; // rel path to users file dir private $userId; private $handle; // Resource returned by fopen private $path; @@ -80,8 +80,9 @@ class Stream { // Strip identifier text from path $this->rawPath = str_replace( 'crypt://', '', $path ); - // Set file path relative to user files dir - $this->relPath = $this->userId . '/files/' . $this->rawPath; + // Set file path relative to user files dir (7 = string length of '/files/') + $this->relPath = substr($this->rawPath, strlen($this->userId)+7); + //$this->relPath = $this->userId . '/files/' . $this->rawPath; if ( dirname( $this->rawPath ) == 'streams' @@ -110,7 +111,7 @@ class Stream { } else { - $this->size = $this->rootView->filesize( $this->relPath, $mode ); + $this->size = $this->rootView->filesize( $this->rawPath, $mode ); //$this->size = filesize( $this->rawPath ); @@ -121,13 +122,13 @@ class Stream { //$this->handle = fopen( $this->rawPath, $mode ); - $this->handle = $this->rootView->fopen( $this->relPath, $mode ); + $this->handle = $this->rootView->fopen( $this->rawPath, $mode ); \OC_FileProxy::$enabled = true; if ( ! is_resource( $this->handle ) ) { - \OCP\Util::writeLog( 'files_encryption', 'failed to open file "' . $this->relPath . '"', \OCP\Util::ERROR ); + \OCP\Util::writeLog( 'files_encryption', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR ); } else { @@ -226,13 +227,13 @@ class Stream { // If a keyfile already exists for a file named identically to // file to be written - if ( $this->rootView->file_exists( $this->userId . '/'. 'files_encryption' . '/' . 'keyfiles' . '/' . $this->rawPath . '.key' ) ) { + if ( $this->rootView->file_exists( $this->userId . '/'. 'files_encryption' . '/' . 'keyfiles' . '/' . $this->relPath . '.key' ) ) { // TODO: add error handling for when file exists but no // keyfile // Fetch existing keyfile - $this->encKeyfile = Keymanager::getFileKey( $this->rootView, $this->userId, $this->rawPath ); + $this->encKeyfile = Keymanager::getFileKey( $this->rootView, $this->userId, $this->relPath ); $this->getUser(); @@ -317,7 +318,7 @@ class Stream { $userId = \OCP\User::getUser(); // Save the new encrypted file key - Keymanager::setFileKey( $view, $this->rawPath, $userId, $this->encKeyfile ); + Keymanager::setFileKey( $view, $this->relPath, $userId, $this->encKeyfile ); } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 815f2594ce..4605c0f597 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -511,17 +511,20 @@ class Util { // Open handle with for binary reading $plainHandle = $this->view->fopen( $plainFile['path'], 'rb' ); // Open handle with for binary writing - $encHandle = fopen( 'crypt://' . 'var/www/oc6/data/' . $plainFile['path'] . '.tmp', 'ab' ); + + $encHandle = fopen( 'crypt://' . $plainFile['path'] . '.tmp', 'wb' ); // Overwrite the existing file with the encrypted one //$this->view->file_put_contents( $plainFile['path'], $encrypted['data'] ); $size = stream_copy_to_stream( $plainHandle, $encHandle ); - + + $this->view->rename($plainFile['path'] . '.tmp', $plainFile['path']); + // Fetch the key that has just been set/updated by the stream - $encKey = Keymanager::getFileKey( $this->view, $this->userId, $relPath ); + //$encKey = Keymanager::getFileKey( $this->view, $this->userId, $relPath ); // Save keyfile - Keymanager::setFileKey( $this->view, $relPath, $this->userId, $encKey ); + //Keymanager::setFileKey( $this->view, $relPath, $this->userId, $encKey ); // Add the file to the cache \OC\Files\Filesystem::putFileInfo( $plainFile['path'], array( 'encrypted'=>true, 'size' => $size ), '' ); From 02d1f86a535410e26d20d860f800ff069a6aa25c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 12 Apr 2013 14:30:02 +0200 Subject: [PATCH 055/257] fix some confusion about paths relative to the files dir and to the data dir --- apps/files_encryption/lib/stream.php | 11 +++++------ apps/files_encryption/lib/util.php | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 3bad43de2e..d269a56240 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -51,7 +51,7 @@ class Stream { // TODO: make all below properties private again once unit testing is // configured correctly - public $rawPath; // The raw path received by stream_open + public $rawPath; // The raw path relative to the data dir public $relPath; // rel path to users file dir private $userId; private $handle; // Resource returned by fopen @@ -77,12 +77,11 @@ class Stream { } - // Strip identifier text from path - $this->rawPath = str_replace( 'crypt://', '', $path ); + // Strip identifier text from path, this gives us the path relative to data//files + $this->relPath = str_replace( 'crypt://', '', $path ); - // Set file path relative to user files dir (7 = string length of '/files/') - $this->relPath = substr($this->rawPath, strlen($this->userId)+7); - //$this->relPath = $this->userId . '/files/' . $this->rawPath; + // rawPath is relative to the data directory + $this->rawPath = $this->userId . '/files/' . $this->relPath; if ( dirname( $this->rawPath ) == 'streams' diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 4605c0f597..6e0aeb96e9 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -344,7 +344,7 @@ class Util { // If the file is not encrypted } else { - $found['plain'][] = array( 'name' => $file, 'path' => $filePath ); + $found['plain'][] = array( 'name' => $file, 'path' => $relPath ); } From 854b9207878d9c5cd8f0d972f4b16b618beade3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 12 Apr 2013 15:18:19 +0200 Subject: [PATCH 056/257] fix some more paths --- apps/files_encryption/lib/util.php | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 6e0aeb96e9..420e3398a8 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -505,20 +505,22 @@ class Util { // Read plain file in chunks - - $relPath = $this->stripUserFilesPath( $plainFile['path'] ); - + //relative to data//file + $relPath = $plainFile['path']; + //relative to /data + $rawPath = $this->userId . '/files/' . $plainFile['path']; + // Open handle with for binary reading - $plainHandle = $this->view->fopen( $plainFile['path'], 'rb' ); + $plainHandle = $this->view->fopen( $rawPath, 'rb' ); // Open handle with for binary writing - $encHandle = fopen( 'crypt://' . $plainFile['path'] . '.tmp', 'wb' ); + $encHandle = fopen( 'crypt://' . $relPath . '.tmp', 'wb' ); // Overwrite the existing file with the encrypted one //$this->view->file_put_contents( $plainFile['path'], $encrypted['data'] ); $size = stream_copy_to_stream( $plainHandle, $encHandle ); - $this->view->rename($plainFile['path'] . '.tmp', $plainFile['path']); + $this->view->rename($rawPath . '.tmp', $rawPath); // Fetch the key that has just been set/updated by the stream //$encKey = Keymanager::getFileKey( $this->view, $this->userId, $relPath ); @@ -545,18 +547,19 @@ class Util { // Recrypt data, generate catfile $recrypted = Crypt::legacyKeyRecryptKeyfile( $legacyData, $legacyPassphrase, $publicKey, $newPassphrase ); - $relPath = $this->stripUserFilesPath( $legacyFile['path'] ); + $relPath = $legacyFile['path']; + $rawPath = $this->userId . '/files/' . $plainFile['path']; // Save keyfile Keymanager::setFileKey( $this->view, $relPath, $this->userId, $recrypted['key'] ); // Overwrite the existing file with the encrypted one - $this->view->file_put_contents( $legacyFile['path'], $recrypted['data'] ); + $this->view->file_put_contents( $rawPath, $recrypted['data'] ); $size = strlen( $recrypted['data'] ); // Add the file to the cache - \OC\Files\Filesystem::putFileInfo( $legacyFile['path'], array( 'encrypted'=>true, 'size' => $size ), '' ); + \OC\Files\Filesystem::putFileInfo( $rawPath, array( 'encrypted'=>true, 'size' => $size ), '' ); } From f378a7f572e1da4b24280c1fcbf830e026186c83 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Wed, 10 Apr 2013 17:37:03 +0200 Subject: [PATCH 057/257] Fixed proxy class handing of read / write files Various work on other classes --- apps/files_encryption/ajax/adminrecovery.php | 12 ++-- apps/files_encryption/appinfo/app.php | 6 +- apps/files_encryption/hooks/hooks.php | 10 +-- apps/files_encryption/js/settings.js | 9 ++- apps/files_encryption/lib/proxy.php | 49 ++++++-------- apps/files_encryption/lib/stream.php | 2 +- apps/files_encryption/lib/util.php | 70 ++++++++++++++++---- apps/files_encryption/test/proxy.php | 2 +- apps/files_encryption/test/util.php | 12 ++++ 9 files changed, 114 insertions(+), 58 deletions(-) diff --git a/apps/files_encryption/ajax/adminrecovery.php b/apps/files_encryption/ajax/adminrecovery.php index f22114f851..cec0cd4ddd 100644 --- a/apps/files_encryption/ajax/adminrecovery.php +++ b/apps/files_encryption/ajax/adminrecovery.php @@ -15,6 +15,8 @@ use OCA\Encryption; \OCP\JSON::checkAppEnabled( 'files_encryption' ); \OCP\JSON::callCheck(); +$return = $doSetup = false; + if ( isset( $_POST['adminEnableRecovery'] ) && $_POST['adminEnableRecovery'] == 1 @@ -47,7 +49,7 @@ if ( // If the recoveryAdmin UID exists but doesn't have admin rights } else { - \OCP\JSON::error(); + $return = false; } @@ -63,10 +65,12 @@ if ( $util->setupServerSide( $_POST['recoveryPassword'] ); // Store the UID in the DB - OC_Appconfig::setValue( 'encryption', 'recoveryAdminUid', $recoveryAdminUid ); + OC_Appconfig::setValue( 'files_encryption', 'recoveryAdminUid', $recoveryAdminUid ); - \OCP\JSON::success(); + $return = true; } -} \ No newline at end of file +} + +($return) ? OC_JSON::success() : OC_JSON::error(); \ No newline at end of file diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 9747fb20ad..c2de9d0b44 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -24,8 +24,10 @@ OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', ' OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfileFromClient' ); stream_wrapper_register( 'crypt', 'OCA\Encryption\Stream' ); -$view = new OC_FilesystemView('/'); -$session = new OCA\Encryption\Session($view); + +$view = new OC_FilesystemView( '/' ); + +$session = new OCA\Encryption\Session( $view ); if ( ! $session->getPrivateKey( \OCP\USER::getUser() ) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 82de80a1cf..e65f0945f4 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -63,7 +63,7 @@ class Hooks { $privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] ); - $session = new Session($view); + $session = new Session( $view ); $session->setPrivateKey( $privateKey, $params['uid'] ); @@ -116,8 +116,8 @@ class Hooks { // is in use (client-side encryption does not have access to // the necessary keys) if ( Crypt::mode() == 'server' ) { - $view = new \OC_FilesystemView( '/' ); - $session = new Session($view); + + $session = new Session(); // Get existing decrypted private key $privateKey = $session->getPrivateKey(); @@ -189,7 +189,7 @@ class Hooks { if ( $params['itemType'] === 'file' ) { $view = new \OC_FilesystemView( '/' ); - $session = new Session($view); + $session = new Session(); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); $path = $util->fileIdToPath( $params['itemSource'] ); @@ -244,7 +244,7 @@ class Hooks { if ( $params['itemType'] === 'file' ) { $view = new \OC_FilesystemView( '/' ); - $session = new Session($view); + $session = new Session(); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); $path = $util->fileIdToPath( $params['itemSource'] ); diff --git a/apps/files_encryption/js/settings.js b/apps/files_encryption/js/settings.js index 4f367f880d..9a0bebf247 100644 --- a/apps/files_encryption/js/settings.js +++ b/apps/files_encryption/js/settings.js @@ -16,11 +16,14 @@ $(document).ready(function(){ // Trigger ajax on recoveryAdmin status change $( 'input:radio[name="adminEnableRecovery"]' ).change( function() { + + var foo = $( this ).val(); + $.post( - '../ajax/adminrecovery.php' - , $( this ).val() + OC.filePath('files_encryption', 'ajax', 'adminrecovery.php') + , { adminEnableRecovery: foo, recoveryPassword: 'password' } , function( data ) { - // TODO: provide user with feedback of outcome + alert( data ); } ); } diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 7e18ec9b10..44a2e1aae5 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -101,7 +101,7 @@ class Proxy extends \OC_FileProxy { $userId = \OCP\USER::getUser(); $rootView = new \OC_FilesystemView( '/' ); $util = new Util( $rootView, $userId ); - $session = new Session($rootView); + $session = new Session( $rootView ); $fileOwner = \OC\Files\Filesystem::getOwner( $path ); $privateKey = $session->getPrivateKey(); $filePath = $util->stripUserFilesPath( $path ); @@ -115,9 +115,16 @@ class Proxy extends \OC_FileProxy { if ( $encKeyfile = Keymanager::getFileKey( $rootView, $fileOwner, $filePath ) ) { $keyPreExists = true; - + + // Fetch shareKey + $shareKey = Keymanager::getShareKey( $rootView, $userId, $filePath ); + // Decrypt the keyfile - $plainKey = $util->decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey ); + $plainKey = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); + + trigger_error("\$shareKey = $shareKey"); + + trigger_error("\$plainKey = $plainKey"); } else { @@ -170,6 +177,7 @@ class Proxy extends \OC_FileProxy { // Save sharekeys to user folders // TODO: openssl_seal generates new shareKeys (envelope keys) each time data is encrypted, but will data still be decryptable using old shareKeys? If so we don't need to replace the old shareKeys here, we only need to set the new ones + Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] ); // Set encrypted keyfile as common varname @@ -219,15 +227,18 @@ class Proxy extends \OC_FileProxy { // If data is a catfile if ( Crypt::mode() == 'server' - && Crypt::isCatfileContent( $data ) + && Crypt::isCatfileContent( $data ) // TODO: Do we really need this check? Can't we assume it is properly encrypted? ) { - // TODO use get owner to find correct location of key files for shared files - $session = new Session($view); + // TODO: use get owner to find correct location of key files for shared files + $session = new Session( $view ); $privateKey = $session->getPrivateKey( $userId ); // Get the file owner so we can retrieve its keyfile - list($fileOwner, $ownerPath) = $util->getUidAndFilename($relPath); +// list( $fileOwner, $ownerPath ) = $util->getUidAndFilename( $relPath ); + + $fileOwner = \OC\Files\Filesystem::getOwner( $path ); + $ownerPath = $util->stripUserFilesPath( $path ); // TODO: Don't trust $path, fetch owner path // Get the encrypted keyfile $encKeyfile = Keymanager::getFileKey( $view, $fileOwner, $ownerPath ); @@ -235,27 +246,9 @@ class Proxy extends \OC_FileProxy { // Attempt to fetch the user's shareKey $shareKey = Keymanager::getShareKey( $view, $userId, $relPath ); - // Check if key is shared or not - if ( $shareKey ) { - - \OC_FileProxy::$enabled = false; - -// trigger_error("\$encKeyfile = $encKeyfile, \$shareKey = $shareKey, \$privateKey = $privateKey"); - - // Decrypt keyfile with shareKey - $plainKeyfile = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); - -// $plainKeyfile = $encKeyfile; - -// trigger_error("PROXY plainkeyfile = ". var_export($plainKeyfile, 1)); - - } else { - - // If key is unshared, decrypt with user private key - $plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey ); - - } - + // Decrypt keyfile with shareKey + $plainKeyfile = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); + $plainData = Crypt::symmetricDecryptFileContent( $data, $plainKeyfile ); // trigger_error("PLAINDATA = ". var_export($plainData, 1)); diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index d269a56240..7315245fcc 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -236,7 +236,7 @@ class Stream { $this->getUser(); - $session = new Session($this->rootView); + $session = new Session( $this->rootView ); $privateKey = $session->getPrivateKey( $this->userId ); diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 420e3398a8..dc4e37150c 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -24,13 +24,17 @@ # Bugs # ---- # Sharing a file to a user without encryption set up will not provide them with access but won't notify the sharer -# Timeouts on first login due to encryption of very large files +# Sharing files to other users currently broken (due to merge + ongoing implementation of support for lost password recovery) +# Timeouts on first login due to encryption of very large files (fix in progress, as a result streaming is currently broken) +# Sharing all files to admin for recovery purposes still in progress +# Possibly public links are broken (not tested since last merge of master) +# getOwner() currently returns false in all circumstances, unsure what code is returning this... # Missing features # ---------------- -# Re-use existing keyfiles so they don't need version control (part implemented, stream{} and util{} remain) # Make sure user knows if large files weren't encrypted +# Support for resharing encrypted files # Test @@ -122,7 +126,8 @@ class Util { $this->userId = $userId; $this->client = $client; $this->userDir = '/' . $this->userId; - $this->userFilesDir = '/' . $this->userId . '/' . 'files'; + $this->fileFolderName = 'files'; + $this->userFilesDir = '/' . $this->userId . '/' . $this->fileFolderName; // TODO: Does this need to be user configurable? $this->publicKeyDir = '/' . 'public-keys'; $this->encryptionDir = '/' . $this->userId . '/' . 'files_encryption'; $this->keyfilesPath = $this->encryptionDir . '/' . 'keyfiles'; @@ -690,7 +695,6 @@ class Util { /** * @brief Expand given path to all sub files & folders - * @param Session $session * @param string $path path which needs to be updated * @return array $pathsArray all found file paths * @note Paths of directories excluded, only *file* paths are returned @@ -747,6 +751,8 @@ class Util { * @param string $privateKey * @note Checks whether file was encrypted with openssl_seal or * openssl_encrypt, and decrypts accrdingly + * @note This was used when 2 types of encryption for keyfiles was used, + * but now we've switched to exclusively using openssl_seal() */ public function decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey ) { @@ -861,19 +867,55 @@ class Util { /** * @brief get uid of the owners of the file and the path to the file - * @param $filename + * @param $shareFilePath Path of the file to check + * @note $shareFilePath must be relative to data/UID/files. Files + * relative to /Shared are also acceptable * @return array */ - public function getUidAndFilename($filename) { - $uid = \OC\Files\Filesystem::getOwner($filename); - - \OC\Files\Filesystem::initMountPoints($uid); - if ( $uid != \OCP\User::getUser() ) { - $info = \OC\Files\Filesystem::getFileInfo($filename); - $ownerView = new \OC\Files\View('/'.$uid.'/files'); - $filename = $ownerView->getPath($info['fileid']); + public function getUidAndFilename( $shareFilePath ) { + + $fileOwnerUid = \OC\Files\Filesystem::getOwner( $shareFilePath ); + + // Check that UID is valid + if ( ! \OCP\User::userExists( $fileOwnerUid ) ) { + + throw new \Exception( 'Could not find owner (UID = "' . var_export( $fileOwnerUid, 1 ) . '") of file "' . $shareFilePath . '"' ); + } - return array($uid, $filename); + + // NOTE: Bah, this dependency should be elsewhere + \OC\Files\Filesystem::initMountPoints( $fileOwnerUid ); + + // If the file owner is the currently logged in user + if ( $fileOwnerUid == $this->userId ) { + + // Assume the path supplied is correct + $filename = $shareFilePath; + + } else { + + $info = \OC\Files\Filesystem::getFileInfo( $shareFilePath ); + $ownerView = new \OC\Files\View( '/' . $fileOwnerUid . '/files' ); + + // Fetch real file path from DB + $filename = $ownerView->getPath( $info['fileid'] ); // TODO: Check that this returns a path without including the user data dir + + } + + // Make path relative for use by $view + $relpath = $fileOwnerUid . '/' . $this->fileFolderName . '/' . $filename; + + // Check that the filename we're using is working + if ( $this->view->file_exists( $relpath ) ) { + + return array ( $fileOwnerUid, $relpath ); + + } else { + + throw new \Exception( 'Supplied path could not be resolved "' . $shareFilePath . '"' ); + + } + } } diff --git a/apps/files_encryption/test/proxy.php b/apps/files_encryption/test/proxy.php index 709730f760..5a2d851ff7 100644 --- a/apps/files_encryption/test/proxy.php +++ b/apps/files_encryption/test/proxy.php @@ -52,7 +52,7 @@ // $this->userId = 'admin'; // $this->pass = 'admin'; // -// $this->session = new Encryption\Session(); +// $this->session = new Encryption\Session( $view ); // FIXME: Provide a $view object for use here // // $this->session->setPrivateKey( // '-----BEGIN PRIVATE KEY----- diff --git a/apps/files_encryption/test/util.php b/apps/files_encryption/test/util.php index e2767a2ec3..3ebc484809 100755 --- a/apps/files_encryption/test/util.php +++ b/apps/files_encryption/test/util.php @@ -24,6 +24,8 @@ $loader->register(); use \Mockery as m; use OCA\Encryption; +\OC_User::login( 'admin', 'admin' ); + class Test_Enc_Util extends \PHPUnit_Framework_TestCase { function setUp() { @@ -184,6 +186,16 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase { $this->assertTrue( $util->setRecovery( $enabled ) ); } + + function testGetUidAndFilename() { + + \OC_User::setUserId( 'admin' ); + + $this->util->getUidAndFilename( 'test1.txt' ); + + + + } // /** // * @brief test decryption using legacy blowfish method From 770dcbf663c31c912b88b280121b21ec7ea4be8e Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 16 Apr 2013 14:50:20 +0200 Subject: [PATCH 058/257] Fixed stream{} reading of encrypted files (stream_read()) --- apps/files_encryption/lib/stream.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index ebfd05041b..f765d62201 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -239,13 +239,15 @@ class Stream { // Fetch existing keyfile $this->encKeyfile = Keymanager::getFileKey( $this->rootView, $this->userId, $this->relPath ); - $this->getUser(); + $this->setUserProperty(); $session = new Session( $this->rootView ); $privateKey = $session->getPrivateKey( $this->userId ); - $this->keyfile = Crypt::keyDecrypt( $this->encKeyfile, $privateKey ); + $shareKey = Keymanager::getShareKey( $this->rootView, $this->userId, $this->relPath ); + + $this->keyfile = Crypt::multiKeyDecrypt( $this->encKeyfile, $shareKey, $privateKey ); return true; @@ -257,7 +259,7 @@ class Stream { } - public function getuser() { + public function setUserProperty() { // Only get the user again if it isn't already set if ( empty( $this->userId ) ) { From f89a3604aabbd36f05789db46b6108f0f41f52b1 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 16 Apr 2013 18:29:22 +0200 Subject: [PATCH 059/257] Working on stream{} writing Development snapshot --- apps/files_encryption/appinfo/spec.txt | 6 +- apps/files_encryption/lib/keymanager.php | 22 +++++++ apps/files_encryption/lib/proxy.php | 44 ++++--------- apps/files_encryption/lib/stream.php | 83 ++++++++++++++++-------- apps/files_encryption/lib/util.php | 39 +++++++++++ 5 files changed, 133 insertions(+), 61 deletions(-) diff --git a/apps/files_encryption/appinfo/spec.txt b/apps/files_encryption/appinfo/spec.txt index a1846ca47f..4a7b3fc6ad 100644 --- a/apps/files_encryption/appinfo/spec.txt +++ b/apps/files_encryption/appinfo/spec.txt @@ -70,4 +70,8 @@ Notes is handled in the login hook listener. Therefore each time the user logs in their files are scanned to detect unencrypted and legacy encrypted files, and they are (re)encrypted as necessary. This may present a performance issue; we - need to monitor this. \ No newline at end of file + need to monitor this. +- When files are saved to ownCloud via WebDAV, a .part file extension is used so + that the file isn't cached before the upload has been completed. .part files + are not compatible with files_encrytion's key management system however, so + we have to always sanitise such paths manually before using them. \ No newline at end of file diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 3e26e6bb69..c37680fcbe 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -132,6 +132,28 @@ class Keymanager { } + /** + * @brief Remove .path extension from a file path + * @param string $path Path that may identify a .part file + * @return string File path without .part extension + */ + public static function fixPartialFilePath( $path ) { + + if ( preg_match( '/\.part$/', $path ) ) { + + $newLength = strlen( $path ) - 5; + $fPath = substr( $path, 0, $newLength ); + + return $fPath; + + } else { + + return $path; + + } + + } + /** * @brief retrieve keyfile for an encrypted file * @param \OC_FilesystemView $view diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 44a2e1aae5..4efb3d2e49 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -138,34 +138,9 @@ class Proxy extends \OC_FileProxy { // Encrypt data $encData = Crypt::symmetricEncryptFileContent( $data, $plainKey ); - // Check if key recovery is enabled - $recoveryEnabled = $util->recoveryEnabled(); + $sharingEnabled = \OCP\Share::isEnabled(); - // Make sure that a share key is generated for the owner too - $userIds = array( $userId ); - - if ( \OCP\Share::isEnabled() ) { - - // Find out who, if anyone, is sharing the file - $shareUids = \OCP\Share::getUsersSharingFile( $filePath, true, true, true ); - - $userIds = array_merge( $userIds, $shareUids ); - - } - - // If recovery is enabled, add the - // Admin UID to list of users to share to - if ( $recoveryEnabled ) { - - // FIXME: Create a separate admin user purely for recovery, and create method in util for fetching this id from DB? - $adminUid = 'recoveryAdmin'; - - $userIds[] = $adminUid; - - } - - // Remove duplicate UIDs - $uniqueUserIds = array_unique ( $userIds ); + $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $filePath ); // Fetch public keys for all users who will share the file $publicKeys = Keymanager::getPublicKeys( $rootView, $uniqueUserIds ); @@ -280,6 +255,8 @@ class Proxy extends \OC_FileProxy { */ public function preUnlink( $path ) { + $path = Keymanager::fixPartialFilePath( $path ); + // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; @@ -290,17 +267,20 @@ class Proxy extends \OC_FileProxy { $util = new Util( $view, $userId ); // Format path to be relative to user files dir - $relPath = $util->stripUserFilesPath($path); + $relPath = $util->stripUserFilesPath( $path ); - list($owner, $ownerPath) = $util->getUidAndFilename($relPath); +// list( $owner, $ownerPath ) = $util->getUidAndFilename( $relPath ); - $filePath = $owner . '/' . 'files_encryption' . '/' . 'keyfiles' . '/'. $ownerPath; + $fileOwner = \OC\Files\Filesystem::getOwner( $path ); + $ownerPath = $util->stripUserFilesPath( $path ); // TODO: Don't trust $path, fetch owner path + + $filePath = $fileOwner . '/' . 'files_encryption' . '/' . 'keyfiles' . '/'. $ownerPath; // Delete keyfile & shareKey so it isn't orphaned if ( ! ( - Keymanager::deleteFileKey( $view, $owner, $ownerPath ) - && Keymanager::delShareKey( $view, $owner, $ownerPath ) + Keymanager::deleteFileKey( $view, $fileOwner, $ownerPath ) + && Keymanager::delShareKey( $view, $fileOwner, $ownerPath ) ) ) { diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index f765d62201..3e854c8df8 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -44,6 +44,9 @@ namespace OCA\Encryption; * buffer size used internally by PHP. The encryption process makes the input * data longer, and input is chunked into smaller pieces in order to result in * a 8192 encrypted block size. + * @note When files are deleted via webdav, or when they are updated and the + * previous version deleted, this is handled by OC\Files\View, and thus the + * encryption proxies are used and keyfiles deleted. */ class Stream { @@ -171,17 +174,21 @@ class Stream { // // Get the data from the file handle $data = fread( $this->handle, 8192 ); + + $result = ''; if ( strlen( $data ) ) { - $this->getKey(); + if ( ! $this->getKey() ) { + + // Error! We don't have a key to decrypt the file with + throw new \Exception( 'Encryption key not found for "' . $this->rawPath . '" during attempted read via stream' ); - $result = Crypt::symmetricDecryptFileContent( $data, $this->keyfile ); + } + + // Decrypt data + $result = Crypt::symmetricDecryptFileContent( $data, $this->plainKey ); - } else { - - $result = ''; - } // $length = $this->size - $pos; @@ -224,18 +231,20 @@ class Stream { */ public function getKey() { - // fix performance issues - if(isset($this->keyfile) && isset($this->encKeyfile)) { - return true; - } - - // If a keyfile already exists for a file named identically to - // file to be written - if ( $this->rootView->file_exists( $this->userId . '/'. 'files_encryption' . '/' . 'keyfiles' . '/' . $this->relPath . '.key' ) ) { + // Check if key is already set + if ( isset( $this->plainKey ) && isset( $this->encKeyfile ) ) { - // TODO: add error handling for when file exists but no - // keyfile + return true; + + } + + // Avoid problems with .part file extensions + $this->relPath = Keymanager::fixPartialFilePath( $this->relPath ); + + // If a keyfile already exists + if ( $this->rootView->file_exists( $this->userId . '/'. 'files_encryption' . '/' . 'keyfiles' . '/' . $this->relPath . '.key' ) ) { + // Fetch and decrypt keyfile // Fetch existing keyfile $this->encKeyfile = Keymanager::getFileKey( $this->rootView, $this->userId, $this->relPath ); @@ -247,12 +256,17 @@ class Stream { $shareKey = Keymanager::getShareKey( $this->rootView, $this->userId, $this->relPath ); - $this->keyfile = Crypt::multiKeyDecrypt( $this->encKeyfile, $shareKey, $privateKey ); + $this->plainKey = Crypt::multiKeyDecrypt( $this->encKeyfile, $shareKey, $privateKey ); + + trigger_error( '$this->relPath = '.$this->relPath ); + trigger_error( '$this->userId = '.$this->userId); + trigger_error( '$this->encKeyfile = '.$this->encKeyfile ); + trigger_error( '$this->plainKey1 = '.var_export($this->plainKey, 1)); return true; } else { - + return false; } @@ -303,7 +317,7 @@ class Stream { $pointer = ftell( $this->handle ); // Make sure the userId is set - $this->getuser(); + $this->setUserProperty(); // TODO: Check if file is shared, if so, use multiKeyEncrypt and // save shareKeys in necessary user directories @@ -313,21 +327,34 @@ class Stream { // one), save the newly generated keyfile if ( ! $this->getKey() ) { - // TODO: Reuse the keyfile, it it exists, instead of making a new one - $this->keyfile = Crypt::generateKey(); + $util = new Util( $this->rootView, $this->userId ); + + $this->plainKey = Crypt::generateKey(); $this->publicKey = Keymanager::getPublicKey( $this->rootView, $this->userId ); - $this->encKeyfile = Crypt::keyEncrypt( $this->keyfile, $this->publicKey ); + $sharingEnabled = \OCP\Share::isEnabled(); + + $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $this->relPath ); + + // Fetch public keys for all users who will share the file + $publicKeys = Keymanager::getPublicKeys( $this->rootView, $uniqueUserIds ); + + $this->encKeyfiles = Crypt::multiKeyEncrypt( $this->plainKey, $publicKeys ); $view = new \OC_FilesystemView( '/' ); - $userId = \OCP\User::getUser(); // Save the new encrypted file key - Keymanager::setFileKey( $view, $this->relPath, $userId, $this->encKeyfile ); + Keymanager::setShareKeys( $view, $this->relPath, $this->encKeyfiles['keys'] ); + +// trigger_error( '$this->relPath = '.$this->relPath ); +// trigger_error( '$this->userId = '.$this->userId); +// trigger_error( '$this->encKeyfile = '.var_export($this->encKeyfiles, 1) ); } - + +// trigger_error( '$this->plainKey2 = '.var_export($this->plainKey, 1)); + // If extra data is left over from the last round, make sure it // is integrated into the next 6126 / 8192 block if ( $this->writeCache ) { @@ -355,7 +382,7 @@ class Stream { // // fseek( $this->handle, - ( $currentPos % 8192 ), SEEK_CUR ); // -// $block = Crypt::symmetricDecryptFileContent( $unencryptedNewBlock, $this->keyfile ); +// $block = Crypt::symmetricDecryptFileContent( $unencryptedNewBlock, $this->plainKey ); // // $x = substr( $block, 0, $currentPos % 8192 ); // @@ -396,7 +423,7 @@ class Stream { // Read the chunk from the start of $data $chunk = substr( $data, 0, 6126 ); - $encrypted = $this->preWriteEncrypt( $chunk, $this->keyfile ); + $encrypted = $this->preWriteEncrypt( $chunk, $this->plainKey ); // Write the data chunk to disk. This will be // attended to the last data chunk if the file @@ -461,7 +488,7 @@ class Stream { // Set keyfile property for file in question $this->getKey(); - $encrypted = $this->preWriteEncrypt( $this->writeCache, $this->keyfile ); + $encrypted = $this->preWriteEncrypt( $this->writeCache, $this->plainKey ); fwrite( $this->handle, $encrypted ); diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index dc4e37150c..c964bd94df 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -864,7 +864,46 @@ class Util { return array_unique( $users ); } + + /** + * @brief Find, sanitise and format users sharing a file + * @note This wraps other methods into a portable bundle + */ + public function getSharingUsersArray( $sharingEnabled, $filePath ) { + // Check if key recovery is enabled + $recoveryEnabled = $this->recoveryEnabled(); + + // Make sure that a share key is generated for the owner too + $userIds = array( $this->userId ); + + if ( $sharingEnabled ) { + + // Find out who, if anyone, is sharing the file + $shareUids = \OCP\Share::getUsersSharingFile( $filePath, true, true, true ); + + $userIds = array_merge( $userIds, $shareUids ); + + } + + // If recovery is enabled, add the + // Admin UID to list of users to share to + if ( $recoveryEnabled ) { + + // FIXME: Create a separate admin user purely for recovery, and create method in util for fetching this id from DB? + $adminUid = 'recoveryAdmin'; + + $userIds[] = $adminUid; + + } + + // Remove duplicate UIDs + $uniqueUserIds = array_unique ( $userIds ); + + return $uniqueUserIds; + + } + /** * @brief get uid of the owners of the file and the path to the file * @param $shareFilePath Path of the file to check From 6dd8c79461bc5edd723ffb1d561f8ab9251ba02c Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Wed, 17 Apr 2013 17:20:37 +0200 Subject: [PATCH 060/257] Development snapshot Working on stream{} write --- apps/files_encryption/lib/proxy.php | 5 +- apps/files_encryption/lib/stream.php | 80 +++++++++++++++------------- apps/files_encryption/lib/util.php | 3 ++ 3 files changed, 48 insertions(+), 40 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 4efb3d2e49..1e7ac609a4 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -122,9 +122,8 @@ class Proxy extends \OC_FileProxy { // Decrypt the keyfile $plainKey = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); - trigger_error("\$shareKey = $shareKey"); - - trigger_error("\$plainKey = $plainKey"); +// trigger_error("\$shareKey = $shareKey"); +// trigger_error("\$plainKey = $plainKey"); } else { diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 3e854c8df8..01eee177cd 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -225,7 +225,7 @@ class Stream { } /** - * @brief Get the keyfile for the current file, generate one if necessary + * @brief Fetch the plain encryption key for the file and set it as plainKey property * @param bool $generate if true, a new key will be generated if none can be found * @return bool true on key found and set, false on key not found and new key generated and set */ @@ -258,10 +258,10 @@ class Stream { $this->plainKey = Crypt::multiKeyDecrypt( $this->encKeyfile, $shareKey, $privateKey ); - trigger_error( '$this->relPath = '.$this->relPath ); - trigger_error( '$this->userId = '.$this->userId); - trigger_error( '$this->encKeyfile = '.$this->encKeyfile ); - trigger_error( '$this->plainKey1 = '.var_export($this->plainKey, 1)); +// trigger_error( '$this->relPath = '.$this->relPath ); +// trigger_error( '$this->userId = '.$this->userId); +// trigger_error( '$this->encKeyfile = '.$this->encKeyfile ); +// trigger_error( '$this->plainKey1 = '.var_export($this->plainKey, 1)); return true; @@ -319,40 +319,44 @@ class Stream { // Make sure the userId is set $this->setUserProperty(); - // TODO: Check if file is shared, if so, use multiKeyEncrypt and - // save shareKeys in necessary user directories - // Get / generate the keyfile for the file we're handling // If we're writing a new file (not overwriting an existing // one), save the newly generated keyfile if ( ! $this->getKey() ) { - $util = new Util( $this->rootView, $this->userId ); - $this->plainKey = Crypt::generateKey(); - $this->publicKey = Keymanager::getPublicKey( $this->rootView, $this->userId ); - - $sharingEnabled = \OCP\Share::isEnabled(); - - $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $this->relPath ); - - // Fetch public keys for all users who will share the file - $publicKeys = Keymanager::getPublicKeys( $this->rootView, $uniqueUserIds ); - - $this->encKeyfiles = Crypt::multiKeyEncrypt( $this->plainKey, $publicKeys ); - - $view = new \OC_FilesystemView( '/' ); - - // Save the new encrypted file key - Keymanager::setShareKeys( $view, $this->relPath, $this->encKeyfiles['keys'] ); - -// trigger_error( '$this->relPath = '.$this->relPath ); -// trigger_error( '$this->userId = '.$this->userId); -// trigger_error( '$this->encKeyfile = '.var_export($this->encKeyfiles, 1) ); - } + // Fetch user's public key + $this->publicKey = Keymanager::getPublicKey( $this->rootView, $this->userId ); + + // Check if OC sharing api is enabled + $sharingEnabled = \OCP\Share::isEnabled(); + + $util = new Util( $this->rootView, $this->userId ); + + // Get all users sharing the file + $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $this->relPath ); + + // Fetch public keys for all sharing users + $publicKeys = Keymanager::getPublicKeys( $this->rootView, $uniqueUserIds ); + + // Encrypt enc key for all sharing users + $this->encKeyfiles = Crypt::multiKeyEncrypt( $this->plainKey, $publicKeys ); + + $view = new \OC_FilesystemView( '/' ); + + // Save the new encrypted file key + Keymanager::setFileKey( $this->rootView, $this->relPath, $this->userId, $this->encKeyfiles['data'] ); + + // Save the sharekeys + Keymanager::setShareKeys( $view, $this->relPath, $this->encKeyfiles['keys'] ); + +// trigger_error( "\$this->encKeyfiles['data'] = ".$this->encKeyfiles['data'] ); +// trigger_error( '$this->relPath = '.$this->relPath ); +// trigger_error( '$this->userId = '.$this->userId); +// trigger_error( '$this->encKeyfile = '.var_export($this->encKeyfiles, 1) ); // trigger_error( '$this->plainKey2 = '.var_export($this->plainKey, 1)); // If extra data is left over from the last round, make sure it @@ -396,7 +400,7 @@ class Stream { // // While there still remains somed data to be processed & written while( strlen( $data ) > 0 ) { -// + // // Remaining length for this iteration, not of the // // entire file (may be greater than 8192 bytes) // $remainingLength = strlen( $data ); @@ -404,7 +408,7 @@ class Stream { // // If data remaining to be written is less than the // // size of 1 6126 byte block if ( strlen( $data ) < 6126 ) { - + // Set writeCache to contents of $data // The writeCache will be carried over to the // next write round, and added to the start of @@ -425,6 +429,8 @@ class Stream { $encrypted = $this->preWriteEncrypt( $chunk, $this->plainKey ); + trigger_error("\$encrypted = $encrypted"); + // Write the data chunk to disk. This will be // attended to the last data chunk if the file // being handled totals more than 6126 bytes @@ -441,7 +447,7 @@ class Stream { } } - + $this->size = max( $this->size, $pointer + $length ); return $length; @@ -493,7 +499,7 @@ class Stream { fwrite( $this->handle, $encrypted ); $this->writeCache = ''; - + } } @@ -501,16 +507,16 @@ class Stream { public function stream_close() { $this->flush(); - + if ( $this->meta['mode']!='r' and $this->meta['mode']!='rb' ) { - + \OC\Files\Filesystem::putFileInfo( $this->path, array( 'encrypted' => true, 'size' => $this->size ), '' ); } - + return fclose( $this->handle ); } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index c964bd94df..2fc7b959ec 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -29,6 +29,9 @@ # Sharing all files to admin for recovery purposes still in progress # Possibly public links are broken (not tested since last merge of master) # getOwner() currently returns false in all circumstances, unsure what code is returning this... +# encryptAll during login mangles paths: /files/files/ +# encryptAll is accessing files via encryption proxy - perhaps proxies should be disabled? +# Sharekeys appear to not be deleted when their parent file is, and thus get orphaned # Missing features From 2434739d699e2ca4316ea3aece86d7f609ff8e6d Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 18 Apr 2013 02:03:03 +0200 Subject: [PATCH 061/257] fix for trashbin --- apps/files_encryption/lib/proxy.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 1e7ac609a4..3af9dc73d8 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -254,6 +254,11 @@ class Proxy extends \OC_FileProxy { */ public function preUnlink( $path ) { + // let the trashbin handle this + if ( \OCP\App::isEnabled('files_trashbin') ) { + return true; + } + $path = Keymanager::fixPartialFilePath( $path ); // Disable encryption proxy to prevent recursive calls From a646a1169f9a17be8d520489ae85c16bbcc7236c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 18 Apr 2013 13:41:21 +0200 Subject: [PATCH 062/257] return filename relative to users file dir and not relative to data dir --- apps/files_encryption/lib/util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 2fc7b959ec..f03b2308b2 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -950,7 +950,7 @@ class Util { // Check that the filename we're using is working if ( $this->view->file_exists( $relpath ) ) { - return array ( $fileOwnerUid, $relpath ); + return array ( $fileOwnerUid, $filename ); } else { From bd3024242f95a0761c0ce2295b39b4e350a6795d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 18 Apr 2013 15:42:28 +0200 Subject: [PATCH 063/257] always save key file, the key doesn't change but the encrypted keyfile change always the same way like the share-keys change --- apps/files_encryption/lib/proxy.php | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 1e7ac609a4..4f02c60e10 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -113,8 +113,6 @@ class Proxy extends \OC_FileProxy { // Check if there is an existing key we can reuse if ( $encKeyfile = Keymanager::getFileKey( $rootView, $fileOwner, $filePath ) ) { - - $keyPreExists = true; // Fetch shareKey $shareKey = Keymanager::getShareKey( $rootView, $userId, $filePath ); @@ -127,8 +125,6 @@ class Proxy extends \OC_FileProxy { } else { - $keyPreExists = false; - // Make a new key $plainKey = Crypt::generateKey(); @@ -157,14 +153,9 @@ class Proxy extends \OC_FileProxy { // Set encrypted keyfile as common varname $encKey = $multiEncrypted['data']; - // Save the key if its new - if ( ! $keyPreExists ) { - - // Save keyfile for newly encrypted file in parallel directory tree - Keymanager::setFileKey( $rootView, $filePath, $fileOwner, $encKey ); - - } - + // Save keyfile for newly encrypted file in parallel directory tree + Keymanager::setFileKey( $rootView, $filePath, $fileOwner, $encKey ); + // Replace plain content with encrypted content by reference $data = $encData; From 7892fddcb95d5d4becde224b1d387025b2a5dd5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 18 Apr 2013 15:44:57 +0200 Subject: [PATCH 064/257] remove ToDo, every time the file key gets encrypted new share keys are generated and a new encrypted filekey. We always need to use the latest share-keys and encrypted keyfiles --- apps/files_encryption/lib/proxy.php | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 4f02c60e10..f996a612bf 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -146,7 +146,6 @@ class Proxy extends \OC_FileProxy { $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys ); // Save sharekeys to user folders - // TODO: openssl_seal generates new shareKeys (envelope keys) each time data is encrypted, but will data still be decryptable using old shareKeys? If so we don't need to replace the old shareKeys here, we only need to set the new ones Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] ); From 40905c8941fa707fe358c0f4a5413931b34f8217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 18 Apr 2013 16:34:23 +0200 Subject: [PATCH 065/257] fix file sharing, sharing files works now; moved the identification of file owner and the owner path in the keymanager functions so that other functions doesn't have to deal with it --- apps/files_encryption/lib/keymanager.php | 17 ++++++++++------- apps/files_encryption/lib/proxy.php | 13 +++---------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index c37680fcbe..52d100055e 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -107,11 +107,13 @@ class Keymanager { public static function setFileKey( \OC_FilesystemView $view, $path, $userId, $catfile ) { \OC_FileProxy::$enabled = false; + + $util = new Util($view, $userId); + list($owner, $filename) = $util->getUidAndFilename($path); + + $basePath = '/' . $owner . '/files_encryption/keyfiles'; - \OC\Files\Filesystem::initMountPoints($userId); - $basePath = '/' . $userId . '/files_encryption/keyfiles'; - - $targetPath = self::keySetPreparation( $view, $path, $basePath, $userId ); + $targetPath = self::keySetPreparation( $view, $filename, $basePath, $owner ); if ( !$view->is_dir( $basePath . '/' . $targetPath ) ) { @@ -166,10 +168,11 @@ class Keymanager { */ public static function getFileKey( \OC_FilesystemView $view, $userId, $filePath ) { - \OC\Files\Filesystem::initMountPoints($userId); - $filePath_f = ltrim( $filePath, '/' ); + $util = new Util($view, $userId); + list($owner, $filename) = $util->getUidAndFilename($filePath); + $filePath_f = ltrim( $filename, '/' ); - $keyfilePath = '/' . $userId . '/files_encryption/keyfiles/' . $filePath_f . '.key'; + $keyfilePath = '/' . $owner . '/files_encryption/keyfiles/' . $filePath_f . '.key'; \OC_FileProxy::$enabled = false; diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index f996a612bf..88a8c072ea 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -102,7 +102,6 @@ class Proxy extends \OC_FileProxy { $rootView = new \OC_FilesystemView( '/' ); $util = new Util( $rootView, $userId ); $session = new Session( $rootView ); - $fileOwner = \OC\Files\Filesystem::getOwner( $path ); $privateKey = $session->getPrivateKey(); $filePath = $util->stripUserFilesPath( $path ); // Set the filesize for userland, before encrypting @@ -112,7 +111,7 @@ class Proxy extends \OC_FileProxy { \OC_FileProxy::$enabled = false; // Check if there is an existing key we can reuse - if ( $encKeyfile = Keymanager::getFileKey( $rootView, $fileOwner, $filePath ) ) { + if ( $encKeyfile = Keymanager::getFileKey( $rootView, $userId, $filePath ) ) { // Fetch shareKey $shareKey = Keymanager::getShareKey( $rootView, $userId, $filePath ); @@ -153,7 +152,7 @@ class Proxy extends \OC_FileProxy { $encKey = $multiEncrypted['data']; // Save keyfile for newly encrypted file in parallel directory tree - Keymanager::setFileKey( $rootView, $filePath, $fileOwner, $encKey ); + Keymanager::setFileKey( $rootView, $filePath, $userId, $encKey ); // Replace plain content with encrypted content by reference $data = $encData; @@ -198,14 +197,8 @@ class Proxy extends \OC_FileProxy { $session = new Session( $view ); $privateKey = $session->getPrivateKey( $userId ); - // Get the file owner so we can retrieve its keyfile -// list( $fileOwner, $ownerPath ) = $util->getUidAndFilename( $relPath ); - - $fileOwner = \OC\Files\Filesystem::getOwner( $path ); - $ownerPath = $util->stripUserFilesPath( $path ); // TODO: Don't trust $path, fetch owner path - // Get the encrypted keyfile - $encKeyfile = Keymanager::getFileKey( $view, $fileOwner, $ownerPath ); + $encKeyfile = Keymanager::getFileKey( $view, $userId, $relPath ); // Attempt to fetch the user's shareKey $shareKey = Keymanager::getShareKey( $view, $userId, $relPath ); From 1df36e0c889e9f80f821274f7f5d1e01a7cc01ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 18 Apr 2013 16:37:49 +0200 Subject: [PATCH 066/257] rename $shareFilePath to $path to avoid confusions, it is not about paths to share files but about general path to files stored in ownCloud --- apps/files_encryption/lib/util.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index f03b2308b2..dbe4acc74e 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -909,19 +909,19 @@ class Util { /** * @brief get uid of the owners of the file and the path to the file - * @param $shareFilePath Path of the file to check + * @param $path Path of the file to check * @note $shareFilePath must be relative to data/UID/files. Files * relative to /Shared are also acceptable * @return array */ - public function getUidAndFilename( $shareFilePath ) { - - $fileOwnerUid = \OC\Files\Filesystem::getOwner( $shareFilePath ); + public function getUidAndFilename( $path ) { + + $fileOwnerUid = \OC\Files\Filesystem::getOwner( $path ); // Check that UID is valid if ( ! \OCP\User::userExists( $fileOwnerUid ) ) { - throw new \Exception( 'Could not find owner (UID = "' . var_export( $fileOwnerUid, 1 ) . '") of file "' . $shareFilePath . '"' ); + throw new \Exception( 'Could not find owner (UID = "' . var_export( $fileOwnerUid, 1 ) . '") of file "' . $path . '"' ); } @@ -932,11 +932,11 @@ class Util { if ( $fileOwnerUid == $this->userId ) { // Assume the path supplied is correct - $filename = $shareFilePath; + $filename = $path; } else { - $info = \OC\Files\Filesystem::getFileInfo( $shareFilePath ); + $info = \OC\Files\Filesystem::getFileInfo( $path ); $ownerView = new \OC\Files\View( '/' . $fileOwnerUid . '/files' ); // Fetch real file path from DB @@ -954,7 +954,7 @@ class Util { } else { - throw new \Exception( 'Supplied path could not be resolved "' . $shareFilePath . '"' ); + throw new \Exception( 'Supplied path could not be resolved "' . $path . '"' ); } From fe58e4b1a6a0f3b63afe74690986493facdad2c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 18 Apr 2013 17:46:04 +0200 Subject: [PATCH 067/257] we need to add the owner of the file as parameter in case someone else like the owner edits the file; if $includeOwner is set than add owner also if no other recipient was found. This changes enable all user with write access to the file to edit it and to encrypt it to the right list of users again --- lib/public/share.php | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index 876de89257..acdf895c92 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -127,21 +127,21 @@ class Share { /** * @brief Find which users can access a shared item * @param $path to the file + * @param $user owner of the file * @param include owner to the list of users with access to the file * @return array * @note $path needs to be relative to user data dir, e.g. 'file.txt' * not '/admin/data/file.txt' */ - public static function getUsersSharingFile( $path, $includeOwner = false, $removeDuplicates = true ) { + public static function getUsersSharingFile( $path, $user, $includeOwner = false, $removeDuplicates = true ) { - $user = \OCP\User::getUser(); $path_parts = explode(DIRECTORY_SEPARATOR, trim($path, DIRECTORY_SEPARATOR)); $path = ''; $shares = array(); - + $view = new \OC\Files\View('/'.$user.'/files/'); foreach ($path_parts as $p) { $path .= '/'.$p; - $meta = \OC\Files\Filesystem::getFileInfo(\OC_Filesystem::normalizePath($path)); + $meta = $view->getFileInfo(\OC_Filesystem::normalizePath($path)); $source = $meta['fileid']; // Fetch all shares of this file path from DB @@ -203,12 +203,9 @@ class Share { $shares[] = "ownCloud"; } } - - if ( ! empty( $shares ) ) { - // Include owner in list of users, if requested - if ( $includeOwner ) { - $shares[] = $user; - } + // Include owner in list of users, if requested + if ( $includeOwner ) { + $shares[] = $user; } return array_unique($shares); From 39c717b24cd4551a78d07256e15b29e52841f49b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 18 Apr 2013 17:52:27 +0200 Subject: [PATCH 068/257] some fixes to the keymanager class to identify the file owner and the owner path correctly. --- apps/files_encryption/lib/keymanager.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 52d100055e..5c5a6c7ec5 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -108,7 +108,8 @@ class Keymanager { \OC_FileProxy::$enabled = false; - $util = new Util($view, $userId); + //here we need the currently logged in user, while userId can be a different user + $util = new Util($view, \OCP\User::getUser()); list($owner, $filename) = $util->getUidAndFilename($path); $basePath = '/' . $owner . '/files_encryption/keyfiles'; @@ -168,7 +169,7 @@ class Keymanager { */ public static function getFileKey( \OC_FilesystemView $view, $userId, $filePath ) { - $util = new Util($view, $userId); + $util = new Util($view, \OCP\User::getUser()); list($owner, $filename) = $util->getUidAndFilename($filePath); $filePath_f = ltrim( $filename, '/' ); @@ -298,7 +299,8 @@ class Keymanager { */ public static function setShareKey( \OC_FilesystemView $view, $path, $userId, $shareKey ) { - $util = new Util( $view, $userId ); + //here we need the currently logged in user, while userId can be a different user + $util = new Util( $view, \OCP\User::getUser() ); list($owner, $filename) = $util->getUidAndFilename($path); @@ -368,7 +370,8 @@ class Keymanager { \OC_FileProxy::$enabled = false; - $util = new Util( $view, $userId ); + //here we need the currently logged in user, while userId can be a different user + $util = new Util( $view, \OCP\User::getUser() ); list($owner, $filename) = $util->getUidAndFilename($filePath); From 935d0398600df7c0f46f1cf5d5905c423b9c22e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 18 Apr 2013 17:53:59 +0200 Subject: [PATCH 069/257] necessary changes in util.php after the changes in \OCP\Share::getUsersSharingFile() (fe58e4b1a6a0f3b63afe74690986493facdad2c4) --- apps/files_encryption/lib/util.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index dbe4acc74e..e4321fdb9d 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -878,12 +878,15 @@ class Util { $recoveryEnabled = $this->recoveryEnabled(); // Make sure that a share key is generated for the owner too - $userIds = array( $this->userId ); - + list($owner, $ownerPath) = $this->getUidAndFilename($filePath); + + //$userIds = array( $this->userId ); + $userIds = array(); + if ( $sharingEnabled ) { // Find out who, if anyone, is sharing the file - $shareUids = \OCP\Share::getUsersSharingFile( $filePath, true, true, true ); + $shareUids = \OCP\Share::getUsersSharingFile( $ownerPath, $owner,true, true, true ); $userIds = array_merge( $userIds, $shareUids ); From 5a7a64df08ba0270d282389ff798708367c30e43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 18 Apr 2013 20:00:45 +0200 Subject: [PATCH 070/257] Session needs filesystem view as parameter; use getSharingUsersArray(), this function also adds the owner to the list --- apps/files_encryption/hooks/hooks.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index e65f0945f4..265b90a87a 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -189,13 +189,13 @@ class Hooks { if ( $params['itemType'] === 'file' ) { $view = new \OC_FilesystemView( '/' ); - $session = new Session(); + $session = new Session($view); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); $path = $util->fileIdToPath( $params['itemSource'] ); - - // Note: this currently doesn't include the owner due to \OC\Files\Filesystem::getOwner() - $usersSharing = $util->getUsersSharingFile( $path ); + + $sharingEnabled = \OCP\Share::isEnabled(); + $usersSharing = $util->getSharingUsersArray( $sharingEnabled, $path); // Recursively expand path to include subfiles $allPaths = $util->getPaths( $path ); From 2bd338c49fd15a992ecc8c796cb921af4ee59e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 18 Apr 2013 20:02:27 +0200 Subject: [PATCH 071/257] getUsersSharingFile() no longer needed, use getSharingUsersArray() instead; fix filterShareReadyUsers() to return the correct results --- apps/files_encryption/lib/util.php | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index e4321fdb9d..8807de7c2a 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -657,14 +657,12 @@ class Util { public function filterShareReadyUsers( $unfilteredUsers ) { // This array will collect the filtered IDs - $userIds = array(); + $readyIds = $unreadyIds = array(); // Loop through users and create array of UIDs that need new keyfiles foreach ( $unfilteredUsers as $user ) { $util = new Util( $this->view, $user ); - - $readyIds = $unreadyIds = array(); // Check that the user is encryption capable, or is the // public system user 'ownCloud' (for public shares) @@ -690,7 +688,7 @@ class Util { } return array ( - 'ready' => $userIds + 'ready' => $readyIds , 'unready' => $unreadyIds ); @@ -810,7 +808,7 @@ class Util { } // Get public keys for each user, ready for generating sharekeys - $userPubKeys = Keymanager::getPublicKeys( $this->view, $filteredUids['ready'] ); // TODO: check this includes the owner's public key + $userPubKeys = Keymanager::getPublicKeys( $this->view, $filteredUids['ready'] ); \OC_FileProxy::$enabled = false; @@ -846,28 +844,6 @@ class Util { return true; } - /** - * @brief Returns the users who are sharing a file, including the file owner - * @param $path Relative path of the file, like files/file.txt - * @return $users array of UIDs - * @note This wraps the OCP\Share method, but includes the owner even if - * the file isn't registered in sharing API - */ - public function getUsersSharingFile( $path ) { - - $users = \OCP\Share::getUsersSharingFile( $path, true, true ); - - // FIXME: this is returning empty :/ - $owner = \OC\Files\Filesystem::getOwner( $path ); - -// trigger_error( var_export( $owner, 1)); - - $users[] = $owner; - - return array_unique( $users ); - - } - /** * @brief Find, sanitise and format users sharing a file * @note This wraps other methods into a portable bundle From 0e1970438b6dd7b6f705aeb420e1d4b4bd27c609 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 18 Apr 2013 22:34:22 +0200 Subject: [PATCH 072/257] fixed incorrect filesize, download via web is now possible fixed broken file-info --- apps/files_encryption/lib/proxy.php | 36 ++++++++++++++++++++++++++-- apps/files_encryption/lib/stream.php | 2 +- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 3af9dc73d8..e23598bb5f 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -439,9 +439,41 @@ class Proxy extends \OC_FileProxy { public function postFileSize( $path, $size ) { - if ( Crypt::isCatfileContent( $path ) ) { + // Reformat path for use with OC_FSV + $path_split = explode( '/', $path ); + $path_f = implode( '/', array_slice( $path_split, 3 ) ); + + if ( Crypt::isEncryptedMeta( $path_f ) ) { - $cached = \OC\Files\Filesystem::getFileInfo( $path, '' ); + // Disable encryption proxy to prevent recursive calls + \OC_FileProxy::$enabled = false; + + // get file info + $cached = \OC\Files\Filesystem::getFileInfo( $path_f, '' ); + + // calculate last chunk nr + $lastChunckNr = floor( $size / 8192); + + // open stream + $result = fopen( 'crypt://'.$path_f, "r" ); + + // calculate last chunk position + $lastChunckPos = ( $lastChunckNr * 8192 ); + + // seek to end + fseek( $result, $lastChunckPos ); + + // get the content of the last chunck + $lastChunkContent = fgets( $result ); + + // calc the real filesize with the size of the last chunk + $realSize = ( ( $lastChunckNr * 6126 ) + strlen( $lastChunkContent ) ); + + // enable proxy + \OC_FileProxy::$enabled = true; + + // set the size + $cached['size'] = $realSize; return $cached['size']; diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 01eee177cd..4b33c200bf 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -513,7 +513,7 @@ class Stream { and $this->meta['mode']!='rb' ) { - \OC\Files\Filesystem::putFileInfo( $this->path, array( 'encrypted' => true, 'size' => $this->size ), '' ); + \OC\Files\Filesystem::putFileInfo( $this->relPath, array( 'encrypted' => true, 'size' => $this->size ), '' ); } From 12785b93f188c85f19e52917c66aa749b9836ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 19 Apr 2013 13:17:08 +0200 Subject: [PATCH 073/257] make sure that all share keys get deleted if a file/folder gets unshared from a user/group --- apps/files_encryption/hooks/hooks.php | 15 +++++--- apps/files_encryption/lib/keymanager.php | 48 +++++++++++++++++------- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 265b90a87a..2731ee1112 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -240,22 +240,27 @@ class Hooks { // [shareType] => 0 // [shareWith] => test1 - // TODO: Should other kinds of item be encrypted too? - if ( $params['itemType'] === 'file' ) { + if ( $params['itemType'] === 'file' || $params['itemType'] === 'folder' ) { $view = new \OC_FilesystemView( '/' ); - $session = new Session(); + $session = new Session($view); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); $path = $util->fileIdToPath( $params['itemSource'] ); - + + if ($params['shareType'] == \OCP\Share::SHARE_TYPE_GROUP) { + $userIds = \OC_Group::usersInGroup($params['shareWith']); + } else { + $userIds = array($params['shareWith']); + } + // If path is a folder, get all children $allPaths = $util->getPaths( $path ); foreach ( $allPaths as $path ) { // Unshare each child path - if ( ! Keymanager::delShareKey( $view, $params['shareWith'], $path ) ) { + if ( ! Keymanager::delShareKey( $view, $userIds, $path ) ) { $failed[] = $path; diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 5c5a6c7ec5..f23423062b 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -395,27 +395,28 @@ class Keymanager { /** * @brief Delete a single user's shareKey for a single file */ - public static function delShareKey( \OC_FilesystemView $view, $userId, $filePath ) { + public static function delShareKey( \OC_FilesystemView $view, $userIds, $filePath ) { \OC_FileProxy::$enabled = false; - $shareKeyPath = '/' . $userId . '/files_encryption/share-keys/' . $filePath; + //here we need the currently logged in user, while userId can be a different user + $util = new Util( $view, \OCP\User::getUser() ); + + list($owner, $filename) = $util->getUidAndFilename($filePath); + + $shareKeyPath = '/' . $owner . '/files_encryption/share-keys/' . $filename; $result = false; if ( $view->is_dir($shareKeyPath) ) { - $result = $view->unlink($shareKeyPath); + + $localPath = \OC_Filesystem::normalizePath($view->getLocalFolder($shareKeyPath)); + $result = self::recursiveDelShareKeys($localPath, $userIds); + } else { - $absPath = $view->getLocalFile($shareKeyPath); - - $matches = glob(preg_quote($absPath).'.*.shareKey' ); - - if ( $matches ) { - - foreach ( $matches as $ma ) { - unlink($ma); - } + foreach ($userIds as $userId) { + $view->unlink($shareKeyPath.'.'.$userId.'.shareKey'); } $result = true; @@ -432,7 +433,28 @@ class Keymanager { return $result; } - + + /** + * @brief recursively delete share keys from given users + * + * @param type $dir directory + * @param type $userIds user ids for which the share keys should be deleted + */ + private static function recursiveDelShareKeys($dir, $userIds) { + foreach ($userIds as $userId) { + $completePath = $dir.'/.*'.'.'.$userId.'.shareKey'; + $matches = glob(preg_quote($dir).'/*'.preg_quote('.'.$userId.'.shareKey')); + } + foreach ($matches as $ma) { + unlink($ma); + } + $subdirs = $directories = glob(preg_quote($dir) . '/*' , GLOB_ONLYDIR); + foreach ( $subdirs as $subdir ) { + self::recursiveDelShareKeys($subdir, $userIds); + } + return $true; + } + /** * @brief Make preparations to vars and filesystem for saving a keyfile */ From 6b47da10bea66d7a925de2850919b503201558be Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 22 Apr 2013 04:40:49 +0200 Subject: [PATCH 074/257] improved rename and file size support fix missing user_id on write --- apps/files_encryption/lib/proxy.php | 174 +++++++++++++++------------ apps/files_encryption/lib/stream.php | 31 ++--- 2 files changed, 115 insertions(+), 90 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 67c93694e3..505fad440d 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -288,38 +288,54 @@ class Proxy extends \OC_FileProxy { * @return bool Result of rename() * @note This is pre rather than post because using post didn't work */ - public function preRename( $oldPath, $newPath ) { - - // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; - - $view = new \OC_FilesystemView( '/' ); - - $userId = \OCP\USER::getUser(); - - // Format paths to be relative to user files dir - $oldTrimmed = ltrim( $oldPath, '/' ); - $oldSplit = explode( '/', $oldTrimmed ); - $oldSliced = array_slice( $oldSplit, 2 ); - $oldRelPath = implode( '/', $oldSliced ); - $oldKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $oldRelPath . '.key'; - - $newTrimmed = ltrim( $newPath, '/' ); - $newSplit = explode( '/', $newTrimmed ); - $newSliced = array_slice( $newSplit, 2 ); - $newRelPath = implode( '/', $newSliced ); - $newKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $newRelPath . '.key'; - - // Rename keyfile so it isn't orphaned - $result = $view->rename( $oldKeyfilePath, $newKeyfilePath ); - - \OC_FileProxy::$enabled = true; - - return $result; - - } - - public function postFopen( $path, &$result ){ + public function preRename( $oldPath, $newPath ) + { + + // Disable encryption proxy to prevent recursive calls + \OC_FileProxy::$enabled = false; + + $view = new \OC_FilesystemView('/'); + + $userId = \OCP\USER::getUser(); + + // Format paths to be relative to user files dir + $oldTrimmed = ltrim($oldPath, '/'); + $oldSplit = explode('/', $oldTrimmed); + $oldSliced = array_slice($oldSplit, 2); + $oldRelPath = implode('/', $oldSliced); + $oldKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $oldRelPath; + + + $newTrimmed = ltrim($newPath, '/'); + $newSplit = explode('/', $newTrimmed); + $newSliced = array_slice($newSplit, 2); + $newRelPath = implode('/', $newSliced); + $newKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $newRelPath; + + // add key ext if this is not an folder + if (!$view->is_dir($oldKeyfilePath)) { + $oldKeyfilePath .= '.key'; + $newKeyfilePath .= '.key'; + } else { + // handle share-keys folders + $oldShareKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $oldRelPath; + $newShareKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $newRelPath; + $view->rename($oldShareKeyfilePath, $newShareKeyfilePath); + } + + //TODO add support for share-keys files + //... + + // Rename keyfile so it isn't orphaned + $result = $view->rename($oldKeyfilePath, $newKeyfilePath); + + \OC_FileProxy::$enabled = true; + + return $result; + + } + + public function postFopen( $path, &$result ){ if ( !$result ) { @@ -421,49 +437,55 @@ class Proxy extends \OC_FileProxy { } public function postFileSize( $path, $size ) { - - // Reformat path for use with OC_FSV - $path_split = explode( '/', $path ); - $path_f = implode( '/', array_slice( $path_split, 3 ) ); - - if ( Crypt::isEncryptedMeta( $path_f ) ) { - - // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; - - // get file info - $cached = \OC\Files\Filesystem::getFileInfo( $path_f, '' ); - - // calculate last chunk nr - $lastChunckNr = floor( $size / 8192); - - // open stream - $result = fopen( 'crypt://'.$path_f, "r" ); - - // calculate last chunk position - $lastChunckPos = ( $lastChunckNr * 8192 ); - - // seek to end - fseek( $result, $lastChunckPos ); - - // get the content of the last chunck - $lastChunkContent = fgets( $result ); - - // calc the real filesize with the size of the last chunk - $realSize = ( ( $lastChunckNr * 6126 ) + strlen( $lastChunkContent ) ); - - // enable proxy - \OC_FileProxy::$enabled = true; - - // set the size - $cached['size'] = $realSize; - - return $cached['size']; - - } else { - - return $size; - - } + + // Reformat path for use with OC_FSV + $path_split = explode('/', $path); + $path_f = implode('/', array_slice($path_split, 3)); + + $view = new \OC_FilesystemView( '/' ); + $userId = \OCP\User::getUser(); + $util = new Util( $view, $userId ); + + if ($util->isEncryptedPath($path)) { + + // Disable encryption proxy to prevent recursive calls + \OC_FileProxy::$enabled = false; + + // get file info + $cached = \OC\Files\Filesystem::getFileInfo($path_f, ''); + + // calculate last chunk nr + $lastChunckNr = floor($size / 8192); + + // open stream + $result = fopen('crypt://' . $path_f, "r"); + + if(is_resource($result)) { + // calculate last chunk position + $lastChunckPos = ($lastChunckNr * 8192); + + // seek to end + fseek($result, $lastChunckPos); + + // get the content of the last chunck + $lastChunkContent = fgets($result); + + // calc the real file size with the size of the last chunk + $realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent)); + + // set the size + $cached['size'] = $realSize; + } + + // enable proxy + \OC_FileProxy::$enabled = true; + + return $cached['size']; + + } else { + + return $size; + + } } } diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 4b33c200bf..c12fab783b 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -101,6 +101,9 @@ class Stream { } else { + // Disable fileproxies so we can get the file size and open the source file without recursive encryption + \OC_FileProxy::$enabled = false; + if ( $mode == 'w' or $mode == 'w+' @@ -119,9 +122,6 @@ class Stream { } - // Disable fileproxies so we can open the source file without recursive encryption - \OC_FileProxy::$enabled = false; - //$this->handle = fopen( $this->rawPath, $mode ); $this->handle = $this->rootView->fopen( $this->rawPath, $mode ); @@ -240,14 +240,13 @@ class Stream { // Avoid problems with .part file extensions $this->relPath = Keymanager::fixPartialFilePath( $this->relPath ); - + + // Fetch and decrypt keyfile + // Fetch existing keyfile + $this->encKeyfile = Keymanager::getFileKey( $this->rootView, $this->userId, $this->relPath ); + // If a keyfile already exists - if ( $this->rootView->file_exists( $this->userId . '/'. 'files_encryption' . '/' . 'keyfiles' . '/' . $this->relPath . '.key' ) ) { - - // Fetch and decrypt keyfile - // Fetch existing keyfile - $this->encKeyfile = Keymanager::getFileKey( $this->rootView, $this->userId, $this->relPath ); - + if ( $this->encKeyfile ) { $this->setUserProperty(); $session = new Session( $this->rootView ); @@ -338,11 +337,15 @@ class Stream { // Get all users sharing the file $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $this->relPath ); - + + // allways add current user + $uniqueUserIds[] = $this->userId; + array_unique( $uniqueUserIds ); + // Fetch public keys for all sharing users $publicKeys = Keymanager::getPublicKeys( $this->rootView, $uniqueUserIds ); - - // Encrypt enc key for all sharing users + + // Encrypt enc key for all sharing users $this->encKeyfiles = Crypt::multiKeyEncrypt( $this->plainKey, $publicKeys ); $view = new \OC_FilesystemView( '/' ); @@ -429,7 +432,7 @@ class Stream { $encrypted = $this->preWriteEncrypt( $chunk, $this->plainKey ); - trigger_error("\$encrypted = $encrypted"); + //trigger_error("\$encrypted = $encrypted"); // Write the data chunk to disk. This will be // attended to the last data chunk if the file From a2ba3c8a43780eab5ad8a4d96db33c584e7ae2ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 22 Apr 2013 11:58:39 +0200 Subject: [PATCH 075/257] fix sharing of folders. First we need to collect all files. Than we need to find all users with access to the file because this can vary from file to file and than we can encrypt it for all recipients --- apps/files_encryption/hooks/hooks.php | 72 +++++++++++++-------------- apps/files_encryption/lib/util.php | 20 ++++++++ 2 files changed, 54 insertions(+), 38 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 2731ee1112..13cf352b4e 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -166,8 +166,8 @@ class Hooks { /** * @brief */ - public static function postShared( $params ) { - + public static function postShared($params) { + // NOTE: $params has keys: // [itemType] => file // itemSource -> int, filecache file ID @@ -183,50 +183,46 @@ class Hooks { // [fileSource] => 13 // [fileTarget] => /test8 // [id] => 10 - // [token] => - + // [token] => // TODO: Should other kinds of item be encrypted too? - if ( $params['itemType'] === 'file' ) { - - $view = new \OC_FilesystemView( '/' ); + if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') { + + $view = new \OC_FilesystemView('/'); $session = new Session($view); $userId = \OCP\User::getUser(); - $util = new Util( $view, $userId ); - $path = $util->fileIdToPath( $params['itemSource'] ); + $util = new Util($view, $userId); + $path = $util->fileIdToPath($params['itemSource']); $sharingEnabled = \OCP\Share::isEnabled(); - $usersSharing = $util->getSharingUsersArray( $sharingEnabled, $path); - - // Recursively expand path to include subfiles - $allPaths = $util->getPaths( $path ); - - $failed = array(); - - // Loop through all subfiles - foreach ( $allPaths as $path ) { - - // Attempt to set shareKey - if ( ! $util->setSharedFileKeyfiles( $session, $usersSharing, $path ) ) { - - $failed[] = $path; - - } - - } - - // If no attempts to set keyfiles failed - if ( empty( $failed ) ) { - - return true; - + + if ($params['itemType'] === 'folder') { + //list($owner, $ownerPath) = $util->getUidAndFilename($filePath); + $allFiles = $util->getAllFiles($path); } else { - - return false; - + $allFiles = array($path); + } + + foreach ($allFiles as $path) { + $usersSharing = $util->getSharingUsersArray($sharingEnabled, $path); + + $failed = array(); + + // Attempt to set shareKey + if (!$util->setSharedFileKeyfiles($session, $usersSharing, $path)) { + + $failed[] = $path; + } + } + + // If no attempts to set keyfiles failed + if (empty($failed)) { + + return true; + } else { + + return false; } - } - } /** diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 8807de7c2a..b3df7f0db0 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -939,4 +939,24 @@ class Util { } + /** + *@ brief geo recursively through a dir and collect all files and sub files. + * @param type $dir relative to the users files folder + * @return array with list of files relative to the users files folder + */ + public function getAllFiles($dir) { + $result = array(); + $path = $this->view->getLocalFile(); + $content = $this->view->getDirectoryContent("/".$this->userFilesDir.'/'.$this->filesFolderName.$dir); + + foreach ($content as $c) { + if ($c['type'] === "dir" ) { + $result = array_merge($result, $this->getAllFiles(substr($c['path'],5))); + } else { + $result[] = substr($c['path'], 5); + } + } + return $result; + } + } From 8a46e809f00745f4b67d118e85ec2d35e74b732e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 22 Apr 2013 12:22:07 +0200 Subject: [PATCH 076/257] remove util::getPaths(), this function was broken and is replaced my util::getAllFiles(). When unsharing a folder only remove the share key for sub files if the user really no longer have access to the file. Can happen that a sub-file/-folder is shared to a group the user is a member of or explicitly once more to the same user --- apps/files_encryption/hooks/hooks.php | 21 +++++++---- apps/files_encryption/lib/util.php | 51 --------------------------- 2 files changed, 14 insertions(+), 58 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 13cf352b4e..e3861e7cc5 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -196,7 +196,6 @@ class Hooks { $sharingEnabled = \OCP\Share::isEnabled(); if ($params['itemType'] === 'folder') { - //list($owner, $ownerPath) = $util->getUidAndFilename($filePath); $allFiles = $util->getAllFiles($path); } else { $allFiles = array($path); @@ -250,13 +249,21 @@ class Hooks { $userIds = array($params['shareWith']); } - // If path is a folder, get all children - $allPaths = $util->getPaths( $path ); + if ($params['itemType'] === 'folder') { + $allFiles = $util->getAllFiles($path); + } else { + $allFiles = array($path); + } + - foreach ( $allPaths as $path ) { - - // Unshare each child path - if ( ! Keymanager::delShareKey( $view, $userIds, $path ) ) { + foreach ( $allFiles as $path ) { + + // check if the user still has access to the file, otherwise delete share key + $sharingUsers = $util->getSharingUsersArray(true, $path); + + // Unshare every user who no longer has access to the file + $delUsers = array_diff($userIds, $sharingUsers); + if ( ! Keymanager::delShareKey( $view, $delUsers, $path ) ) { $failed[] = $path; diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index b3df7f0db0..de63e0ff9f 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -693,58 +693,7 @@ class Util { ); } - - /** - * @brief Expand given path to all sub files & folders - * @param string $path path which needs to be updated - * @return array $pathsArray all found file paths - * @note Paths of directories excluded, only *file* paths are returned - */ - public function getPaths( $path ) { - // Default return value is success - $result = true; - - // Make path include 'files' dir for OC_FSV operations - $fPath = 'files' . $path; - - // If we're handling a single file - if ( ! $this->view->is_dir( $fPath ) ) { - - $pathsArray[] = $path; - - // If we're handling a folder (recursively) - } else { - - $subFiles = $this->view->getDirectoryContent( $fPath ); - - foreach ( $subFiles as $file ) { - - $filePath = substr( $file['path'], 5 ); - - // If this is a nested file - if ( ! $this->view->is_dir( $fPath ) ) { - - // Add the file path to array - $pathsArray[] = $path; - - } else { - - // If this is a nested folder - $dirPaths = $this->getPaths( $filePath ); - - // Add all subfiles & folders to the array - $pathsArray = array_merge( $dirPaths, $pathsArray ); - - } - } - - } - - return $pathsArray; - - } - /** * @brief Decrypt a keyfile without knowing how it was encrypted * @param string $filePath From f6ac34afea6c1f68f53e0e7a076b0b274559fd8b Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 22 Apr 2013 12:25:55 +0200 Subject: [PATCH 077/257] improved handling for getSharingUsersArray --- apps/files_encryption/lib/proxy.php | 2 +- apps/files_encryption/lib/stream.php | 10 +++------- apps/files_encryption/lib/util.php | 9 +++++++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 505fad440d..bc6280ff61 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -134,7 +134,7 @@ class Proxy extends \OC_FileProxy { $sharingEnabled = \OCP\Share::isEnabled(); - $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $filePath ); + $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $filePath, $userId ); // Fetch public keys for all users who will share the file $publicKeys = Keymanager::getPublicKeys( $rootView, $uniqueUserIds ); diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index c12fab783b..6fb95934c3 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -335,14 +335,10 @@ class Stream { $util = new Util( $this->rootView, $this->userId ); - // Get all users sharing the file - $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $this->relPath ); + // Get all users sharing the file includes current user + $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $this->relPath, $this->userId); - // allways add current user - $uniqueUserIds[] = $this->userId; - array_unique( $uniqueUserIds ); - - // Fetch public keys for all sharing users + // Fetch public keys for all sharing users $publicKeys = Keymanager::getPublicKeys( $this->rootView, $uniqueUserIds ); // Encrypt enc key for all sharing users diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index b3df7f0db0..e69314e099 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -848,7 +848,7 @@ class Util { * @brief Find, sanitise and format users sharing a file * @note This wraps other methods into a portable bundle */ - public function getSharingUsersArray( $sharingEnabled, $filePath ) { + public function getSharingUsersArray( $sharingEnabled, $filePath, $currentUserId = false ) { // Check if key recovery is enabled $recoveryEnabled = $this->recoveryEnabled(); @@ -878,7 +878,12 @@ class Util { $userIds[] = $adminUid; } - + + // add current user if given + if($currentUserId != false) { + $userIds[] = $currentUserId; + } + // Remove duplicate UIDs $uniqueUserIds = array_unique ( $userIds ); From 17059388482eabf6a1d05ea4c8d09e0f67ed9c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 22 Apr 2013 12:32:38 +0200 Subject: [PATCH 078/257] removed some leftover code; use already existing var for path to users file folder --- apps/files_encryption/lib/util.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index de63e0ff9f..d1377df9a9 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -895,8 +895,8 @@ class Util { */ public function getAllFiles($dir) { $result = array(); - $path = $this->view->getLocalFile(); - $content = $this->view->getDirectoryContent("/".$this->userFilesDir.'/'.$this->filesFolderName.$dir); + + $content = $this->view->getDirectoryContent($this->userFilesDir.$dir); foreach ($content as $c) { if ($c['type'] === "dir" ) { From b24a673714289bf515c93999a1dd0dfc552eb7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 22 Apr 2013 14:12:18 +0200 Subject: [PATCH 079/257] the owner uid is not interesting. We want to get all users who have access to the given item source, no matter from whom it was shared --- lib/public/share.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index acdf895c92..9fd8eb42fb 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -150,10 +150,10 @@ class Share { FROM `*PREFIX*share` WHERE - item_source = ? AND share_type = ? AND uid_owner = ?' + item_source = ? AND share_type = ?' ); - $result = $query->execute( array( $source, self::SHARE_TYPE_USER, $user ) ); + $result = $query->execute( array( $source, self::SHARE_TYPE_USER ) ); if ( \OC_DB::isError( $result ) ) { \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); @@ -170,10 +170,10 @@ class Share { FROM `*PREFIX*share` WHERE - item_source = ? AND share_type = ? AND uid_owner = ?' + item_source = ? AND share_type = ?' ); - $result = $query->execute( array( $source, self::SHARE_TYPE_GROUP, $user ) ); + $result = $query->execute( array( $source, self::SHARE_TYPE_GROUP ) ); if ( \OC_DB::isError( $result ) ) { \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); @@ -190,10 +190,10 @@ class Share { FROM `*PREFIX*share` WHERE - item_source = ? AND share_type = ? AND uid_owner = ?' + item_source = ? AND share_type = ?' ); - $result = $query->execute( array( $source, self::SHARE_TYPE_LINK, $user ) ); + $result = $query->execute( array( $source, self::SHARE_TYPE_LINK ) ); if ( \OC_DB::isError( $result ) ) { \OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result), \OC_Log::ERROR ); From bcb2e87846407959a1826b3c38d6956d180e3468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 22 Apr 2013 14:13:59 +0200 Subject: [PATCH 080/257] check if the item source was shared to me to decide if it is a re-share or not. Re-sharing of encrypted files should work now, we might still need to test some corner cases --- apps/files_encryption/hooks/hooks.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index e3861e7cc5..88ec64b492 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -193,8 +193,18 @@ class Hooks { $util = new Util($view, $userId); $path = $util->fileIdToPath($params['itemSource']); + //check if this is a reshare action, that's true if the item source is already shared with me + $sharedItem = \OCP\Share::getItemSharedWithBySource($params['itemType'], $params['itemSource']); + if ($sharedItem) { + // if it is a re-share than the file is located in my Shared folder + $path = '/Shared'.$sharedItem['file_target']; + } else { + $path = $util->fileIdToPath($params['itemSource']); + } + $sharingEnabled = \OCP\Share::isEnabled(); + // if a folder was shared, get a list if all (sub-)folders if ($params['itemType'] === 'folder') { $allFiles = $util->getAllFiles($path); } else { @@ -243,12 +253,14 @@ class Hooks { $util = new Util( $view, $userId ); $path = $util->fileIdToPath( $params['itemSource'] ); + // for group shares get a list of the group members if ($params['shareType'] == \OCP\Share::SHARE_TYPE_GROUP) { $userIds = \OC_Group::usersInGroup($params['shareWith']); } else { $userIds = array($params['shareWith']); } + // if we unshare a folder we need a list of all (sub-)files if ($params['itemType'] === 'folder') { $allFiles = $util->getAllFiles($path); } else { From b57478fa27a2dc2dcfeba68064e44aca5848e145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 22 Apr 2013 14:14:28 +0200 Subject: [PATCH 081/257] fix comment, remove unused variable --- apps/files_encryption/lib/util.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index d1377df9a9..1ba339c15d 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -805,15 +805,10 @@ class Util { // Make sure that a share key is generated for the owner too list($owner, $ownerPath) = $this->getUidAndFilename($filePath); - //$userIds = array( $this->userId ); - $userIds = array(); - if ( $sharingEnabled ) { // Find out who, if anyone, is sharing the file - $shareUids = \OCP\Share::getUsersSharingFile( $ownerPath, $owner,true, true, true ); - - $userIds = array_merge( $userIds, $shareUids ); + $userIds = \OCP\Share::getUsersSharingFile( $ownerPath, $owner,true, true, true ); } @@ -889,7 +884,7 @@ class Util { } /** - *@ brief geo recursively through a dir and collect all files and sub files. + * @brief geo recursively through a dir and collect all files and sub files. * @param type $dir relative to the users files folder * @return array with list of files relative to the users files folder */ From b5cb5dab513441b8c914aaa043921d0affae4604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 22 Apr 2013 14:30:10 +0200 Subject: [PATCH 082/257] fix encryption to owncloud user for public link shares --- apps/files_encryption/lib/keymanager.php | 2 +- apps/files_encryption/lib/util.php | 2 +- lib/public/share.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index f23423062b..6fb1f128b5 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -54,7 +54,7 @@ class Keymanager { \OC_FileProxy::$enabled = false; - return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' ); + return $view->file_get_contents( '/public-keys/' . $userId . '.public.key' ); \OC_FileProxy::$enabled = true; diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 1ba339c15d..143ba69f25 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -668,7 +668,7 @@ class Util { // public system user 'ownCloud' (for public shares) if ( $util->ready() - or $user == 'ownCloud' + or $user == 'owncloud' ) { // Construct array of ready UIDs for Keymanager{} diff --git a/lib/public/share.php b/lib/public/share.php index 9fd8eb42fb..5cd556c6ac 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -200,7 +200,7 @@ class Share { } if ($result->fetchRow()) { - $shares[] = "ownCloud"; + $shares[] = "owncloud"; } } // Include owner in list of users, if requested From a4364a93d0e80e0d1daa2b28713df05c25970fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 22 Apr 2013 15:29:58 +0200 Subject: [PATCH 083/257] delete all share keys if a file gets deleted --- apps/files_encryption/lib/keymanager.php | 21 ++++++++++++++++++++- apps/files_encryption/lib/proxy.php | 11 +++-------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 6fb1f128b5..9885f5e550 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -391,7 +391,26 @@ class Keymanager { return $result; } - + + /** + * @brief delete all share keys of a given file + * @param \OC_FilesystemView $view + * @param type $userId owner of the file + * @param type $filePath path to the file, relative to the owners file dir + */ + public static function delAllShareKeys(\OC_FilesystemView $view, $userId, $filePath) { + + if ($view->is_dir($userId.'/files/'.$filePath)) { + $view->unlink($userId.'/files_encryption/share-keys/'.$filePath); + } else { + $localKeyPath = $view->getLocalFile($userId.'/files_encryption/share-keys/'.$filePath); + $matches = glob(preg_quote($localKeyPath).'*.shareKey'); + foreach ($matches as $ma) { + unlink($ma); + } + } + } + /** * @brief Delete a single user's shareKey for a single file */ diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 505fad440d..bd25465ee6 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -256,18 +256,13 @@ class Proxy extends \OC_FileProxy { // Format path to be relative to user files dir $relPath = $util->stripUserFilesPath( $path ); -// list( $owner, $ownerPath ) = $util->getUidAndFilename( $relPath ); - - $fileOwner = \OC\Files\Filesystem::getOwner( $path ); - $ownerPath = $util->stripUserFilesPath( $path ); // TODO: Don't trust $path, fetch owner path - - $filePath = $fileOwner . '/' . 'files_encryption' . '/' . 'keyfiles' . '/'. $ownerPath; + list( $owner, $ownerPath ) = $util->getUidAndFilename( $relPath ); // Delete keyfile & shareKey so it isn't orphaned if ( ! ( - Keymanager::deleteFileKey( $view, $fileOwner, $ownerPath ) - && Keymanager::delShareKey( $view, $fileOwner, $ownerPath ) + Keymanager::deleteFileKey( $view, $owner, $ownerPath ) + && Keymanager::delAllShareKeys( $view, $owner, $ownerPath ) ) ) { From 37c72059417d2f2f776ee4318e3705adf6c54fe7 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 22 Apr 2013 18:50:59 +0200 Subject: [PATCH 084/257] fix wrong file path in util --- apps/files_encryption/lib/util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 9868aba02e..6e8786b7cd 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -337,7 +337,7 @@ class Util { // scanning every file like this // will eat server resources :( if ( - Keymanager::getFileKey( $this->view, $this->userId, $file ) + Keymanager::getFileKey( $this->view, $this->userId, $relPath ) && Crypt::isCatfileContent( $data ) ) { From 8ab9433fdff179649a5e5b9d6046d85efd81d3b8 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 22 Apr 2013 18:54:23 +0200 Subject: [PATCH 085/257] fix wrong file path in proxy --- apps/files_encryption/lib/proxy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 1a96f1e495..e058a528ad 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -266,7 +266,7 @@ class Proxy extends \OC_FileProxy { ) ) { - \OC_Log::write( 'Encryption library', 'Keyfile or shareKey could not be deleted for file "'.$filePath.'"', \OC_Log::ERROR ); + \OC_Log::write( 'Encryption library', 'Keyfile or shareKey could not be deleted for file "'.$ownerPath.'"', \OC_Log::ERROR ); } From a1d241783ee44529fac99ba25cb34b658f827876 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 23 Apr 2013 14:12:28 +0200 Subject: [PATCH 086/257] Updated buglist --- apps/files_encryption/lib/util.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 1b69ad320c..f7bb51a861 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -24,20 +24,16 @@ # Bugs # ---- # Sharing a file to a user without encryption set up will not provide them with access but won't notify the sharer -# Sharing files to other users currently broken (due to merge + ongoing implementation of support for lost password recovery) # Timeouts on first login due to encryption of very large files (fix in progress, as a result streaming is currently broken) # Sharing all files to admin for recovery purposes still in progress # Possibly public links are broken (not tested since last merge of master) -# getOwner() currently returns false in all circumstances, unsure what code is returning this... # encryptAll during login mangles paths: /files/files/ # encryptAll is accessing files via encryption proxy - perhaps proxies should be disabled? -# Sharekeys appear to not be deleted when their parent file is, and thus get orphaned # Missing features # ---------------- # Make sure user knows if large files weren't encrypted -# Support for resharing encrypted files # Test From c6bfc7315b380710d7c59f7bb23588822063dc6f Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 23 Apr 2013 17:36:35 +0200 Subject: [PATCH 087/257] Stream writing improved: working with dolphin + kate, gedit & nautilus give errors, suspect those issues are clientside .part file paths fixed in stream{} --- apps/files_encryption/lib/proxy.php | 5 ----- apps/files_encryption/lib/stream.php | 22 ++++++---------------- apps/files_encryption/lib/util.php | 2 +- 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index e058a528ad..0d20ff1af1 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -118,9 +118,6 @@ class Proxy extends \OC_FileProxy { // Decrypt the keyfile $plainKey = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); - -// trigger_error("\$shareKey = $shareKey"); -// trigger_error("\$plainKey = $plainKey"); } else { @@ -207,8 +204,6 @@ class Proxy extends \OC_FileProxy { $plainKeyfile = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); $plainData = Crypt::symmetricDecryptFileContent( $data, $plainKeyfile ); - -// trigger_error("PLAINDATA = ". var_export($plainData, 1)); } elseif ( Crypt::mode() == 'server' diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 6fb95934c3..9a37c3b08e 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -86,6 +86,9 @@ class Stream { // rawPath is relative to the data directory $this->rawPath = $this->userId . '/files/' . $this->relPath; + // Fix .part filenames + $this->rawPath = Keymanager::fixPartialFilePath( $this->rawPath ); + if ( dirname( $this->rawPath ) == 'streams' and isset( self::$sourceStreams[basename( $this->rawPath )] ) @@ -257,11 +260,6 @@ class Stream { $this->plainKey = Crypt::multiKeyDecrypt( $this->encKeyfile, $shareKey, $privateKey ); -// trigger_error( '$this->relPath = '.$this->relPath ); -// trigger_error( '$this->userId = '.$this->userId); -// trigger_error( '$this->encKeyfile = '.$this->encKeyfile ); -// trigger_error( '$this->plainKey1 = '.var_export($this->plainKey, 1)); - return true; } else { @@ -352,12 +350,6 @@ class Stream { // Save the sharekeys Keymanager::setShareKeys( $view, $this->relPath, $this->encKeyfiles['keys'] ); -// trigger_error( "\$this->encKeyfiles['data'] = ".$this->encKeyfiles['data'] ); -// trigger_error( '$this->relPath = '.$this->relPath ); -// trigger_error( '$this->userId = '.$this->userId); -// trigger_error( '$this->encKeyfile = '.var_export($this->encKeyfiles, 1) ); -// trigger_error( '$this->plainKey2 = '.var_export($this->plainKey, 1)); - // If extra data is left over from the last round, make sure it // is integrated into the next 6126 / 8192 block if ( $this->writeCache ) { @@ -420,7 +412,7 @@ class Stream { // Clear $data ready for next round $data = ''; -// + } else { // Read the chunk from the start of $data @@ -428,8 +420,6 @@ class Stream { $encrypted = $this->preWriteEncrypt( $chunk, $this->plainKey ); - //trigger_error("\$encrypted = $encrypted"); - // Write the data chunk to disk. This will be // attended to the last data chunk if the file // being handled totals more than 6126 bytes @@ -515,9 +505,9 @@ class Stream { \OC\Files\Filesystem::putFileInfo( $this->relPath, array( 'encrypted' => true, 'size' => $this->size ), '' ); } - - return fclose( $this->handle ); + return fclose( $this->handle ); + } } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index f7bb51a861..38b4219f6e 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -492,7 +492,7 @@ class Util { * @note Encryption is recursive */ public function encryptAll( $publicKey, $dirPath, $legacyPassphrase = null, $newPassphrase = null ) { - + if ( $found = $this->findEncFiles( $dirPath ) ) { // Disable proxy to prevent file being encrypted twice From b7d8da87d0b094c5e55a0ac43995074fa3351618 Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 23 Apr 2013 18:41:01 +0200 Subject: [PATCH 088/257] Development snapshot working on stream handling (large files) in Util->encryptAll() --- apps/files_encryption/lib/keymanager.php | 3 +- apps/files_encryption/lib/proxy.php | 1 - apps/files_encryption/lib/util.php | 50 ++++++++++++------------ 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 9885f5e550..0e1dafeed7 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -106,6 +106,7 @@ class Keymanager { */ public static function setFileKey( \OC_FilesystemView $view, $path, $userId, $catfile ) { + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; //here we need the currently logged in user, while userId can be a different user @@ -129,7 +130,7 @@ class Keymanager { $result = $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile ); - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; return $result; diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 0d20ff1af1..620f7cc8c3 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -142,7 +142,6 @@ class Proxy extends \OC_FileProxy { $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys ); // Save sharekeys to user folders - Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] ); // Set encrypted keyfile as common varname diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 38b4219f6e..f9198e0606 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -500,37 +500,39 @@ class Util { // Encrypt unencrypted files foreach ( $found['plain'] as $plainFile ) { - - // Open plain file handle - - - // Open enc file handle - - - // Read plain file in chunks //relative to data//file $relPath = $plainFile['path']; + //relative to /data $rawPath = $this->userId . '/files/' . $plainFile['path']; - - // Open handle with for binary reading - $plainHandle = $this->view->fopen( $rawPath, 'rb' ); - // Open handle with for binary writing - - $encHandle = fopen( 'crypt://' . $relPath . '.tmp', 'wb' ); - // Overwrite the existing file with the encrypted one - //$this->view->file_put_contents( $plainFile['path'], $encrypted['data'] ); - $size = stream_copy_to_stream( $plainHandle, $encHandle ); - - $this->view->rename($rawPath . '.tmp', $rawPath); - - // Fetch the key that has just been set/updated by the stream - //$encKey = Keymanager::getFileKey( $this->view, $this->userId, $relPath ); + // Open plain file handle for binary reading + $plainHandle1 = $this->view->fopen( $rawPath, 'rb' ); - // Save keyfile - //Keymanager::setFileKey( $this->view, $relPath, $this->userId, $encKey ); + // 2nd handle for moving plain file - view->rename() doesn't work, this is a workaround + $plainHandle2 = $this->view->fopen( $rawPath . '.plaintmp', 'wb' ); + + // Move plain file to a temporary location + stream_copy_to_stream( $plainHandle1, $plainHandle2 ); + + // Close access to original file +// $this->view->fclose( $plainHandle1 ); // not implemented in view{} + + // Delete original plain file so we can rename enc file later + $this->view->unlink( $rawPath ); + + // Open enc file handle for binary writing, with same filename as original plain file + $encHandle = fopen( 'crypt://' . $relPath, 'wb' ); + + // Save data from plain stream to new encrypted file via enc stream + // NOTE: Stream{} will be invoked for handling + // the encryption, and should handle all keys + // and their generation etc. automatically + $size = stream_copy_to_stream( $plainHandle2, $encHandle ); + + // Delete temporary plain copy of file + $this->view->unlink( $rawPath . '.plaintmp' ); // Add the file to the cache \OC\Files\Filesystem::putFileInfo( $plainFile['path'], array( 'encrypted'=>true, 'size' => $size ), '' ); From baa6fd639fb9e6b2a954975603428603fcd04a85 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Tue, 23 Apr 2013 19:08:52 +0200 Subject: [PATCH 089/257] improved file size handling --- apps/files_encryption/lib/proxy.php | 92 +++++++++++++++++++---------- 1 file changed, 60 insertions(+), 32 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index e058a528ad..cb7cb8a2cc 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -91,14 +91,14 @@ class Proxy extends \OC_FileProxy { return false; } - public function preFile_put_contents( $path, &$data ) { - - if ( self::shouldEncrypt( $path ) ) { - - // Stream put contents should have been converted to fopen + public function preFile_put_contents( $path, &$data ) { + + if ( self::shouldEncrypt( $path ) ) { + + // Stream put contents should have been converted to fopen if ( !is_resource( $data ) ) { - - $userId = \OCP\USER::getUser(); + + $userId = \OCP\USER::getUser(); $rootView = new \OC_FilesystemView( '/' ); $util = new Util( $rootView, $userId ); $session = new Session( $rootView ); @@ -135,8 +135,8 @@ class Proxy extends \OC_FileProxy { $sharingEnabled = \OCP\Share::isEnabled(); $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $filePath, $userId ); - - // Fetch public keys for all users who will share the file + + // Fetch public keys for all users who will share the file $publicKeys = Keymanager::getPublicKeys( $rootView, $uniqueUserIds ); \OC_FileProxy::$enabled = false; @@ -165,7 +165,8 @@ class Proxy extends \OC_FileProxy { } } - + + return true; } /** @@ -174,7 +175,7 @@ class Proxy extends \OC_FileProxy { */ public function postFile_get_contents( $path, $data ) { - // FIXME: $path for shared files is just /uid/files/Shared/filepath + // FIXME: $path for shared files is just /uid/files/Shared/filepath $userId = \OCP\USER::getUser(); $view = new \OC_FilesystemView( '/' ); @@ -300,7 +301,6 @@ class Proxy extends \OC_FileProxy { $oldRelPath = implode('/', $oldSliced); $oldKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $oldRelPath; - $newTrimmed = ltrim($newPath, '/'); $newSplit = explode('/', $newTrimmed); $newSliced = array_slice($newSplit, 2); @@ -331,14 +331,14 @@ class Proxy extends \OC_FileProxy { } public function postFopen( $path, &$result ){ - - if ( !$result ) { + + if ( !$result ) { return $result; } - - // Reformat path for use with OC_FSV + + // Reformat path for use with OC_FSV $path_split = explode( '/', $path ); $path_f = implode( '/', array_slice( $path_split, 3 ) ); @@ -394,8 +394,8 @@ class Proxy extends \OC_FileProxy { // fclose( $tmp ); } - - $result = fopen( 'crypt://'.$path_f, $meta['mode'] ); + + $result = fopen( 'crypt://'.$path_f, $meta['mode'] ); } @@ -407,8 +407,8 @@ class Proxy extends \OC_FileProxy { } public function postGetMimeType( $path, $mime ) { - - if ( Crypt::isCatfileContent( $path ) ) { + + if ( Crypt::isCatfileContent( $path ) ) { $mime = \OCP\Files::getMimeType( 'crypt://' . $path, 'w' ); @@ -418,9 +418,28 @@ class Proxy extends \OC_FileProxy { } + public function postGetFileInfo( $path, $data ) { + + // if path is a folder do nothing + if(is_array($data) && array_key_exists('size', $data)) { + // Disable encryption proxy to prevent recursive calls + \OC_FileProxy::$enabled = false; + + // get file size + $data['size'] = self::postFileSize($path, $data['size']); + + // Re-enable the proxy + \OC_FileProxy::$enabled = true; + + trigger_error('postGetFileInfo '.$path.' size: '.$data['size']); + } + + return $data; + } + public function postStat( $path, $data ) { - - if ( Crypt::isCatfileContent( $path ) ) { + + if ( Crypt::isCatfileContent( $path ) ) { $cached = \OC\Files\Filesystem::getFileInfo( $path, '' ); @@ -433,29 +452,38 @@ class Proxy extends \OC_FileProxy { public function postFileSize( $path, $size ) { + $view = new \OC_FilesystemView( '/' ); + + // if path is a folder do nothing + if($view->is_dir($path)) { + return $size; + } + // Reformat path for use with OC_FSV $path_split = explode('/', $path); $path_f = implode('/', array_slice($path_split, 3)); - $view = new \OC_FilesystemView( '/' ); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); - if ($util->isEncryptedPath($path)) { + + // FIXME: is there a better solution to check if file belongs to files path? + // only get file size if file is in 'files' path + if (count($path_split) >= 2 && $path_split[2] == 'files' && $util->isEncryptedPath($path)) { // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; - // get file info - $cached = \OC\Files\Filesystem::getFileInfo($path_f, ''); - - // calculate last chunk nr - $lastChunckNr = floor($size / 8192); - // open stream $result = fopen('crypt://' . $path_f, "r"); if(is_resource($result)) { + // don't trust the given size, allways get the size from filesystem + $size = $view->filesize($path); + + // calculate last chunk nr + $lastChunckNr = floor($size / 8192); + // calculate last chunk position $lastChunckPos = ($lastChunckNr * 8192); @@ -469,13 +497,13 @@ class Proxy extends \OC_FileProxy { $realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent)); // set the size - $cached['size'] = $realSize; + $size = $realSize; } // enable proxy \OC_FileProxy::$enabled = true; - return $cached['size']; + return $size; } else { From 25ff32db6bec0992b0fac18b04345aa5e99f4ea1 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Tue, 23 Apr 2013 22:20:31 +0200 Subject: [PATCH 090/257] Added post proxy for getFileInfo. This is needed for WebDAV and FileSize @samtuke and @schiesbn you guys know a better solution? --- lib/files/view.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/files/view.php b/lib/files/view.php index f607bb59aa..bd4812f8f8 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -724,6 +724,9 @@ class View { $data['permissions'] = $permissions; } } + + $data = \OC_FileProxy::runPostProxies('getFileInfo', $path, $data); + return $data; } From 170d09203f376fad452fc6959729a0f778b5934f Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 25 Apr 2013 14:56:11 +0200 Subject: [PATCH 091/257] fixed file_proxy handling --- apps/files_encryption/lib/keymanager.php | 52 +++++++++++++++--------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 0e1dafeed7..ceefe8887a 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -51,12 +51,15 @@ class Keymanager { * @return string public key or false */ public static function getPublicKey( \OC_FilesystemView $view, $userId ) { - + + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; - return $view->file_get_contents( '/public-keys/' . $userId . '.public.key' ); + $result = $view->file_get_contents( '/public-keys/' . $userId . '.public.key' ); - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; + + return $result; } @@ -175,7 +178,8 @@ class Keymanager { $filePath_f = ltrim( $filename, '/' ); $keyfilePath = '/' . $owner . '/files_encryption/keyfiles/' . $filePath_f . '.key'; - + + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; if ( $view->file_exists( $keyfilePath ) ) { @@ -188,7 +192,7 @@ class Keymanager { } - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; return $result; @@ -243,15 +247,17 @@ class Keymanager { $user = \OCP\User::getUser(); $view = new \OC_FilesystemView( '/' . $user . '/files_encryption' ); - + + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; if ( !$view->file_exists( '' ) ) $view->mkdir( '' ); - return $view->file_put_contents( $user . '.private.key', $key ); - - \OC_FileProxy::$enabled = true; + $result = $view->file_put_contents( $user . '.private.key', $key ); + \OC_FileProxy::$enabled = $proxyStatus; + + return $result; } /** @@ -276,14 +282,17 @@ class Keymanager { public static function setPublicKey( $key ) { $view = new \OC_FilesystemView( '/public-keys' ); - + + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; if ( !$view->file_exists( '' ) ) $view->mkdir( '' ); - return $view->file_put_contents( \OCP\User::getUser() . '.public.key', $key ); + $result = $view->file_put_contents( \OCP\User::getUser() . '.public.key', $key ); - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; + + return $result; } @@ -310,11 +319,14 @@ class Keymanager { $shareKeyPath = self::keySetPreparation( $view, $filename, $basePath, $owner ); $writePath = $basePath . '/' . $shareKeyPath . '.' . $userId . '.shareKey'; - + + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $result = $view->file_put_contents( $writePath, $shareKey ); - + + \OC_FileProxy::$enabled = $proxyStatus; + if ( is_int( $result ) && $result > 0 @@ -368,7 +380,8 @@ class Keymanager { * of the keyfile must be performed by client code */ public static function getShareKey( \OC_FilesystemView $view, $userId, $filePath ) { - + + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; //here we need the currently logged in user, while userId can be a different user @@ -387,7 +400,7 @@ class Keymanager { } - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; return $result; @@ -416,7 +429,8 @@ class Keymanager { * @brief Delete a single user's shareKey for a single file */ public static function delShareKey( \OC_FilesystemView $view, $userIds, $filePath ) { - + + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; //here we need the currently logged in user, while userId can be a different user @@ -448,7 +462,7 @@ class Keymanager { } - \OC_FileProxy::$enabled = false; + \OC_FileProxy::$enabled = $proxyStatus; return $result; @@ -472,7 +486,7 @@ class Keymanager { foreach ( $subdirs as $subdir ) { self::recursiveDelShareKeys($subdir, $userIds); } - return $true; + return true; } /** From fac288a4ad8f6db907c0a2ddfeb0b772fe616db5 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 25 Apr 2013 15:20:06 +0200 Subject: [PATCH 092/257] added unencrypted file size to file cache improved file size calculation and speeds --- apps/files_encryption/lib/proxy.php | 113 ++++++++++----------------- apps/files_encryption/lib/stream.php | 14 ++-- db_structure.xml | 8 ++ lib/files/cache/cache.php | 11 +-- 4 files changed, 62 insertions(+), 84 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index b805ec648d..c07b9a8a7a 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -108,7 +108,8 @@ class Proxy extends \OC_FileProxy { $size = strlen( $data ); // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; // Check if there is an existing key we can reuse if ( $encKeyfile = Keymanager::getFileKey( $rootView, $userId, $filePath ) ) { @@ -135,10 +136,8 @@ class Proxy extends \OC_FileProxy { // Fetch public keys for all users who will share the file $publicKeys = Keymanager::getPublicKeys( $rootView, $uniqueUserIds ); - - \OC_FileProxy::$enabled = false; - - // Encrypt plain keyfile to multiple sharefiles + + // Encrypt plain keyfile to multiple sharefiles $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys ); // Save sharekeys to user folders @@ -157,7 +156,7 @@ class Proxy extends \OC_FileProxy { \OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' ); // Re-enable proxy - our work is done - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; } } @@ -182,9 +181,10 @@ class Proxy extends \OC_FileProxy { // TODO check for existing key file and reuse it if possible to avoid problems with versioning etc. // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; - - // If data is a catfile + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + // If data is a catfile if ( Crypt::mode() == 'server' && Crypt::isCatfileContent( $data ) // TODO: Do we really need this check? Can't we assume it is properly encrypted? @@ -215,7 +215,7 @@ class Proxy extends \OC_FileProxy { } - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; if ( ! isset( $plainData ) ) { @@ -240,7 +240,8 @@ class Proxy extends \OC_FileProxy { $path = Keymanager::fixPartialFilePath( $path ); // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; $view = new \OC_FilesystemView( '/' ); @@ -265,7 +266,7 @@ class Proxy extends \OC_FileProxy { } - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; // If we don't return true then file delete will fail; better // to leave orphaned keyfiles than to disallow file deletion @@ -282,6 +283,7 @@ class Proxy extends \OC_FileProxy { { // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $view = new \OC_FilesystemView('/'); @@ -318,7 +320,7 @@ class Proxy extends \OC_FileProxy { // Rename keyfile so it isn't orphaned $result = $view->rename($oldKeyfilePath, $newKeyfilePath); - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; return $result; @@ -337,9 +339,10 @@ class Proxy extends \OC_FileProxy { $path_f = implode( '/', array_slice( $path_split, 3 ) ); // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; - - $meta = stream_get_meta_data( $result ); + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + $meta = stream_get_meta_data( $result ); $view = new \OC_FilesystemView( '' ); @@ -369,13 +372,13 @@ class Proxy extends \OC_FileProxy { // NOTE: this is the case for new files saved via WebDAV - if ( - $view->file_exists( $path ) - and $view->filesize( $path ) > 0 - ) { - $x = $view->file_get_contents( $path ); - - $tmp = tmpfile(); +// if ( +// $view->file_exists( $path ) +// and $view->filesize( $path ) > 0 +// ) { +// $x = $view->file_get_contents( $path ); +// +// $tmp = tmpfile(); // // Make a temporary copy of the original file // \OCP\Files::streamCopy( $result, $tmp ); @@ -387,14 +390,14 @@ class Proxy extends \OC_FileProxy { // // fclose( $tmp ); - } +// } $result = fopen( 'crypt://'.$path_f, $meta['mode'] ); } // Re-enable the proxy - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; return $result; @@ -417,15 +420,15 @@ class Proxy extends \OC_FileProxy { // if path is a folder do nothing if(is_array($data) && array_key_exists('size', $data)) { // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; + // get file size $data['size'] = self::postFileSize($path, $data['size']); // Re-enable the proxy - \OC_FileProxy::$enabled = true; - - trigger_error('postGetFileInfo '.$path.' size: '.$data['size']); + \OC_FileProxy::$enabled = $proxyStatus; } return $data; @@ -437,7 +440,7 @@ class Proxy extends \OC_FileProxy { $cached = \OC\Files\Filesystem::getFileInfo( $path, '' ); - $data['size'] = $cached['size']; + $data['size'] = $cached['unencrypted_size']; } @@ -453,56 +456,20 @@ class Proxy extends \OC_FileProxy { return $size; } + $path = Keymanager::fixPartialFilePath( $path ); + // Reformat path for use with OC_FSV $path_split = explode('/', $path); $path_f = implode('/', array_slice($path_split, 3)); - $userId = \OCP\User::getUser(); - $util = new Util( $view, $userId ); - - - // FIXME: is there a better solution to check if file belongs to files path? - // only get file size if file is in 'files' path - if (count($path_split) >= 2 && $path_split[2] == 'files' && $util->isEncryptedPath($path)) { - - // Disable encryption proxy to prevent recursive calls - \OC_FileProxy::$enabled = false; - - // open stream - $result = fopen('crypt://' . $path_f, "r"); - - if(is_resource($result)) { - // don't trust the given size, allways get the size from filesystem - $size = $view->filesize($path); - - // calculate last chunk nr - $lastChunckNr = floor($size / 8192); - - // calculate last chunk position - $lastChunckPos = ($lastChunckNr * 8192); - - // seek to end - fseek($result, $lastChunckPos); - - // get the content of the last chunck - $lastChunkContent = fgets($result); - - // calc the real file size with the size of the last chunk - $realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent)); - - // set the size - $size = $realSize; - } - - // enable proxy - \OC_FileProxy::$enabled = true; - - return $size; + // get file info from database/cache + $fileInfo = \OC\Files\Filesystem::getFileInfo($path_f); + // if file is encrypted return real file size + if(is_array($fileInfo) && $fileInfo['encrypted'] == 1) { + return $fileInfo['unencrypted_size']; } else { - - return $size; - + return $fileInfo['size']; } } } diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 9a37c3b08e..7e42627f8c 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -64,6 +64,7 @@ class Stream { private $count; private $writeCache; public $size; + public $unencryptedSize; private $publicKey; private $keyfile; private $encKeyfile; @@ -105,6 +106,7 @@ class Stream { } else { // Disable fileproxies so we can get the file size and open the source file without recursive encryption + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; if ( @@ -116,6 +118,7 @@ class Stream { // We're writing a new file so start write counter with 0 bytes $this->size = 0; + $this->unencryptedSize = 0; } else { @@ -129,7 +132,7 @@ class Stream { $this->handle = $this->rootView->fopen( $this->rawPath, $mode ); - \OC_FileProxy::$enabled = true; + \OC_FileProxy::$enabled = $proxyStatus; if ( ! is_resource( $this->handle ) ) { @@ -301,7 +304,7 @@ class Stream { // automatically attempted when the file is written to disk - // we are handling that separately here and we don't want to // get into an infinite loop - \OC_FileProxy::$enabled = false; + //\OC_FileProxy::$enabled = false; // Get the length of the unencrypted data that we are handling $length = strlen( $data ); @@ -438,7 +441,8 @@ class Stream { } $this->size = max( $this->size, $pointer + $length ); - + $this->unencryptedSize += $length; + return $length; } @@ -501,9 +505,7 @@ class Stream { $this->meta['mode']!='r' and $this->meta['mode']!='rb' ) { - - \OC\Files\Filesystem::putFileInfo( $this->relPath, array( 'encrypted' => true, 'size' => $this->size ), '' ); - + \OC\Files\Filesystem::putFileInfo( $this->relPath, array( 'encrypted' => 1, 'size' => $this->size, 'unencrypted_size' => $this->unencryptedSize ), '' ); } return fclose( $this->handle ); diff --git a/db_structure.xml b/db_structure.xml index dce90697b1..366f51a82d 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -288,6 +288,14 @@ 4 + + unencrypted_size + integer + + true + 8 + + etag text diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 71b70abe3f..4e32ff2ba8 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -117,7 +117,7 @@ class Cache { $params = array($file); } $query = \OC_DB::prepare( - 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` ' . $where); $result = $query->execute($params); $data = $result->fetchRow(); @@ -133,6 +133,7 @@ class Cache { $data['size'] = (int)$data['size']; $data['mtime'] = (int)$data['mtime']; $data['encrypted'] = (bool)$data['encrypted']; + $data['unencrypted_size'] = (int)$data['unencrypted_size']; $data['storage'] = $this->storageId; $data['mimetype'] = $this->getMimetype($data['mimetype']); $data['mimepart'] = $this->getMimetype($data['mimepart']); @@ -151,7 +152,7 @@ class Cache { $fileId = $this->getId($folder); if ($fileId > -1) { $query = \OC_DB::prepare( - 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `name` ASC'); $result = $query->execute(array($fileId)); $files = $result->fetchAll(); @@ -234,7 +235,7 @@ class Cache { * @return array */ function buildParts(array $data) { - $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted', 'etag'); + $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted', 'unencrypted_size', 'etag'); $params = array(); $queryParts = array(); foreach ($data as $name => $value) { @@ -391,7 +392,7 @@ class Cache { */ public function search($pattern) { $query = \OC_DB::prepare(' - SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` WHERE `name` LIKE ? AND `storage` = ?' ); $result = $query->execute(array($pattern, $this->numericId)); @@ -417,7 +418,7 @@ class Cache { $where = '`mimepart` = ?'; } $query = \OC_DB::prepare(' - SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag` FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?' ); $mimetype = $this->getMimetypeId($mimetype); From 11d0eef8ccbbfaf7dee6fa4a58b9778c16bec895 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 25 Apr 2013 15:21:11 +0200 Subject: [PATCH 093/257] fixed webdav errors, now webdav up - and downloads are full working --- apps/files_encryption/hooks/hooks.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 88ec64b492..2ac74ad6c4 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -40,7 +40,8 @@ class Hooks { // Manually initialise Filesystem{} singleton with correct // fake root path, in order to avoid fatal webdav errors - \OC\Files\Filesystem::init( $params['uid'], '/' . 'files' . '/' ); + // NOTE: disabled because this give errors on webdav! + //\OC\Files\Filesystem::init( $params['uid'], '/' . 'files' . '/' ); $view = new \OC_FilesystemView( '/' ); @@ -66,8 +67,10 @@ class Hooks { $session = new Session( $view ); $session->setPrivateKey( $privateKey, $params['uid'] ); - - $view1 = new \OC_FilesystemView( '/' . $params['uid'] ); + + //FIXME: disabled because it gets called each time a user do an operation on iPhone + //FIXME: we need a better place doing this and maybe only one time or by user + /*$view1 = new \OC_FilesystemView( '/' . $params['uid'] ); // Set legacy encryption key if it exists, to support // depreciated encryption system @@ -86,12 +89,12 @@ class Hooks { $publicKey = Keymanager::getPublicKey( $view, $params['uid'] ); - \OC_FileProxy::$enabled = false; + \OC_FileProxy::$enabled = false;*/ // Encrypt existing user files: // This serves to upgrade old versions of the encryption // app (see appinfo/spec.txt) - if ( + /*if ( $util->encryptAll( $publicKey, '/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password'] ) ) { @@ -100,7 +103,7 @@ class Hooks { , \OC_Log::INFO ); - } + }*/ return true; From 328dea93c7a4a68bfb83c15f97af64275c953782 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 25 Apr 2013 20:23:54 +0200 Subject: [PATCH 094/257] webdav fix for file chunking upload with big files should now work @samtuke and @schiesbn we need a solution for the cache files created by webdav --- apps/files_encryption/lib/proxy.php | 7 ++++++- apps/files_encryption/lib/util.php | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index c07b9a8a7a..66ea282312 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -337,7 +337,12 @@ class Proxy extends \OC_FileProxy { // Reformat path for use with OC_FSV $path_split = explode( '/', $path ); $path_f = implode( '/', array_slice( $path_split, 3 ) ); - + + // FIXME: handling for /userId/cache used by webdav for chunking. The cache chunks are NOT encrypted + if($path_split[2] == 'cache') { + return $result; + } + // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index f9198e0606..2198963ce1 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -880,7 +880,7 @@ class Util { } else { - throw new \Exception( 'Supplied path could not be resolved "' . $path . '"' ); + return false; } From 672d177f10e44581ecc9f37844681afaa06c0272 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 25 Apr 2013 22:43:15 +0200 Subject: [PATCH 095/257] added post rename proxy --- lib/files/view.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/files/view.php b/lib/files/view.php index bd4812f8f8..d0fc5910e6 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -362,6 +362,7 @@ class View { list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); if ($storage) { $result = $storage->rename($internalPath1, $internalPath2); + \OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2); } else { $result = false; } From 8ee7959092d8363f35de49819b44b6b8fe19bc34 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 25 Apr 2013 22:49:47 +0200 Subject: [PATCH 096/257] implement postRename @samtuke no need anymore for fixPartialFilePath this is now handled by rename share-keys are now handled properly webdav .part files are handled properly --- apps/files_encryption/lib/keymanager.php | 22 ------- apps/files_encryption/lib/proxy.php | 84 +++++++++++++++++++++--- apps/files_encryption/lib/stream.php | 10 +-- 3 files changed, 77 insertions(+), 39 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index ceefe8887a..cfc13ee132 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -139,28 +139,6 @@ class Keymanager { } - /** - * @brief Remove .path extension from a file path - * @param string $path Path that may identify a .part file - * @return string File path without .part extension - */ - public static function fixPartialFilePath( $path ) { - - if ( preg_match( '/\.part$/', $path ) ) { - - $newLength = strlen( $path ) - 5; - $fPath = substr( $path, 0, $newLength ); - - return $fPath; - - } else { - - return $path; - - } - - } - /** * @brief retrieve keyfile for an encrypted file * @param \OC_FilesystemView $view diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 66ea282312..7294c24366 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -237,8 +237,6 @@ class Proxy extends \OC_FileProxy { return true; } - $path = Keymanager::fixPartialFilePath( $path ); - // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; @@ -307,6 +305,15 @@ class Proxy extends \OC_FileProxy { if (!$view->is_dir($oldKeyfilePath)) { $oldKeyfilePath .= '.key'; $newKeyfilePath .= '.key'; + + // handle share-keys + $localKeyPath = $view->getLocalFile($userId.'/files_encryption/share-keys/'.$oldRelPath); + $matches = glob(preg_quote($localKeyPath).'*.shareKey'); + foreach ($matches as $src) { + $dst = str_replace($oldRelPath, $newRelPath, $src); + rename($src, $dst); + } + } else { // handle share-keys folders $oldShareKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $oldRelPath; @@ -314,9 +321,6 @@ class Proxy extends \OC_FileProxy { $view->rename($oldShareKeyfilePath, $newShareKeyfilePath); } - //TODO add support for share-keys files - //... - // Rename keyfile so it isn't orphaned $result = $view->rename($oldKeyfilePath, $newKeyfilePath); @@ -326,6 +330,70 @@ class Proxy extends \OC_FileProxy { } + /** + * @brief When a file is renamed, rename its keyfile also + * @return bool Result of rename() + * @note This is pre rather than post because using post didn't work + */ + public function postRename( $oldPath, $newPath ) + { + + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + $view = new \OC_FilesystemView('/'); + $userId = \OCP\User::getUser(); + $util = new Util( $view, $userId ); + + // Reformat path for use with OC_FSV + $newPathSplit = explode( '/', $newPath ); + $newPathRelative = implode( '/', array_slice( $newPathSplit, 3 ) ); + $newPathRelativeToUser = implode( '/', array_slice( $newPathSplit, 2 ) ); + + // get file info from database/cache + //$newFileInfo = \OC\Files\Filesystem::getFileInfo($newPathRelative); + + if ($util->isEncryptedPath($newPath)) { + $cached = $view->getFileInfo($newPath); + $cached['encrypted'] = 1; + + // get the size from filesystem + $size = $view->filesize($newPath); + + // calculate last chunk nr + $lastChunckNr = floor($size / 8192); + + // open stream + $result = fopen('crypt://' . $newPathRelative, "r"); + + if(is_resource($result)) { + // calculate last chunk position + $lastChunckPos = ($lastChunckNr * 8192); + + // seek to end + fseek($result, $lastChunckPos); + + // get the content of the last chunck + $lastChunkContent = fread($result, 8192); + + // calc the real file size with the size of the last chunk + $realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent)); + + // set the size + $cached['unencrypted_size'] = $realSize; + } + + $view->putFileInfo( $newPath, $cached ); + + } + + \OC_FileProxy::$enabled = $proxyStatus; + + return true; + + } + public function postFopen( $path, &$result ){ if ( !$result ) { @@ -424,11 +492,11 @@ class Proxy extends \OC_FileProxy { // if path is a folder do nothing if(is_array($data) && array_key_exists('size', $data)) { + // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; - // get file size $data['size'] = self::postFileSize($path, $data['size']); @@ -461,8 +529,6 @@ class Proxy extends \OC_FileProxy { return $size; } - $path = Keymanager::fixPartialFilePath( $path ); - // Reformat path for use with OC_FSV $path_split = explode('/', $path); $path_f = implode('/', array_slice($path_split, 3)); @@ -474,7 +540,7 @@ class Proxy extends \OC_FileProxy { if(is_array($fileInfo) && $fileInfo['encrypted'] == 1) { return $fileInfo['unencrypted_size']; } else { - return $fileInfo['size']; + return $size; } } } diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 7e42627f8c..411bcdac92 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -87,10 +87,7 @@ class Stream { // rawPath is relative to the data directory $this->rawPath = $this->userId . '/files/' . $this->relPath; - // Fix .part filenames - $this->rawPath = Keymanager::fixPartialFilePath( $this->rawPath ); - - if ( + if ( dirname( $this->rawPath ) == 'streams' and isset( self::$sourceStreams[basename( $this->rawPath )] ) ) { @@ -244,10 +241,7 @@ class Stream { } - // Avoid problems with .part file extensions - $this->relPath = Keymanager::fixPartialFilePath( $this->relPath ); - - // Fetch and decrypt keyfile + // Fetch and decrypt keyfile // Fetch existing keyfile $this->encKeyfile = Keymanager::getFileKey( $this->rootView, $this->userId, $this->relPath ); From d017bbb065245212e8aa4091f4bee0a4e8ea9055 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Thu, 25 Apr 2013 23:24:07 +0200 Subject: [PATCH 097/257] fix share for renamed or moved files --- apps/files_encryption/lib/proxy.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 7294c24366..73f72a9e23 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -343,13 +343,13 @@ class Proxy extends \OC_FileProxy { \OC_FileProxy::$enabled = false; $view = new \OC_FilesystemView('/'); + $session = new Session($view); $userId = \OCP\User::getUser(); $util = new Util( $view, $userId ); // Reformat path for use with OC_FSV $newPathSplit = explode( '/', $newPath ); $newPathRelative = implode( '/', array_slice( $newPathSplit, 3 ) ); - $newPathRelativeToUser = implode( '/', array_slice( $newPathSplit, 2 ) ); // get file info from database/cache //$newFileInfo = \OC\Files\Filesystem::getFileInfo($newPathRelative); @@ -386,8 +386,19 @@ class Proxy extends \OC_FileProxy { $view->putFileInfo( $newPath, $cached ); + // get sharing app state + $sharingEnabled = \OCP\Share::isEnabled(); + + // get users + $usersSharing = $util->getSharingUsersArray($sharingEnabled, $newPathRelative); + + // update sharing-keys + $util->setSharedFileKeyfiles($session, $usersSharing, $newPathRelative); } + + + \OC_FileProxy::$enabled = $proxyStatus; return true; From 813641e6e86601cc73da0f00d8430da62e872180 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Sat, 27 Apr 2013 00:05:20 +0200 Subject: [PATCH 098/257] improved file size created new method fixFileSize in Util so it can be used with files_trashbin --- apps/files_encryption/lib/proxy.php | 40 +---------------- apps/files_encryption/lib/util.php | 70 ++++++++++++++++++++++++++--- 2 files changed, 66 insertions(+), 44 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 73f72a9e23..24821d8a05 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -351,41 +351,7 @@ class Proxy extends \OC_FileProxy { $newPathSplit = explode( '/', $newPath ); $newPathRelative = implode( '/', array_slice( $newPathSplit, 3 ) ); - // get file info from database/cache - //$newFileInfo = \OC\Files\Filesystem::getFileInfo($newPathRelative); - - if ($util->isEncryptedPath($newPath)) { - $cached = $view->getFileInfo($newPath); - $cached['encrypted'] = 1; - - // get the size from filesystem - $size = $view->filesize($newPath); - - // calculate last chunk nr - $lastChunckNr = floor($size / 8192); - - // open stream - $result = fopen('crypt://' . $newPathRelative, "r"); - - if(is_resource($result)) { - // calculate last chunk position - $lastChunckPos = ($lastChunckNr * 8192); - - // seek to end - fseek($result, $lastChunckPos); - - // get the content of the last chunck - $lastChunkContent = fread($result, 8192); - - // calc the real file size with the size of the last chunk - $realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent)); - - // set the size - $cached['unencrypted_size'] = $realSize; - } - - $view->putFileInfo( $newPath, $cached ); - + if($util->fixFileSize($newPath)) { // get sharing app state $sharingEnabled = \OCP\Share::isEnabled(); @@ -396,13 +362,9 @@ class Proxy extends \OC_FileProxy { $util->setSharedFileKeyfiles($session, $usersSharing, $newPathRelative); } - - - \OC_FileProxy::$enabled = $proxyStatus; return true; - } public function postFopen( $path, &$result ){ diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 2198963ce1..9d9e420e4d 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -421,10 +421,10 @@ class Util { return $text; } - /** - * @brief Check if a given path identifies an encrypted file - * @return true / false - */ + /** + * @brief Check if a given path identifies an encrypted file + * @return true / false + */ public function isEncryptedPath( $path ) { // Disable encryption proxy so data retreived is in its @@ -438,7 +438,67 @@ class Util { return Crypt::isCatfileContent( $data ); } - + + /** + * @brief fix the file size of the encrypted file + * + * @param $path absolute path + * @return true / false if file is encrypted + */ + + public function fixFileSize($path) { + $result = false; + + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + if ($this->isEncryptedPath($path)) { + + // Reformat path for use with OC_FSV + $pathSplit = explode( '/', $path ); + $pathRelative = implode( '/', array_slice( $pathSplit, 3 ) ); + + $cached = $this->view->getFileInfo($path); + $cached['encrypted'] = 1; + + // get the size from filesystem + $size = $this->view->filesize($path); + + // calculate last chunk nr + $lastChunckNr = floor($size / 8192); + + // open stream + $result = fopen('crypt://' . $pathRelative, "r"); + + if(is_resource($result)) { + // calculate last chunk position + $lastChunckPos = ($lastChunckNr * 8192); + + // seek to end + fseek($result, $lastChunckPos); + + // get the content of the last chunk + $lastChunkContent = fread($result, 8192); + + // calc the real file size with the size of the last chunk + $realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent)); + + // set the size + $cached['unencrypted_size'] = $realSize; + } + + // put file info + $this->view->putFileInfo( $path, $cached ); + + $result = true; + } + + \OC_FileProxy::$enabled = $proxyStatus; + + return $result; + } + /** * @brief Format a path to be relative to the /user/files/ directory */ From d40ffc5aac2e54da6b94e62094bbd323db818e82 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Sat, 27 Apr 2013 20:18:05 +0200 Subject: [PATCH 099/257] added filesystem post rename hook --- apps/files_encryption/appinfo/app.php | 3 ++ apps/files_encryption/hooks/hooks.php | 66 ++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index c2de9d0b44..9ae6c8331f 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -23,6 +23,9 @@ OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', ' // Webdav-related hooks OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfileFromClient' ); +// filesystem hooks +OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRename'); + stream_wrapper_register( 'crypt', 'OCA\Encryption\Stream' ); $view = new OC_FilesystemView( '/' ); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 2ac74ad6c4..82aae2272a 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -310,5 +310,69 @@ class Hooks { // we may not need to implement it } - + + + /** + * @brief after a file is renamed, rename its keyfile and share-keys also fix the file size and fix also the sharing + * @param array with oldpath and newpath + * + * This function is connected to the rename signal of OC_Filesystem and adjust the name and location + * of the stored versions along the actual file + */ + public static function postRename($params) { + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + $view = new \OC_FilesystemView('/'); + $session = new Session($view); + $userId = \OCP\User::getUser(); + $util = new Util( $view, $userId ); + + // Format paths to be relative to user files dir + $oldKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $params['oldpath']; + $newKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $params['newpath']; + + // add key ext if this is not an folder + if (!$view->is_dir($oldKeyfilePath)) { + $oldKeyfilePath .= '.key'; + $newKeyfilePath .= '.key'; + + // handle share-keys + $localKeyPath = $view->getLocalFile($userId.'/files_encryption/share-keys/'.$params['oldpath']); + $matches = glob(preg_quote($localKeyPath).'*.shareKey'); + foreach ($matches as $src) { + $dst = str_replace($params['oldpath'], $params['newpath'], $src); + rename($src, $dst); + } + + } else { + // handle share-keys folders + $oldShareKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $params['oldpath']; + $newShareKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $params['newpath']; + $view->rename($oldShareKeyfilePath, $newShareKeyfilePath); + } + + // Rename keyfile so it isn't orphaned + if($view->file_exists($oldKeyfilePath)) { + $view->rename($oldKeyfilePath, $newKeyfilePath); + } + + // build the path to the file + $newPath = '/' . $userId . '/files' .$params['newpath']; + $newPathRelative = $params['newpath']; + + if($util->fixFileSize($newPath)) { + // get sharing app state + $sharingEnabled = \OCP\Share::isEnabled(); + + // get users + $usersSharing = $util->getSharingUsersArray($sharingEnabled, $newPathRelative); + + // update sharing-keys + $util->setSharedFileKeyfiles($session, $usersSharing, $newPathRelative); + } + + \OC_FileProxy::$enabled = $proxyStatus; + } } From 05523b76c0c17a74db6604f2689a9219d318153d Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Sat, 27 Apr 2013 20:18:57 +0200 Subject: [PATCH 100/257] fix reusing keys fix webdav part files --- apps/files_encryption/lib/keymanager.php | 76 ++++++++++++++++++++---- 1 file changed, 66 insertions(+), 10 deletions(-) diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index cfc13ee132..9f3cb8120c 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -129,16 +129,51 @@ class Keymanager { mkdir($keyfileFolderName, 0750, true); } } - - $result = $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile ); - + + // try reusing key file if part file + if(self::isPartialFilePath($targetPath)) { + $result = $view->file_put_contents( $basePath . '/' . self::fixPartialFilePath($targetPath) . '.key', $catfile ); + } else { + $result = $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile ); + } \OC_FileProxy::$enabled = $proxyStatus; return $result; } - + + /** + * @brief Remove .path extension from a file path + * @param string $path Path that may identify a .part file + * @return string File path without .part extension + * @note this is needed for reusing keys + */ + public static function fixPartialFilePath($path) + { + if (preg_match('/\.part$/', $path)) { + + $newLength = strlen($path) - 5; + $fPath = substr($path, 0, $newLength); + + return $fPath; + } else { + + return $path; + + } + + } + + public static function isPartialFilePath($path) + { + if (preg_match('/\.part$/', $path)) { + return true; + } else { + return false; + } + + } /** * @brief retrieve keyfile for an encrypted file * @param \OC_FilesystemView $view @@ -150,12 +185,20 @@ class Keymanager { * of the keyfile must be performed by client code */ public static function getFileKey( \OC_FilesystemView $view, $userId, $filePath ) { - + + // try reusing key file if part file + if(self::isPartialFilePath($filePath)) { + $result = self::getFileKey($view, $userId, self::fixPartialFilePath($filePath)); + if($result) { + return $result; + } + } + $util = new Util($view, \OCP\User::getUser()); list($owner, $filename) = $util->getUidAndFilename($filePath); $filePath_f = ltrim( $filename, '/' ); - - $keyfilePath = '/' . $owner . '/files_encryption/keyfiles/' . $filePath_f . '.key'; + + $keyfilePath = '/' . $owner . '/files_encryption/keyfiles/' . $filePath_f . '.key'; $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; @@ -287,7 +330,7 @@ class Keymanager { */ public static function setShareKey( \OC_FilesystemView $view, $path, $userId, $shareKey ) { - //here we need the currently logged in user, while userId can be a different user + //here we need the currently logged in user, while userId can be a different user $util = new Util( $view, \OCP\User::getUser() ); list($owner, $filename) = $util->getUidAndFilename($path); @@ -295,8 +338,13 @@ class Keymanager { $basePath = '/' . $owner . '/files_encryption/share-keys'; $shareKeyPath = self::keySetPreparation( $view, $filename, $basePath, $owner ); - - $writePath = $basePath . '/' . $shareKeyPath . '.' . $userId . '.shareKey'; + + // try reusing key file if part file + if(self::isPartialFilePath($shareKeyPath)) { + $writePath = $basePath . '/' . self::fixPartialFilePath($shareKeyPath) . '.' . $userId . '.shareKey'; + } else { + $writePath = $basePath . '/' . $shareKeyPath . '.' . $userId . '.shareKey'; + } $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; @@ -359,6 +407,14 @@ class Keymanager { */ public static function getShareKey( \OC_FilesystemView $view, $userId, $filePath ) { + // try reusing key file if part file + if(self::isPartialFilePath($filePath)) { + $result = self::getShareKey($view, $userId, self::fixPartialFilePath($filePath)); + if($result) { + return $result; + } + } + $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; From ba080e0d2e43a24b891aa7d8bb8bcf54ccd5faa4 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Sat, 27 Apr 2013 20:21:46 +0200 Subject: [PATCH 101/257] removed preRename and moved postRename to hooks.php added postWrite and postTouch to fix file size and sharing keys --- apps/files_encryption/lib/proxy.php | 158 ++++++++++------------------ 1 file changed, 58 insertions(+), 100 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 24821d8a05..439aa0da25 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -273,96 +273,20 @@ class Proxy extends \OC_FileProxy { } /** - * @brief When a file is renamed, rename its keyfile also - * @return bool Result of rename() - * @note This is pre rather than post because using post didn't work - */ - public function preRename( $oldPath, $newPath ) - { - - // Disable encryption proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - - $view = new \OC_FilesystemView('/'); - - $userId = \OCP\USER::getUser(); - - // Format paths to be relative to user files dir - $oldTrimmed = ltrim($oldPath, '/'); - $oldSplit = explode('/', $oldTrimmed); - $oldSliced = array_slice($oldSplit, 2); - $oldRelPath = implode('/', $oldSliced); - $oldKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $oldRelPath; - - $newTrimmed = ltrim($newPath, '/'); - $newSplit = explode('/', $newTrimmed); - $newSliced = array_slice($newSplit, 2); - $newRelPath = implode('/', $newSliced); - $newKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $newRelPath; - - // add key ext if this is not an folder - if (!$view->is_dir($oldKeyfilePath)) { - $oldKeyfilePath .= '.key'; - $newKeyfilePath .= '.key'; - - // handle share-keys - $localKeyPath = $view->getLocalFile($userId.'/files_encryption/share-keys/'.$oldRelPath); - $matches = glob(preg_quote($localKeyPath).'*.shareKey'); - foreach ($matches as $src) { - $dst = str_replace($oldRelPath, $newRelPath, $src); - rename($src, $dst); - } - - } else { - // handle share-keys folders - $oldShareKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $oldRelPath; - $newShareKeyfilePath = $userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $newRelPath; - $view->rename($oldShareKeyfilePath, $newShareKeyfilePath); - } - - // Rename keyfile so it isn't orphaned - $result = $view->rename($oldKeyfilePath, $newKeyfilePath); - - \OC_FileProxy::$enabled = $proxyStatus; - - return $result; - - } - - /** * @brief When a file is renamed, rename its keyfile also * @return bool Result of rename() * @note This is pre rather than post because using post didn't work */ - public function postRename( $oldPath, $newPath ) + public function postWrite( $path ) { + $this->handleFile($path); - // Disable encryption proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; + return true; + } - $view = new \OC_FilesystemView('/'); - $session = new Session($view); - $userId = \OCP\User::getUser(); - $util = new Util( $view, $userId ); - - // Reformat path for use with OC_FSV - $newPathSplit = explode( '/', $newPath ); - $newPathRelative = implode( '/', array_slice( $newPathSplit, 3 ) ); - - if($util->fixFileSize($newPath)) { - // get sharing app state - $sharingEnabled = \OCP\Share::isEnabled(); - - // get users - $usersSharing = $util->getSharingUsersArray($sharingEnabled, $newPathRelative); - - // update sharing-keys - $util->setSharedFileKeyfiles($session, $usersSharing, $newPathRelative); - } - - \OC_FileProxy::$enabled = $proxyStatus; + public function postTouch( $path ) + { + $this->handleFile($path); return true; } @@ -480,25 +404,28 @@ class Proxy extends \OC_FileProxy { return $data; } - public function postStat( $path, $data ) { + public function postStat($path, $data) + { + // check if file is encrypted + if (Crypt::isCatfileContent($path)) { - if ( Crypt::isCatfileContent( $path ) ) { - - $cached = \OC\Files\Filesystem::getFileInfo( $path, '' ); - - $data['size'] = $cached['unencrypted_size']; - - } - - return $data; - } + // get file info from cache + $cached = \OC\Files\Filesystem::getFileInfo($path, ''); - public function postFileSize( $path, $size ) { + // set the real file size + $data['size'] = $cached['unencrypted_size']; + } - $view = new \OC_FilesystemView( '/' ); + return $data; + } + + public function postFileSize($path, $size) + { + + $view = new \OC_FilesystemView('/'); // if path is a folder do nothing - if($view->is_dir($path)) { + if ($view->is_dir($path)) { return $size; } @@ -510,10 +437,41 @@ class Proxy extends \OC_FileProxy { $fileInfo = \OC\Files\Filesystem::getFileInfo($path_f); // if file is encrypted return real file size - if(is_array($fileInfo) && $fileInfo['encrypted'] == 1) { + if (is_array($fileInfo) && $fileInfo['encrypted'] == 1) { return $fileInfo['unencrypted_size']; } else { return $size; } - } -} + } + + public function handleFile($path) { + + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + $view = new \OC_FilesystemView('/'); + $session = new Session($view); + $userId = \OCP\User::getUser(); + $util = new Util( $view, $userId ); + + // Reformat path for use with OC_FSV + $path_split = explode( '/', $path ); + $path_f = implode( '/', array_slice( $path_split, 3 ) ); + + // only if file is on 'files' folder fix file size and sharing + if($path_split[2] == 'files' && $util->fixFileSize($path)) { + + // get sharing app state + $sharingEnabled = \OCP\Share::isEnabled(); + + // get users + $usersSharing = $util->getSharingUsersArray($sharingEnabled, $path_f); + + // update sharing-keys + $util->setSharedFileKeyfiles($session, $usersSharing, $path_f); + } + + \OC_FileProxy::$enabled = $proxyStatus; + } + } From 770aebfb9ed7703010ee2bceca73dee35f660c00 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Sat, 27 Apr 2013 20:22:38 +0200 Subject: [PATCH 102/257] check if file exists before fixing file size --- apps/files_encryption/lib/util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 9d9e420e4d..a9996999a3 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -453,7 +453,7 @@ class Util { $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; - if ($this->isEncryptedPath($path)) { + if ($this->view->file_exists($path) && $this->isEncryptedPath($path)) { // Reformat path for use with OC_FSV $pathSplit = explode( '/', $path ); From d32bf993fa0d0e1dae6c9e1541bfa9a599ec9b52 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Sat, 27 Apr 2013 20:23:30 +0200 Subject: [PATCH 103/257] removed previous added post rename FileProxy hook --- lib/files/view.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/files/view.php b/lib/files/view.php index d0fc5910e6..bd4812f8f8 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -362,7 +362,6 @@ class View { list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); if ($storage) { $result = $storage->rename($internalPath1, $internalPath2); - \OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2); } else { $result = false; } From 7f1f0464a882dc8df80cc2da79079dad0933ecdd Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Sat, 27 Apr 2013 23:02:42 +0200 Subject: [PATCH 104/257] added self healing if file get remove from file cache --- apps/files_encryption/lib/proxy.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 439aa0da25..23290b5b20 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -438,10 +438,24 @@ class Proxy extends \OC_FileProxy { // if file is encrypted return real file size if (is_array($fileInfo) && $fileInfo['encrypted'] == 1) { - return $fileInfo['unencrypted_size']; + $size = $fileInfo['unencrypted_size']; } else { - return $size; + // self healing if file was removed from file cache + $userId = \OCP\User::getUser(); + $util = new Util( $view, $userId ); + $fixSize = $util->getFileSize($path); + if($fixSize > 0) { + $size = $fixSize; + + $fileInfo['encrypted'] = 1; + $fileInfo['unencrypted_size'] = $size; + + // put file info + $view->putFileInfo( $path, $fileInfo ); + } } + + return $size; } public function handleFile($path) { From f9760f65212bd6464685ec1dd60a73825b4a3f66 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Sat, 27 Apr 2013 23:34:25 +0200 Subject: [PATCH 105/257] improved file size --- apps/files_encryption/lib/util.php | 87 +++++++++++++++++++----------- 1 file changed, 56 insertions(+), 31 deletions(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index a9996999a3..fe040d8877 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -439,6 +439,58 @@ class Util { } + /** + * @brief get the file size of the unencrypted file + * + * @param $path absolute path + * @return true / false if file is encrypted + */ + + public function getFileSize($path) { + $result = 0; + + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + // Reformat path for use with OC_FSV + $pathSplit = explode( '/', $path ); + $pathRelative = implode( '/', array_slice( $pathSplit, 3 ) ); + + if ($pathSplit[2] == 'files' && $this->view->file_exists($path) && $this->isEncryptedPath($path)) { + + // get the size from filesystem + $fullPath = $this->view->getLocalFile($path); + $size = filesize($fullPath); + + // calculate last chunk nr + $lastChunckNr = floor($size / 8192); + + // open stream + $stream = fopen('crypt://' . $pathRelative, "r"); + + if(is_resource($stream)) { + // calculate last chunk position + $lastChunckPos = ($lastChunckNr * 8192); + + // seek to end + fseek($stream, $lastChunckPos); + + // get the content of the last chunk + $lastChunkContent = fread($stream, 8192); + + // calc the real file size with the size of the last chunk + $realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent)); + + // store file size + $result = $realSize; + } + } + + \OC_FileProxy::$enabled = $proxyStatus; + + return $result; + } /** * @brief fix the file size of the encrypted file * @@ -453,40 +505,13 @@ class Util { $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; - if ($this->view->file_exists($path) && $this->isEncryptedPath($path)) { - - // Reformat path for use with OC_FSV - $pathSplit = explode( '/', $path ); - $pathRelative = implode( '/', array_slice( $pathSplit, 3 ) ); - + $realSize = $this->getFileSize($path); + if($realSize > 0) { $cached = $this->view->getFileInfo($path); $cached['encrypted'] = 1; - // get the size from filesystem - $size = $this->view->filesize($path); - - // calculate last chunk nr - $lastChunckNr = floor($size / 8192); - - // open stream - $result = fopen('crypt://' . $pathRelative, "r"); - - if(is_resource($result)) { - // calculate last chunk position - $lastChunckPos = ($lastChunckNr * 8192); - - // seek to end - fseek($result, $lastChunckPos); - - // get the content of the last chunk - $lastChunkContent = fread($result, 8192); - - // calc the real file size with the size of the last chunk - $realSize = (($lastChunckNr * 6126) + strlen($lastChunkContent)); - - // set the size - $cached['unencrypted_size'] = $realSize; - } + // set the size + $cached['unencrypted_size'] = $realSize; // put file info $this->view->putFileInfo( $path, $cached ); From 4a63faf64b14b21af7cb73f43ca3fcf841aff804 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 29 Apr 2013 01:43:59 +0200 Subject: [PATCH 106/257] speed improvement --- apps/files_encryption/lib/stream.php | 65 +++++++++++++++++----------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 411bcdac92..a51f2c56d9 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -298,7 +298,8 @@ class Stream { // automatically attempted when the file is written to disk - // we are handling that separately here and we don't want to // get into an infinite loop - //\OC_FileProxy::$enabled = false; + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; // Get the length of the unencrypted data that we are handling $length = strlen( $data ); @@ -322,30 +323,7 @@ class Stream { } - // Fetch user's public key - $this->publicKey = Keymanager::getPublicKey( $this->rootView, $this->userId ); - - // Check if OC sharing api is enabled - $sharingEnabled = \OCP\Share::isEnabled(); - - $util = new Util( $this->rootView, $this->userId ); - - // Get all users sharing the file includes current user - $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $this->relPath, $this->userId); - // Fetch public keys for all sharing users - $publicKeys = Keymanager::getPublicKeys( $this->rootView, $uniqueUserIds ); - - // Encrypt enc key for all sharing users - $this->encKeyfiles = Crypt::multiKeyEncrypt( $this->plainKey, $publicKeys ); - - $view = new \OC_FilesystemView( '/' ); - - // Save the new encrypted file key - Keymanager::setFileKey( $this->rootView, $this->relPath, $this->userId, $this->encKeyfiles['data'] ); - - // Save the sharekeys - Keymanager::setShareKeys( $view, $this->relPath, $this->encKeyfiles['keys'] ); // If extra data is left over from the last round, make sure it // is integrated into the next 6126 / 8192 block @@ -437,6 +415,8 @@ class Stream { $this->size = max( $this->size, $pointer + $length ); $this->unencryptedSize += $length; + \OC_FileProxy::$enabled = $proxyStatus; + return $length; } @@ -492,13 +472,46 @@ class Stream { } public function stream_close() { - - $this->flush(); + + $this->flush(); if ( $this->meta['mode']!='r' and $this->meta['mode']!='rb' ) { + + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + // Fetch user's public key + $this->publicKey = Keymanager::getPublicKey( $this->rootView, $this->userId ); + + // Check if OC sharing api is enabled + $sharingEnabled = \OCP\Share::isEnabled(); + + $util = new Util( $this->rootView, $this->userId ); + + // Get all users sharing the file includes current user + $uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $this->relPath, $this->userId); + + // Fetch public keys for all sharing users + $publicKeys = Keymanager::getPublicKeys( $this->rootView, $uniqueUserIds ); + + // Encrypt enc key for all sharing users + $this->encKeyfiles = Crypt::multiKeyEncrypt( $this->plainKey, $publicKeys ); + + $view = new \OC_FilesystemView( '/' ); + + // Save the new encrypted file key + Keymanager::setFileKey( $this->rootView, $this->relPath, $this->userId, $this->encKeyfiles['data'] ); + + // Save the sharekeys + Keymanager::setShareKeys( $view, $this->relPath, $this->encKeyfiles['keys'] ); + + // Re-enable proxy - our work is done + \OC_FileProxy::$enabled = $proxyStatus; + \OC\Files\Filesystem::putFileInfo( $this->relPath, array( 'encrypted' => 1, 'size' => $this->size, 'unencrypted_size' => $this->unencryptedSize ), '' ); } From 4ecd62e58d6caf8da3b6e1a14114fec49784a622 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 29 Apr 2013 09:12:43 +0200 Subject: [PATCH 107/257] improvements for test testSymmetricStreamEncryptShortFileContent this runs currently into an infinite loop --- apps/files_encryption/test/crypt.php | 66 ++++++++++++++++------------ 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/apps/files_encryption/test/crypt.php b/apps/files_encryption/test/crypt.php index b02e63b2ff..9c5e43e242 100755 --- a/apps/files_encryption/test/crypt.php +++ b/apps/files_encryption/test/crypt.php @@ -52,14 +52,19 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { \OC_User::setUserId( 'admin' ); $this->userId = 'admin'; $this->pass = 'admin'; - - \OC_Filesystem::init( '/' ); - \OC_Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => \OC_User::getHome($this->userId)), '/' ); - + + $userHome = \OC_User::getHome($this->userId); + if(!file_exists($userHome)) { + mkdir($userHome, 0777, true); + } + $dataDir = str_replace('/'.$this->userId, '', $userHome); + + \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $dataDir), '/' ); + \OC\Files\Filesystem::init($this->userId, '/'); } function tearDown() { - + } function testGenerateKey() { @@ -222,35 +227,38 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { function testSymmetricStreamEncryptShortFileContent() { - $filename = 'tmp-'.time(); - + $filename = 'tmp-'.time().'.test'; + $cryptedFile = file_put_contents( 'crypt://' . $filename, $this->dataShort ); // Test that data was successfully written $this->assertTrue( is_int( $cryptedFile ) ); - - - // Get file contents without using any wrapper to get it's actual contents on disk - $retreivedCryptedFile = $this->view->file_get_contents( $this->userId . '/files/' . $filename ); - + + // Get file contents without using any wrapper to get it's actual contents on disk + $absolutePath = \OC\Files\Filesystem::getLocalFile($this->userId . '/files/' . $filename); + $retreivedCryptedFile = file_get_contents($absolutePath); + // Check that the file was encrypted before being written to disk $this->assertNotEquals( $this->dataShort, $retreivedCryptedFile ); - - // Get private key - $encryptedPrivateKey = Encryption\Keymanager::getPrivateKey( $this->view, $this->userId ); - - $decryptedPrivateKey = Encryption\Crypt::symmetricDecryptFileContent( $encryptedPrivateKey, $this->pass ); - - - // Get keyfile - $encryptedKeyfile = Encryption\Keymanager::getFileKey( $this->view, $this->userId, $filename ); - - $decryptedKeyfile = Encryption\Crypt::keyDecrypt( $encryptedKeyfile, $decryptedPrivateKey ); - - - // Manually decrypt - $manualDecrypt = Encryption\Crypt::symmetricBlockDecryptFileContent( $retreivedCryptedFile, $decryptedKeyfile ); - + + // Get the encrypted keyfile + $encKeyfile = Encryption\Keymanager::getFileKey( $this->view, $this->userId, $filename ); + + // Attempt to fetch the user's shareKey + $shareKey = Encryption\Keymanager::getShareKey( $this->view, $this->userId, $filename ); + + // get session + $session = new Encryption\Session( $this->view ); + + // get private key + $privateKey = $session->getPrivateKey( $this->userId ); + + // Decrypt keyfile with shareKey + $plainKeyfile = Encryption\Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); + + // Manually decrypt + $manualDecrypt = Encryption\Crypt::symmetricDecryptFileContent( $retreivedCryptedFile, $plainKeyfile ); + // Check that decrypted data matches $this->assertEquals( $this->dataShort, $manualDecrypt ); @@ -329,7 +337,7 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { $this->view->unlink( $filename ); - Encryption\Keymanager::deleteFileKey( $filename ); + Encryption\Keymanager::deleteFileKey( $this->view, $this->userId, $filename ); } From c52fe1253728dde2b85521df3fce4c461741bcc3 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 29 Apr 2013 23:37:08 +0200 Subject: [PATCH 108/257] fixed missing parameter --- apps/files_encryption/hooks/hooks.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 82aae2272a..25c2d091c4 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -119,8 +119,10 @@ class Hooks { // is in use (client-side encryption does not have access to // the necessary keys) if ( Crypt::mode() == 'server' ) { - - $session = new Session(); + + $view = new \OC_FilesystemView( '/' ); + + $session = new Session($view); // Get existing decrypted private key $privateKey = $session->getPrivateKey(); From d22795d68b4937bc6dba6d742b0f7b503cb32228 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Mon, 29 Apr 2013 23:41:49 +0200 Subject: [PATCH 109/257] fixed test for crypt and keymanager disabled encryption file proxy in test/lib/cache/file.php --- apps/files_encryption/test/crypt.php | 87 +++++++++++++---------- apps/files_encryption/test/keymanager.php | 37 ++++++---- tests/lib/cache/file.php | 7 +- 3 files changed, 78 insertions(+), 53 deletions(-) diff --git a/apps/files_encryption/test/crypt.php b/apps/files_encryption/test/crypt.php index 9c5e43e242..7f9572f426 100755 --- a/apps/files_encryption/test/crypt.php +++ b/apps/files_encryption/test/crypt.php @@ -34,7 +34,9 @@ use OCA\Encryption; class Test_Crypt extends \PHPUnit_Framework_TestCase { function setUp() { - + // reset backend + \OC_User::useBackend('database'); + // set content for encrypting / decrypting in tests $this->dataLong = file_get_contents( realpath( dirname(__FILE__).'/../lib/crypt.php' ) ); $this->dataShort = 'hats'; @@ -54,13 +56,10 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { $this->pass = 'admin'; $userHome = \OC_User::getHome($this->userId); - if(!file_exists($userHome)) { - mkdir($userHome, 0777, true); - } - $dataDir = str_replace('/'.$this->userId, '', $userHome); + $this->dataDir = str_replace('/'.$this->userId, '', $userHome); - \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $dataDir), '/' ); \OC\Files\Filesystem::init($this->userId, '/'); + \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $this->dataDir), '/' ); } function tearDown() { @@ -225,7 +224,7 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { // // } - function testSymmetricStreamEncryptShortFileContent() { + function testSymmetricStreamEncryptShortFileContent() { $filename = 'tmp-'.time().'.test'; @@ -234,9 +233,15 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { // Test that data was successfully written $this->assertTrue( is_int( $cryptedFile ) ); + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + // Get file contents without using any wrapper to get it's actual contents on disk - $absolutePath = \OC\Files\Filesystem::getLocalFile($this->userId . '/files/' . $filename); - $retreivedCryptedFile = file_get_contents($absolutePath); + $retreivedCryptedFile = $this->view->file_get_contents($this->userId . '/files/' . $filename); + + // Re-enable proxy - our work is done + \OC_FileProxy::$enabled = $proxyStatus; // Check that the file was encrypted before being written to disk $this->assertNotEquals( $this->dataShort, $retreivedCryptedFile ); @@ -261,7 +266,11 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { // Check that decrypted data matches $this->assertEquals( $this->dataShort, $manualDecrypt ); - + + // Teardown + $this->view->unlink( $filename ); + + Encryption\Keymanager::deleteFileKey( $this->view, $this->userId, $filename ); } /** @@ -273,7 +282,7 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { function testSymmetricStreamEncryptLongFileContent() { // Generate a a random filename - $filename = 'tmp-'.time(); + $filename = 'tmp-'.time().'.test'; // Save long data as encrypted file using stream wrapper $cryptedFile = file_put_contents( 'crypt://' . $filename, $this->dataLong.$this->dataLong ); @@ -281,12 +290,18 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { // Test that data was successfully written $this->assertTrue( is_int( $cryptedFile ) ); - // Get file contents without using any wrapper to get it's actual contents on disk - $retreivedCryptedFile = $this->view->file_get_contents( $this->userId . '/files/' . $filename ); - -// echo "\n\n\$retreivedCryptedFile = $retreivedCryptedFile\n\n"; - - // Check that the file was encrypted before being written to disk + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + // Get file contents without using any wrapper to get it's actual contents on disk + $retreivedCryptedFile = $this->view->file_get_contents($this->userId . '/files/' . $filename); + + // Re-enable proxy - our work is done + \OC_FileProxy::$enabled = $proxyStatus; + + + // Check that the file was encrypted before being written to disk $this->assertNotEquals( $this->dataLong.$this->dataLong, $retreivedCryptedFile ); // Manuallly split saved file into separate IVs and encrypted chunks @@ -298,39 +313,35 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { $e = array( $r[0].$r[1], $r[2].$r[3], $r[4].$r[5], $r[6].$r[7], $r[8].$r[9], $r[10].$r[11], $r[12].$r[13] );//.$r[11], $r[12].$r[13], $r[14] ); //print_r($e); - - - // Get private key - $encryptedPrivateKey = Encryption\Keymanager::getPrivateKey( $this->view, $this->userId ); - - $decryptedPrivateKey = Encryption\Crypt::symmetricDecryptFileContent( $encryptedPrivateKey, $this->pass ); - - - // Get keyfile - $encryptedKeyfile = Encryption\Keymanager::getFileKey( $this->view, $this->userId, $filename ); - - $decryptedKeyfile = Encryption\Crypt::keyDecrypt( $encryptedKeyfile, $decryptedPrivateKey ); - - + + // Get the encrypted keyfile + $encKeyfile = Encryption\Keymanager::getFileKey( $this->view, $this->userId, $filename ); + + // Attempt to fetch the user's shareKey + $shareKey = Encryption\Keymanager::getShareKey( $this->view, $this->userId, $filename ); + + // get session + $session = new Encryption\Session( $this->view ); + + // get private key + $privateKey = $session->getPrivateKey( $this->userId ); + + // Decrypt keyfile with shareKey + $plainKeyfile = Encryption\Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey ); + // Set var for reassembling decrypted content $decrypt = ''; // Manually decrypt chunk foreach ($e as $e) { - -// echo "\n\$e = $e"; - $chunkDecrypt = Encryption\Crypt::symmetricDecryptFileContent( $e, $decryptedKeyfile ); + $chunkDecrypt = Encryption\Crypt::symmetricDecryptFileContent( $e, $plainKeyfile ); // Assemble decrypted chunks $decrypt .= $chunkDecrypt; -// echo "\n\$chunkDecrypt = $chunkDecrypt"; - } -// echo "\n\$decrypt = $decrypt"; - $this->assertEquals( $this->dataLong.$this->dataLong, $decrypt ); // Teardown diff --git a/apps/files_encryption/test/keymanager.php b/apps/files_encryption/test/keymanager.php index bf453fe316..3dba6d0df9 100644 --- a/apps/files_encryption/test/keymanager.php +++ b/apps/files_encryption/test/keymanager.php @@ -24,7 +24,9 @@ use OCA\Encryption; class Test_Keymanager extends \PHPUnit_Framework_TestCase { function setUp() { - + // reset backend + \OC_User::useBackend('database'); + \OC_FileProxy::$enabled = false; // set content for encrypting / decrypting in tests @@ -44,9 +46,12 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { \OC_User::setUserId( 'admin' ); $this->userId = 'admin'; $this->pass = 'admin'; - - \OC_Filesystem::init( '/' ); - \OC_Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => \OC_User::getHome($this->userId)), '/' ); + + $userHome = \OC_User::getHome($this->userId); + $this->dataDir = str_replace('/'.$this->userId, '', $userHome); + + \OC_Filesystem::init( $this->userId, '/' ); + \OC_Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $this->dataDir), '/' ); } @@ -61,7 +66,7 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { $key = Encryption\Keymanager::getPrivateKey( $this->view, $this->userId ); // Will this length vary? Perhaps we should use a range instead - $this->assertEquals( 2296, strlen( $key ) ); + $this->assertEquals( 4388, strlen( $key ) ); } @@ -69,7 +74,7 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { $key = Encryption\Keymanager::getPublicKey( $this->view, $this->userId ); - $this->assertEquals( 451, strlen( $key ) ); + $this->assertEquals( 800, strlen( $key ) ); $this->assertEquals( '-----BEGIN PUBLIC KEY-----', substr( $key, 0, 26 ) ); } @@ -81,11 +86,19 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { $key = Encryption\Crypt::symmetricEncryptFileContentKeyfile( $this->randomKey, 'hat' ); - $path = 'unittest-'.time().'txt'; - + $file = 'unittest-'.time().'.txt'; + + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + $this->view->file_put_contents($this->userId . '/files/' . $file, $key['encrypted']); + + // Re-enable proxy - our work is done + \OC_FileProxy::$enabled = $proxyStatus; + //$view = new \OC_FilesystemView( '/' . $this->userId . '/files_encryption/keyfiles' ); - - Encryption\Keymanager::setFileKey( $this->view, $path, $this->userId, $key['key'] ); + Encryption\Keymanager::setFileKey( $this->view, $file, $this->userId, $key['key'] ); } @@ -109,9 +122,9 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { $keys = Encryption\Keymanager::getUserKeys( $this->view, $this->userId ); - $this->assertEquals( 451, strlen( $keys['publicKey'] ) ); + $this->assertEquals( 800, strlen( $keys['publicKey'] ) ); $this->assertEquals( '-----BEGIN PUBLIC KEY-----', substr( $keys['publicKey'], 0, 26 ) ); - $this->assertEquals( 2296, strlen( $keys['privateKey'] ) ); + $this->assertEquals( 4388, strlen( $keys['privateKey'] ) ); } diff --git a/tests/lib/cache/file.php b/tests/lib/cache/file.php index 5dcd326880..d113f90768 100644 --- a/tests/lib/cache/file.php +++ b/tests/lib/cache/file.php @@ -33,9 +33,10 @@ class Test_Cache_File extends Test_Cache { OC_Hook::clear('OC_Filesystem'); //enable only the encryption hook if needed - if(OC_App::isEnabled('files_encryption')) { - OC_FileProxy::register(new OC_FileProxy_Encryption()); - } + //not used right now + //if(OC_App::isEnabled('files_encryption')) { + // OC_FileProxy::register(new OCA\Encryption\Proxy()); + //} //set up temporary storage \OC\Files\Filesystem::clearMounts(); From 882a747b47371ab9d71ba6c336a873873805c696 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Tue, 30 Apr 2013 00:34:05 +0200 Subject: [PATCH 110/257] rename folder to tests --- apps/files_encryption/{test => tests}/binary | Bin apps/files_encryption/{test => tests}/crypt.php | 0 .../files_encryption/{test => tests}/keymanager.php | 0 .../{test => tests}/legacy-encrypted-text.txt | Bin apps/files_encryption/{test => tests}/proxy.php | 0 apps/files_encryption/{test => tests}/stream.php | 0 apps/files_encryption/{test => tests}/util.php | 0 apps/files_encryption/{test => tests}/zeros | Bin 8 files changed, 0 insertions(+), 0 deletions(-) rename apps/files_encryption/{test => tests}/binary (100%) rename apps/files_encryption/{test => tests}/crypt.php (100%) rename apps/files_encryption/{test => tests}/keymanager.php (100%) rename apps/files_encryption/{test => tests}/legacy-encrypted-text.txt (100%) rename apps/files_encryption/{test => tests}/proxy.php (100%) rename apps/files_encryption/{test => tests}/stream.php (100%) rename apps/files_encryption/{test => tests}/util.php (100%) rename apps/files_encryption/{test => tests}/zeros (100%) diff --git a/apps/files_encryption/test/binary b/apps/files_encryption/tests/binary similarity index 100% rename from apps/files_encryption/test/binary rename to apps/files_encryption/tests/binary diff --git a/apps/files_encryption/test/crypt.php b/apps/files_encryption/tests/crypt.php similarity index 100% rename from apps/files_encryption/test/crypt.php rename to apps/files_encryption/tests/crypt.php diff --git a/apps/files_encryption/test/keymanager.php b/apps/files_encryption/tests/keymanager.php similarity index 100% rename from apps/files_encryption/test/keymanager.php rename to apps/files_encryption/tests/keymanager.php diff --git a/apps/files_encryption/test/legacy-encrypted-text.txt b/apps/files_encryption/tests/legacy-encrypted-text.txt similarity index 100% rename from apps/files_encryption/test/legacy-encrypted-text.txt rename to apps/files_encryption/tests/legacy-encrypted-text.txt diff --git a/apps/files_encryption/test/proxy.php b/apps/files_encryption/tests/proxy.php similarity index 100% rename from apps/files_encryption/test/proxy.php rename to apps/files_encryption/tests/proxy.php diff --git a/apps/files_encryption/test/stream.php b/apps/files_encryption/tests/stream.php similarity index 100% rename from apps/files_encryption/test/stream.php rename to apps/files_encryption/tests/stream.php diff --git a/apps/files_encryption/test/util.php b/apps/files_encryption/tests/util.php similarity index 100% rename from apps/files_encryption/test/util.php rename to apps/files_encryption/tests/util.php diff --git a/apps/files_encryption/test/zeros b/apps/files_encryption/tests/zeros similarity index 100% rename from apps/files_encryption/test/zeros rename to apps/files_encryption/tests/zeros From 27ce7845b4205650e50f3777d8b152470440cbe6 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Tue, 30 Apr 2013 01:35:46 +0200 Subject: [PATCH 111/257] fixed tests, now tests should work via autotest.sh files_encryption app is now enabled in enable_all.php --- apps/files_encryption/lib/util.php | 7 ++- apps/files_encryption/tests/keymanager.php | 4 +- apps/files_encryption/tests/util.php | 61 +++++++++++++++------- tests/enable_all.php | 1 + 4 files changed, 50 insertions(+), 23 deletions(-) diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index fe040d8877..4097250b25 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -204,7 +204,12 @@ class Util { $this->view->file_put_contents( $this->privateKeyPath, $encryptedPrivateKey ); \OC_FileProxy::$enabled = true; - + + // create database configuration + $sql = 'INSERT INTO `*PREFIX*encryption` (`uid`,`mode`,`recovery`) VALUES (?,?,?)'; + $args = array( $this->userId, 'server-side', 0); + $query = \OCP\DB::prepare( $sql ); + $query->execute( $args ); } return true; diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php index 3dba6d0df9..7fe37838a4 100644 --- a/apps/files_encryption/tests/keymanager.php +++ b/apps/files_encryption/tests/keymanager.php @@ -50,8 +50,8 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { $userHome = \OC_User::getHome($this->userId); $this->dataDir = str_replace('/'.$this->userId, '', $userHome); - \OC_Filesystem::init( $this->userId, '/' ); - \OC_Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $this->dataDir), '/' ); + \OC\Files\Filesystem::init( $this->userId, '/' ); + \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $this->dataDir), '/' ); } diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index 3ebc484809..0659b468a3 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -29,19 +29,20 @@ use OCA\Encryption; class Test_Enc_Util extends \PHPUnit_Framework_TestCase { function setUp() { - - \OC_Filesystem::mount( 'OC_Filestorage_Local', array(), '/' ); - - // set content for encrypting / decrypting in tests + // reset backend + \OC_User::useBackend('database'); + + \OC_User::setUserId( 'admin' ); + $this->userId = 'admin'; + $this->pass = 'admin'; + + // set content for encrypting / decrypting in tests $this->dataUrl = realpath( dirname(__FILE__).'/../lib/crypt.php' ); $this->dataShort = 'hats'; $this->dataLong = file_get_contents( realpath( dirname(__FILE__).'/../lib/crypt.php' ) ); $this->legacyData = realpath( dirname(__FILE__).'/legacy-text.txt' ); $this->legacyEncryptedData = realpath( dirname(__FILE__).'/legacy-encrypted-text.txt' ); - - $this->userId = 'admin'; - $this->pass = 'admin'; - + $keypair = Encryption\Crypt::createKeypair(); $this->genPublicKey = $keypair['publicKey']; @@ -54,9 +55,15 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase { $this->privateKeyPath = $this->encryptionDir . '/' . $this->userId . '.private.key'; // e.g. data/admin/admin.private.key $this->view = new \OC_FilesystemView( '/' ); - - $this->mockView = m::mock('OC_FilesystemView'); - $this->util = new Encryption\Util( $this->mockView, $this->userId ); + + $userHome = \OC_User::getHome($this->userId); + $this->dataDir = str_replace('/'.$this->userId, '', $userHome); + + \OC\Files\Filesystem::init( $this->userId, '/' ); + \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $this->dataDir), '/' ); + + $mockView = m::mock('OC_FilesystemView'); + $this->util = new Encryption\Util( $mockView, $this->userId ); } @@ -90,8 +97,8 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase { $mockView = m::mock('OC_FilesystemView'); - $mockView->shouldReceive( 'file_exists' )->times(5)->andReturn( false ); - $mockView->shouldReceive( 'mkdir' )->times(4)->andReturn( true ); + $mockView->shouldReceive( 'file_exists' )->times(7)->andReturn( false ); + $mockView->shouldReceive( 'mkdir' )->times(6)->andReturn( true ); $mockView->shouldReceive( 'file_put_contents' )->withAnyArgs(); $util = new Encryption\Util( $mockView, $this->userId ); @@ -107,7 +114,7 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase { $mockView = m::mock('OC_FilesystemView'); - $mockView->shouldReceive( 'file_exists' )->times(6)->andReturn( true ); + $mockView->shouldReceive( 'file_exists' )->times(8)->andReturn( true ); $mockView->shouldReceive( 'file_put_contents' )->withAnyArgs(); $util = new Encryption\Util( $mockView, $this->userId ); @@ -141,7 +148,7 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase { $mockView = m::mock('OC_FilesystemView'); - $mockView->shouldReceive( 'file_exists' )->times(3)->andReturn( true ); + $mockView->shouldReceive( 'file_exists' )->times(5)->andReturn( true ); $util = new Encryption\Util( $mockView, $this->userId ); @@ -190,11 +197,25 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase { function testGetUidAndFilename() { \OC_User::setUserId( 'admin' ); - - $this->util->getUidAndFilename( 'test1.txt' ); - - - + + $filename = 'tmp-'.time().'.test'; + + // Disable encryption proxy to prevent recursive calls + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + $this->view->file_put_contents($this->userId . '/files/' . $filename, $this->dataShort); + + // Re-enable proxy - our work is done + \OC_FileProxy::$enabled = $proxyStatus; + + $util = new Encryption\Util( $this->view, $this->userId ); + + list($fileOwnerUid, $file) = $util->getUidAndFilename( $filename ); + + $this->assertEquals('admin', $fileOwnerUid); + + $this->assertEquals($file, $filename); } // /** diff --git a/tests/enable_all.php b/tests/enable_all.php index 44af011565..111ed0e135 100644 --- a/tests/enable_all.php +++ b/tests/enable_all.php @@ -8,6 +8,7 @@ require_once __DIR__.'/../lib/base.php'; +OC_App::enable('files_encryption'); OC_App::enable('calendar'); OC_App::enable('contacts'); OC_App::enable('apptemplateadvanced'); From b1c4464eda73d0c6674a1635c7f8c8629414ecaa Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Tue, 30 Apr 2013 01:54:19 +0200 Subject: [PATCH 112/257] improved key length tests --- apps/files_encryption/tests/keymanager.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php index 7fe37838a4..81034be54b 100644 --- a/apps/files_encryption/tests/keymanager.php +++ b/apps/files_encryption/tests/keymanager.php @@ -64,9 +64,13 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { function testGetPrivateKey() { $key = Encryption\Keymanager::getPrivateKey( $this->view, $this->userId ); - + + $privateKey = Encryption\Crypt::symmetricDecryptFileContent( $key, $this->pass); + // Will this length vary? Perhaps we should use a range instead - $this->assertEquals( 4388, strlen( $key ) ); + $this->assertGreaterThan( 27, strlen( $privateKey ) ); + + $this->assertEquals( '-----BEGIN PRIVATE KEY-----', substr( $privateKey, 0, 27 ) ); } @@ -74,7 +78,7 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { $key = Encryption\Keymanager::getPublicKey( $this->view, $this->userId ); - $this->assertEquals( 800, strlen( $key ) ); + $this->assertGreaterThan( 26, strlen( $key ) ); $this->assertEquals( '-----BEGIN PUBLIC KEY-----', substr( $key, 0, 26 ) ); } @@ -122,9 +126,15 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { $keys = Encryption\Keymanager::getUserKeys( $this->view, $this->userId ); - $this->assertEquals( 800, strlen( $keys['publicKey'] ) ); + $this->assertGreaterThan( 26, strlen( $keys['publicKey'] ) ); + $this->assertEquals( '-----BEGIN PUBLIC KEY-----', substr( $keys['publicKey'], 0, 26 ) ); - $this->assertEquals( 4388, strlen( $keys['privateKey'] ) ); + + $privateKey = Encryption\Crypt::symmetricDecryptFileContent( $keys['privateKey'], $this->pass); + + $this->assertGreaterThan( 27, strlen( $keys['privateKey'] ) ); + + $this->assertEquals( '-----BEGIN PRIVATE KEY-----', substr( $privateKey, 0, 27 ) ); } From fbbc76f281f50afa3072d99e4e0d413df835b3d3 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Tue, 30 Apr 2013 20:44:42 +0200 Subject: [PATCH 113/257] fix for sharing files --- apps/files_encryption/lib/proxy.php | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 23290b5b20..50f30594b4 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -153,9 +153,9 @@ class Proxy extends \OC_FileProxy { $data = $encData; // Update the file cache with file info - \OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' ); - - // Re-enable proxy - our work is done + \OC\Files\Filesystem::putFileInfo( $filePath, array( 'encrypted'=>true, 'size' => strlen($size), 'unencrypted_size' => $size), '' ); + + // Re-enable proxy - our work is done \OC_FileProxy::$enabled = $proxyStatus; } @@ -437,24 +437,25 @@ class Proxy extends \OC_FileProxy { $fileInfo = \OC\Files\Filesystem::getFileInfo($path_f); // if file is encrypted return real file size - if (is_array($fileInfo) && $fileInfo['encrypted'] == 1) { + if (is_array($fileInfo) && $fileInfo['encrypted'] === true) { $size = $fileInfo['unencrypted_size']; } else { // self healing if file was removed from file cache - $userId = \OCP\User::getUser(); - $util = new Util( $view, $userId ); - $fixSize = $util->getFileSize($path); - if($fixSize > 0) { - $size = $fixSize; + if(is_array($fileInfo)) { + $userId = \OCP\User::getUser(); + $util = new Util( $view, $userId ); + $fixSize = $util->getFileSize($path); + if($fixSize > 0) { + $size = $fixSize; - $fileInfo['encrypted'] = 1; - $fileInfo['unencrypted_size'] = $size; + $fileInfo['encrypted'] = 1; + $fileInfo['unencrypted_size'] = $size; - // put file info - $view->putFileInfo( $path, $fileInfo ); + // put file info + $view->putFileInfo( $path_f, $fileInfo ); + } } } - return $size; } From b08179d406cf5af76291bba2edf81b9563a46f44 Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Tue, 30 Apr 2013 23:58:53 +0200 Subject: [PATCH 114/257] fixed tests after merge against master --- apps/files_encryption/tests/crypt.php | 9 ++++++--- apps/files_encryption/tests/keymanager.php | 7 +++++-- apps/files_encryption/tests/stream.php | 2 +- apps/files_encryption/tests/util.php | 9 +++++++-- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index 7f9572f426..4a85048ba4 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -21,7 +21,6 @@ use OCA\Encryption; // This has to go here because otherwise session errors arise, and the private // encryption key needs to be saved in the session -\OC_User::login( 'admin', 'admin' ); /** * @note It would be better to use Mockery here for mocking out the session @@ -37,7 +36,7 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { // reset backend \OC_User::useBackend('database'); - // set content for encrypting / decrypting in tests + // set content for encrypting / decrypting in tests $this->dataLong = file_get_contents( realpath( dirname(__FILE__).'/../lib/crypt.php' ) ); $this->dataShort = 'hats'; $this->dataUrl = realpath( dirname(__FILE__).'/../lib/crypt.php' ); @@ -60,13 +59,17 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { \OC\Files\Filesystem::init($this->userId, '/'); \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $this->dataDir), '/' ); + + $params['uid'] = $this->userId; + $params['password'] = $this->pass; + OCA\Encryption\Hooks::login($params); } function tearDown() { } - function testGenerateKey() { + function testGenerateKey() { # TODO: use more accurate (larger) string length for test confirmation diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php index 81034be54b..33ca29997b 100644 --- a/apps/files_encryption/tests/keymanager.php +++ b/apps/files_encryption/tests/keymanager.php @@ -19,7 +19,7 @@ use OCA\Encryption; // This has to go here because otherwise session errors arise, and the private // encryption key needs to be saved in the session -\OC_User::login( 'admin', 'admin' ); +//\OC_User::login( 'admin', 'admin' ); class Test_Keymanager extends \PHPUnit_Framework_TestCase { @@ -52,7 +52,10 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { \OC\Files\Filesystem::init( $this->userId, '/' ); \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $this->dataDir), '/' ); - + + $params['uid'] = $this->userId; + $params['password'] = $this->pass; + OCA\Encryption\Hooks::login($params); } function tearDown(){ diff --git a/apps/files_encryption/tests/stream.php b/apps/files_encryption/tests/stream.php index ba82ac80ea..633cc9e4fc 100644 --- a/apps/files_encryption/tests/stream.php +++ b/apps/files_encryption/tests/stream.php @@ -1,4 +1,4 @@ -// // * This file is licensed under the Affero General Public License version 3 or diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index 0659b468a3..e3ec0860fa 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -24,8 +24,6 @@ $loader->register(); use \Mockery as m; use OCA\Encryption; -\OC_User::login( 'admin', 'admin' ); - class Test_Enc_Util extends \PHPUnit_Framework_TestCase { function setUp() { @@ -62,6 +60,10 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase { \OC\Files\Filesystem::init( $this->userId, '/' ); \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $this->dataDir), '/' ); + $params['uid'] = $this->userId; + $params['password'] = $this->pass; + OCA\Encryption\Hooks::login($params); + $mockView = m::mock('OC_FilesystemView'); $this->util = new Encryption\Util( $mockView, $this->userId ); @@ -75,6 +77,9 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase { /** * @brief test that paths set during User construction are correct + * + * + * */ function testKeyPaths() { From 5deba29bdfedc3ee2babece9eafff0bb709cd90c Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Wed, 1 May 2013 00:09:55 +0200 Subject: [PATCH 115/257] fixed public-keys mount point error --- apps/files_encryption/hooks/hooks.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 25c2d091c4..e27054f0ec 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -45,7 +45,12 @@ class Hooks { $view = new \OC_FilesystemView( '/' ); - $util = new Util( $view, $params['uid'] ); + $userHome = \OC_User::getHome($params['uid']); + $dataDir = str_replace('/'.$params['uid'], '', $userHome); + + \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $dataDir .'/public-keys'), '/public-keys/' ); + + $util = new Util( $view, $params['uid'] ); // Check files_encryption infrastructure is ready for action if ( ! $util->ready() ) { From 3c100af1329c1c101f38f23f2d74710954387fdf Mon Sep 17 00:00:00 2001 From: Florin Peter Date: Wed, 1 May 2013 01:38:06 +0200 Subject: [PATCH 116/257] revert changes to fbbc76f281f50afa3072d99e4e0d413df835b3d3 because master is very unstable right now --- apps/files/js/files.js | 5 - apps/files/l10n/ar.php | 6 +- apps/files/l10n/bg_BG.php | 8 +- apps/files/l10n/bn_BD.php | 15 +- apps/files/l10n/ca.php | 16 +- apps/files/l10n/cs_CZ.php | 8 +- apps/files/l10n/da.php | 17 +- apps/files/l10n/de.php | 21 +- apps/files/l10n/de_DE.php | 11 +- apps/files/l10n/el.php | 6 +- apps/files/l10n/eo.php | 11 +- apps/files/l10n/es.php | 18 +- apps/files/l10n/es_AR.php | 14 +- apps/files/l10n/et_EE.php | 6 +- apps/files/l10n/eu.php | 13 +- apps/files/l10n/fa.php | 23 +- apps/files/l10n/fi_FI.php | 10 +- apps/files/l10n/fr.php | 16 +- apps/files/l10n/gl.php | 10 +- apps/files/l10n/he.php | 10 +- apps/files/l10n/hr.php | 22 +- apps/files/l10n/hu_HU.php | 4 +- apps/files/l10n/ia.php | 2 +- apps/files/l10n/id.php | 6 +- apps/files/l10n/it.php | 12 +- apps/files/l10n/ja_JP.php | 14 +- apps/files/l10n/ka_GE.php | 2 +- apps/files/l10n/ko.php | 18 +- apps/files/l10n/lb.php | 4 +- apps/files/l10n/lt_LT.php | 8 +- apps/files/l10n/lv.php | 4 +- apps/files/l10n/mk.php | 10 +- apps/files/l10n/ms_MY.php | 17 +- apps/files/l10n/nb_NO.php | 13 +- apps/files/l10n/nl.php | 28 +- apps/files/l10n/nn_NO.php | 53 +- apps/files/l10n/oc.php | 3 +- apps/files/l10n/pl.php | 14 +- apps/files/l10n/pt_BR.php | 14 +- apps/files/l10n/pt_PT.php | 20 +- apps/files/l10n/ro.php | 24 +- apps/files/l10n/ru.php | 19 +- apps/files/l10n/si_LK.php | 13 +- apps/files/l10n/sk_SK.php | 24 +- apps/files/l10n/sl.php | 17 +- apps/files/l10n/sr.php | 2 +- apps/files/l10n/sv.php | 11 +- apps/files/l10n/ta_LK.php | 5 +- apps/files/l10n/th_TH.php | 17 +- apps/files/l10n/tr.php | 14 +- apps/files/l10n/uk.php | 4 +- apps/files/l10n/ur_PK.php | 3 +- apps/files/l10n/vi.php | 15 +- apps/files/l10n/zh_CN.GB2312.php | 21 +- apps/files/l10n/zh_CN.php | 14 +- apps/files/templates/index.php | 3 +- apps/files_encryption/hooks/hooks.php | 7 +- apps/files_encryption/l10n/ca.php | 2 +- apps/files_encryption/l10n/de.php | 2 +- apps/files_encryption/l10n/de_DE.php | 2 +- apps/files_encryption/l10n/el.php | 2 +- apps/files_encryption/l10n/eu.php | 2 +- apps/files_encryption/l10n/it.php | 2 +- apps/files_encryption/l10n/pl.php | 2 +- apps/files_encryption/l10n/pt_BR.php | 2 +- apps/files_encryption/l10n/ru.php | 2 +- apps/files_encryption/l10n/sk_SK.php | 2 +- apps/files_encryption/l10n/th_TH.php | 2 +- apps/files_encryption/l10n/vi.php | 2 +- apps/files_encryption/tests/crypt.php | 9 +- apps/files_encryption/tests/keymanager.php | 7 +- apps/files_encryption/tests/stream.php | 2 +- apps/files_encryption/tests/util.php | 9 +- apps/files_external/l10n/ar.php | 2 +- apps/files_external/l10n/bn_BD.php | 2 +- apps/files_external/l10n/ca.php | 2 +- apps/files_external/l10n/de.php | 1 - apps/files_external/l10n/de_DE.php | 1 - apps/files_external/l10n/el.php | 1 - apps/files_external/l10n/es.php | 2 +- apps/files_external/l10n/et_EE.php | 3 +- apps/files_external/l10n/fr.php | 1 - apps/files_external/l10n/lb.php | 1 - apps/files_external/l10n/nl.php | 1 - apps/files_external/l10n/pt_BR.php | 3 +- apps/files_external/l10n/ro.php | 3 - apps/files_external/l10n/ru.php | 1 - apps/files_external/l10n/sk_SK.php | 3 +- apps/files_external/l10n/sl.php | 5 +- apps/files_external/l10n/zh_TW.php | 20 +- apps/files_sharing/l10n/bn_BD.php | 2 +- apps/files_sharing/l10n/de_DE.php | 4 +- apps/files_sharing/l10n/he.php | 2 +- apps/files_sharing/l10n/hi.php | 3 - apps/files_sharing/l10n/hr.php | 6 - apps/files_sharing/l10n/hy.php | 4 - apps/files_sharing/l10n/ia.php | 6 - apps/files_sharing/l10n/ku_IQ.php | 2 +- apps/files_sharing/l10n/lb.php | 5 +- apps/files_sharing/l10n/lt_LT.php | 8 +- apps/files_sharing/l10n/lv.php | 2 +- apps/files_sharing/l10n/ms_MY.php | 6 - apps/files_sharing/l10n/nn_NO.php | 6 - apps/files_sharing/l10n/oc.php | 6 - apps/files_sharing/l10n/pt_BR.php | 2 +- apps/files_sharing/l10n/si_LK.php | 4 +- apps/files_sharing/l10n/sk_SK.php | 2 +- apps/files_sharing/l10n/sr.php | 3 +- apps/files_sharing/l10n/sr@latin.php | 5 - apps/files_sharing/l10n/tr.php | 2 +- apps/files_sharing/l10n/uk.php | 2 +- apps/files_sharing/l10n/zh_TW.php | 6 +- apps/files_sharing/lib/cache.php | 2 +- apps/files_sharing/lib/sharedstorage.php | 2 +- apps/files_trashbin/l10n/id.php | 8 +- apps/files_trashbin/l10n/nn_NO.php | 5 - apps/files_trashbin/l10n/pl.php | 4 +- apps/files_trashbin/l10n/pt_PT.php | 2 +- apps/files_trashbin/l10n/ro.php | 1 - apps/files_trashbin/l10n/sk_SK.php | 2 +- apps/files_trashbin/lib/trash.php | 395 +++----------- apps/files_versions/l10n/et_EE.php | 2 +- apps/files_versions/l10n/he.php | 4 +- apps/files_versions/l10n/ku_IQ.php | 4 +- apps/files_versions/l10n/nb_NO.php | 4 +- apps/files_versions/l10n/ro.php | 12 +- apps/files_versions/l10n/si_LK.php | 4 +- apps/files_versions/l10n/ta_LK.php | 4 +- apps/files_versions/l10n/th_TH.php | 4 +- apps/files_versions/l10n/vi.php | 1 - apps/user_ldap/l10n/ca.php | 2 +- apps/user_ldap/l10n/fa.php | 2 +- apps/user_ldap/l10n/gl.php | 2 +- apps/user_ldap/l10n/hi.php | 1 - apps/user_ldap/l10n/hr.php | 1 - apps/user_ldap/l10n/ia.php | 1 - apps/user_ldap/l10n/id.php | 8 +- apps/user_ldap/l10n/ku_IQ.php | 1 - apps/user_ldap/l10n/ms_MY.php | 1 - apps/user_ldap/l10n/nn_NO.php | 1 - apps/user_ldap/l10n/oc.php | 1 - apps/user_ldap/l10n/pl.php | 2 +- apps/user_ldap/l10n/pt_PT.php | 2 +- apps/user_ldap/l10n/sr@latin.php | 1 - apps/user_ldap/l10n/tr.php | 21 - core/css/styles.css | 6 +- core/js/jquery-showpassword.js | 14 +- core/l10n/ar.php | 20 +- core/l10n/bg_BG.php | 51 +- core/l10n/bn_BD.php | 16 +- core/l10n/ca.php | 6 +- core/l10n/cs_CZ.php | 6 +- core/l10n/cy_GB.php | 2 + core/l10n/da.php | 6 +- core/l10n/de.php | 10 +- core/l10n/de_DE.php | 12 +- core/l10n/el.php | 8 +- core/l10n/eo.php | 3 +- core/l10n/es.php | 12 +- core/l10n/es_AR.php | 40 +- core/l10n/et_EE.php | 13 +- core/l10n/eu.php | 4 +- core/l10n/fa.php | 18 +- core/l10n/fi_FI.php | 45 +- core/l10n/fr.php | 10 +- core/l10n/gl.php | 14 +- core/l10n/he.php | 8 +- core/l10n/hr.php | 6 +- core/l10n/hu_HU.php | 8 +- core/l10n/hy.php | 21 - core/l10n/id.php | 10 +- core/l10n/is.php | 14 +- core/l10n/it.php | 12 +- core/l10n/ja_JP.php | 10 +- core/l10n/ka_GE.php | 14 +- core/l10n/ko.php | 14 +- core/l10n/lb.php | 2 +- core/l10n/lt_LT.php | 2 +- core/l10n/lv.php | 8 +- core/l10n/mk.php | 6 +- core/l10n/ms_MY.php | 4 +- core/l10n/nb_NO.php | 2 +- core/l10n/nl.php | 12 +- core/l10n/nn_NO.php | 96 +--- core/l10n/oc.php | 28 +- core/l10n/pl.php | 4 +- core/l10n/pt_BR.php | 12 +- core/l10n/pt_PT.php | 14 +- core/l10n/ro.php | 23 +- core/l10n/ru.php | 14 +- core/l10n/ru_RU.php | 136 ++++- core/l10n/si_LK.php | 13 +- core/l10n/sk_SK.php | 14 +- core/l10n/sl.php | 10 +- core/l10n/sq.php | 6 +- core/l10n/sr.php | 14 +- core/l10n/sr@latin.php | 2 +- core/l10n/sv.php | 6 +- core/l10n/ta_LK.php | 16 +- core/l10n/th_TH.php | 10 +- core/l10n/tr.php | 6 +- core/l10n/uk.php | 8 +- core/l10n/vi.php | 14 +- core/l10n/zh_CN.GB2312.php | 14 +- core/l10n/zh_CN.php | 12 +- core/l10n/zh_HK.php | 2 + core/l10n/zh_TW.php | 8 +- core/lostpassword/templates/lostpassword.php | 31 +- core/templates/layout.user.php | 3 - l10n/.tx/config | 3 - l10n/af_ZA/core.po | 75 ++- l10n/af_ZA/files.po | 14 +- l10n/af_ZA/files_encryption.po | 4 +- l10n/af_ZA/files_external.po | 15 +- l10n/af_ZA/files_sharing.po | 4 +- l10n/af_ZA/files_trashbin.po | 4 +- l10n/af_ZA/files_versions.po | 4 +- l10n/af_ZA/lib.po | 55 +- l10n/af_ZA/settings.po | 80 +-- l10n/af_ZA/user_ldap.po | 4 +- l10n/ar/core.po | 96 ++-- l10n/ar/files.po | 22 +- l10n/ar/files_encryption.po | 6 +- l10n/ar/files_external.po | 17 +- l10n/ar/files_sharing.po | 5 +- l10n/ar/files_trashbin.po | 5 +- l10n/ar/files_versions.po | 5 +- l10n/ar/lib.po | 58 ++- l10n/ar/settings.po | 95 ++-- l10n/ar/user_ldap.po | 4 +- l10n/be/core.po | 75 ++- l10n/be/files.po | 14 +- l10n/be/files_encryption.po | 4 +- l10n/be/files_external.po | 15 +- l10n/be/files_sharing.po | 4 +- l10n/be/files_trashbin.po | 4 +- l10n/be/files_versions.po | 4 +- l10n/be/lib.po | 55 +- l10n/be/settings.po | 78 +-- l10n/be/user_ldap.po | 4 +- l10n/bg_BG/core.po | 182 ++++--- l10n/bg_BG/files.po | 28 +- l10n/bg_BG/files_encryption.po | 5 +- l10n/bg_BG/files_external.po | 18 +- l10n/bg_BG/files_sharing.po | 5 +- l10n/bg_BG/files_trashbin.po | 8 +- l10n/bg_BG/files_versions.po | 9 +- l10n/bg_BG/lib.po | 57 +- l10n/bg_BG/settings.po | 97 ++-- l10n/bg_BG/user_ldap.po | 4 +- l10n/bn_BD/core.po | 90 ++-- l10n/bn_BD/files.po | 29 +- l10n/bn_BD/files_encryption.po | 4 +- l10n/bn_BD/files_external.po | 17 +- l10n/bn_BD/files_sharing.po | 6 +- l10n/bn_BD/files_trashbin.po | 4 +- l10n/bn_BD/files_versions.po | 4 +- l10n/bn_BD/lib.po | 61 ++- l10n/bn_BD/settings.po | 87 ++-- l10n/bn_BD/user_ldap.po | 4 +- l10n/ca/core.po | 82 ++- l10n/ca/files.po | 37 +- l10n/ca/files_encryption.po | 8 +- l10n/ca/files_external.po | 19 +- l10n/ca/files_sharing.po | 5 +- l10n/ca/files_trashbin.po | 5 +- l10n/ca/files_versions.po | 7 +- l10n/ca/lib.po | 59 ++- l10n/ca/settings.po | 94 ++-- l10n/ca/user_ldap.po | 8 +- l10n/cs_CZ/core.po | 49 +- l10n/cs_CZ/files.po | 25 +- l10n/cs_CZ/files_encryption.po | 6 +- l10n/cs_CZ/files_external.po | 19 +- l10n/cs_CZ/files_sharing.po | 7 +- l10n/cs_CZ/files_trashbin.po | 5 +- l10n/cs_CZ/files_versions.po | 6 +- l10n/cs_CZ/lib.po | 63 ++- l10n/cs_CZ/settings.po | 88 ++-- l10n/cs_CZ/user_ldap.po | 6 +- l10n/cy_GB/core.po | 57 +- l10n/cy_GB/files.po | 17 +- l10n/cy_GB/files_encryption.po | 4 +- l10n/cy_GB/files_external.po | 15 +- l10n/cy_GB/files_sharing.po | 7 +- l10n/cy_GB/files_trashbin.po | 7 +- l10n/cy_GB/files_versions.po | 4 +- l10n/cy_GB/lib.po | 58 ++- l10n/cy_GB/settings.po | 78 +-- l10n/cy_GB/user_ldap.po | 4 +- l10n/da/core.po | 89 ++-- l10n/da/files.po | 42 +- l10n/da/files_encryption.po | 7 +- l10n/da/files_external.po | 19 +- l10n/da/files_sharing.po | 6 +- l10n/da/files_trashbin.po | 6 +- l10n/da/files_versions.po | 8 +- l10n/da/lib.po | 70 ++- l10n/da/settings.po | 98 ++-- l10n/da/user_ldap.po | 9 +- l10n/de/core.po | 81 +-- l10n/de/files.po | 58 ++- l10n/de/files_encryption.po | 8 +- l10n/de/files_external.po | 24 +- l10n/de/files_sharing.po | 9 +- l10n/de/files_trashbin.po | 10 +- l10n/de/files_versions.po | 11 +- l10n/de/lib.po | 73 ++- l10n/de/settings.po | 101 ++-- l10n/de/user_ldap.po | 14 +- l10n/de_DE/core.po | 87 ++-- l10n/de_DE/files.po | 99 ++-- l10n/de_DE/files_encryption.po | 12 +- l10n/de_DE/files_external.po | 24 +- l10n/de_DE/files_sharing.po | 13 +- l10n/de_DE/files_trashbin.po | 11 +- l10n/de_DE/files_versions.po | 16 +- l10n/de_DE/lib.po | 70 ++- l10n/de_DE/settings.po | 110 ++-- l10n/de_DE/user_ldap.po | 18 +- l10n/el/core.po | 92 ++-- l10n/el/files.po | 30 +- l10n/el/files_encryption.po | 9 +- l10n/el/files_external.po | 25 +- l10n/el/files_sharing.po | 7 +- l10n/el/files_trashbin.po | 5 +- l10n/el/files_versions.po | 8 +- l10n/el/lib.po | 66 ++- l10n/el/settings.po | 103 ++-- l10n/el/user_ldap.po | 11 +- l10n/eo/core.po | 79 ++- l10n/eo/files.po | 29 +- l10n/eo/files_encryption.po | 5 +- l10n/eo/files_external.po | 16 +- l10n/eo/files_sharing.po | 5 +- l10n/eo/files_trashbin.po | 4 +- l10n/eo/files_versions.po | 6 +- l10n/eo/lib.po | 64 ++- l10n/eo/settings.po | 107 ++-- l10n/eo/user_ldap.po | 6 +- l10n/es/core.po | 59 ++- l10n/es/files.po | 46 +- l10n/es/files_encryption.po | 8 +- l10n/es/files_external.po | 22 +- l10n/es/files_sharing.po | 7 +- l10n/es/files_trashbin.po | 6 +- l10n/es/files_versions.po | 10 +- l10n/es/lib.po | 67 ++- l10n/es/settings.po | 111 ++-- l10n/es/user_ldap.po | 12 +- l10n/es_AR/core.po | 115 ++--- l10n/es_AR/files.po | 34 +- l10n/es_AR/files_encryption.po | 6 +- l10n/es_AR/files_external.po | 18 +- l10n/es_AR/files_sharing.po | 5 +- l10n/es_AR/files_trashbin.po | 5 +- l10n/es_AR/files_versions.po | 7 +- l10n/es_AR/lib.po | 71 ++- l10n/es_AR/settings.po | 90 ++-- l10n/es_AR/user_ldap.po | 7 +- l10n/et_EE/core.po | 87 ++-- l10n/et_EE/files.po | 23 +- l10n/et_EE/files_encryption.po | 7 +- l10n/et_EE/files_external.po | 22 +- l10n/et_EE/files_sharing.po | 7 +- l10n/et_EE/files_trashbin.po | 8 +- l10n/et_EE/files_versions.po | 11 +- l10n/et_EE/lib.po | 64 ++- l10n/et_EE/settings.po | 85 +-- l10n/et_EE/user_ldap.po | 6 +- l10n/et_EE/user_webdavauth.po | 10 +- l10n/eu/core.po | 80 ++- l10n/eu/files.po | 32 +- l10n/eu/files_encryption.po | 8 +- l10n/eu/files_external.po | 17 +- l10n/eu/files_sharing.po | 5 +- l10n/eu/files_trashbin.po | 5 +- l10n/eu/files_versions.po | 6 +- l10n/eu/lib.po | 67 ++- l10n/eu/settings.po | 90 ++-- l10n/eu/user_ldap.po | 6 +- l10n/fa/core.po | 94 ++-- l10n/fa/files.po | 40 +- l10n/fa/files_encryption.po | 7 +- l10n/fa/files_external.po | 16 +- l10n/fa/files_sharing.po | 6 +- l10n/fa/files_trashbin.po | 5 +- l10n/fa/files_versions.po | 7 +- l10n/fa/lib.po | 58 ++- l10n/fa/settings.po | 98 ++-- l10n/fa/user_ldap.po | 9 +- l10n/fi/core.po | 74 ++- l10n/fi/files.po | 16 +- l10n/fi/lib.po | 55 +- l10n/fi_FI/core.po | 126 +++-- l10n/fi_FI/files.po | 29 +- l10n/fi_FI/files_encryption.po | 5 +- l10n/fi_FI/files_external.po | 18 +- l10n/fi_FI/files_sharing.po | 6 +- l10n/fi_FI/files_trashbin.po | 5 +- l10n/fi_FI/files_versions.po | 5 +- l10n/fi_FI/lib.po | 58 ++- l10n/fi_FI/settings.po | 90 ++-- l10n/fi_FI/user_ldap.po | 7 +- l10n/fr/core.po | 95 ++-- l10n/fr/files.po | 47 +- l10n/fr/files_encryption.po | 5 +- l10n/fr/files_external.po | 18 +- l10n/fr/files_sharing.po | 9 +- l10n/fr/files_trashbin.po | 6 +- l10n/fr/files_versions.po | 6 +- l10n/fr/lib.po | 63 ++- l10n/fr/settings.po | 106 ++-- l10n/fr/user_ldap.po | 12 +- l10n/gl/core.po | 89 ++-- l10n/gl/files.po | 29 +- l10n/gl/files_encryption.po | 6 +- l10n/gl/files_external.po | 18 +- l10n/gl/files_sharing.po | 6 +- l10n/gl/files_trashbin.po | 5 +- l10n/gl/files_versions.po | 8 +- l10n/gl/lib.po | 63 ++- l10n/gl/settings.po | 89 ++-- l10n/gl/user_ldap.po | 11 +- l10n/he/core.po | 85 ++- l10n/he/files.po | 28 +- l10n/he/files_encryption.po | 5 +- l10n/he/files_external.po | 17 +- l10n/he/files_sharing.po | 7 +- l10n/he/files_trashbin.po | 5 +- l10n/he/files_versions.po | 8 +- l10n/he/lib.po | 57 +- l10n/he/settings.po | 94 ++-- l10n/he/user_ldap.po | 5 +- l10n/hi/core.po | 76 ++- l10n/hi/files.po | 14 +- l10n/hi/files_encryption.po | 4 +- l10n/hi/files_external.po | 15 +- l10n/hi/files_sharing.po | 6 +- l10n/hi/files_trashbin.po | 4 +- l10n/hi/files_versions.po | 4 +- l10n/hi/lib.po | 55 +- l10n/hi/settings.po | 80 +-- l10n/hi/user_ldap.po | 6 +- l10n/hr/core.po | 84 ++- l10n/hr/files.po | 39 +- l10n/hr/files_encryption.po | 4 +- l10n/hr/files_external.po | 15 +- l10n/hr/files_sharing.po | 12 +- l10n/hr/files_trashbin.po | 4 +- l10n/hr/files_versions.po | 4 +- l10n/hr/lib.po | 57 +- l10n/hr/settings.po | 89 ++-- l10n/hr/user_ldap.po | 6 +- l10n/hu_HU/core.po | 85 ++- l10n/hu_HU/files.po | 25 +- l10n/hu_HU/files_encryption.po | 8 +- l10n/hu_HU/files_external.po | 16 +- l10n/hu_HU/files_sharing.po | 5 +- l10n/hu_HU/files_trashbin.po | 6 +- l10n/hu_HU/files_versions.po | 5 +- l10n/hu_HU/lib.po | 64 ++- l10n/hu_HU/settings.po | 86 +-- l10n/hu_HU/user_ldap.po | 6 +- l10n/hy/core.po | 456 +++++----------- l10n/hy/files.po | 16 +- l10n/hy/files_external.po | 17 +- l10n/hy/files_sharing.po | 22 +- l10n/hy/files_trashbin.po | 6 +- l10n/hy/settings.po | 82 +-- l10n/ia/core.po | 75 ++- l10n/ia/files.po | 18 +- l10n/ia/files_encryption.po | 4 +- l10n/ia/files_external.po | 15 +- l10n/ia/files_sharing.po | 12 +- l10n/ia/files_trashbin.po | 4 +- l10n/ia/files_versions.po | 4 +- l10n/ia/lib.po | 57 +- l10n/ia/settings.po | 86 +-- l10n/ia/user_ldap.po | 6 +- l10n/id/core.po | 91 ++-- l10n/id/files.po | 25 +- l10n/id/files_encryption.po | 6 +- l10n/id/files_external.po | 18 +- l10n/id/files_sharing.po | 6 +- l10n/id/files_trashbin.po | 14 +- l10n/id/files_versions.po | 7 +- l10n/id/lib.po | 58 ++- l10n/id/settings.po | 92 ++-- l10n/id/user_ldap.po | 15 +- l10n/is/core.po | 88 ++-- l10n/is/files.po | 15 +- l10n/is/files_encryption.po | 5 +- l10n/is/files_external.po | 16 +- l10n/is/files_sharing.po | 5 +- l10n/is/files_trashbin.po | 4 +- l10n/is/files_versions.po | 5 +- l10n/is/lib.po | 56 +- l10n/is/settings.po | 81 +-- l10n/is/user_ldap.po | 5 +- l10n/it/core.po | 89 ++-- l10n/it/files.po | 30 +- l10n/it/files_encryption.po | 7 +- l10n/it/files_external.po | 17 +- l10n/it/files_sharing.po | 5 +- l10n/it/files_trashbin.po | 5 +- l10n/it/files_versions.po | 5 +- l10n/it/lib.po | 62 ++- l10n/it/settings.po | 89 ++-- l10n/it/user_ldap.po | 6 +- l10n/ja_JP/core.po | 88 ++-- l10n/ja_JP/files.po | 33 +- l10n/ja_JP/files_encryption.po | 6 +- l10n/ja_JP/files_external.po | 18 +- l10n/ja_JP/files_sharing.po | 6 +- l10n/ja_JP/files_trashbin.po | 5 +- l10n/ja_JP/files_versions.po | 8 +- l10n/ja_JP/lib.po | 68 ++- l10n/ja_JP/settings.po | 93 ++-- l10n/ja_JP/user_ldap.po | 8 +- l10n/ka/core.po | 74 ++- l10n/ka/files.po | 14 +- l10n/ka/files_encryption.po | 4 +- l10n/ka/files_external.po | 15 +- l10n/ka/files_sharing.po | 5 +- l10n/ka/files_trashbin.po | 4 +- l10n/ka/files_versions.po | 4 +- l10n/ka/lib.po | 56 +- l10n/ka/settings.po | 80 +-- l10n/ka/user_ldap.po | 4 +- l10n/ka_GE/core.po | 70 ++- l10n/ka_GE/files.po | 20 +- l10n/ka_GE/files_encryption.po | 7 +- l10n/ka_GE/files_external.po | 18 +- l10n/ka_GE/files_sharing.po | 8 +- l10n/ka_GE/files_trashbin.po | 7 +- l10n/ka_GE/files_versions.po | 7 +- l10n/ka_GE/lib.po | 57 +- l10n/ka_GE/settings.po | 83 +-- l10n/ka_GE/user_ldap.po | 7 +- l10n/kn/core.po | 74 ++- l10n/kn/files.po | 14 +- l10n/kn/files_encryption.po | 4 +- l10n/kn/files_external.po | 15 +- l10n/kn/files_sharing.po | 4 +- l10n/kn/files_trashbin.po | 4 +- l10n/kn/files_versions.po | 4 +- l10n/kn/lib.po | 55 +- l10n/kn/settings.po | 78 +-- l10n/kn/user_ldap.po | 4 +- l10n/ko/core.po | 98 ++-- l10n/ko/files.po | 38 +- l10n/ko/files_encryption.po | 6 +- l10n/ko/files_external.po | 19 +- l10n/ko/files_sharing.po | 7 +- l10n/ko/files_trashbin.po | 4 +- l10n/ko/files_versions.po | 7 +- l10n/ko/lib.po | 58 ++- l10n/ko/settings.po | 93 ++-- l10n/ko/user_ldap.po | 8 +- l10n/ku_IQ/core.po | 75 ++- l10n/ku_IQ/files.po | 14 +- l10n/ku_IQ/files_encryption.po | 5 +- l10n/ku_IQ/files_external.po | 15 +- l10n/ku_IQ/files_sharing.po | 7 +- l10n/ku_IQ/files_trashbin.po | 4 +- l10n/ku_IQ/files_versions.po | 7 +- l10n/ku_IQ/lib.po | 57 +- l10n/ku_IQ/settings.po | 80 +-- l10n/ku_IQ/user_ldap.po | 6 +- l10n/lb/core.po | 78 ++- l10n/lb/files.po | 19 +- l10n/lb/files_encryption.po | 4 +- l10n/lb/files_external.po | 17 +- l10n/lb/files_sharing.po | 10 +- l10n/lb/files_trashbin.po | 4 +- l10n/lb/files_versions.po | 5 +- l10n/lb/lib.po | 59 ++- l10n/lb/settings.po | 99 ++-- l10n/lb/user_ldap.po | 4 +- l10n/lt_LT/core.po | 78 ++- l10n/lt_LT/files.po | 25 +- l10n/lt_LT/files_encryption.po | 5 +- l10n/lt_LT/files_external.po | 18 +- l10n/lt_LT/files_sharing.po | 13 +- l10n/lt_LT/files_trashbin.po | 4 +- l10n/lt_LT/files_versions.po | 7 +- l10n/lt_LT/lib.po | 65 ++- l10n/lt_LT/settings.po | 94 ++-- l10n/lt_LT/user_ldap.po | 5 +- l10n/lv/core.po | 82 ++- l10n/lv/files.po | 21 +- l10n/lv/files_encryption.po | 5 +- l10n/lv/files_external.po | 16 +- l10n/lv/files_sharing.po | 7 +- l10n/lv/files_trashbin.po | 5 +- l10n/lv/files_versions.po | 5 +- l10n/lv/lib.po | 56 +- l10n/lv/settings.po | 85 +-- l10n/lv/user_ldap.po | 5 +- l10n/mk/core.po | 81 ++- l10n/mk/files.po | 27 +- l10n/mk/files_encryption.po | 5 +- l10n/mk/files_external.po | 16 +- l10n/mk/files_sharing.po | 5 +- l10n/mk/files_trashbin.po | 4 +- l10n/mk/files_versions.po | 5 +- l10n/mk/lib.po | 58 ++- l10n/mk/settings.po | 89 ++-- l10n/mk/user_ldap.po | 5 +- l10n/ms_MY/core.po | 81 ++- l10n/ms_MY/files.po | 34 +- l10n/ms_MY/files_encryption.po | 4 +- l10n/ms_MY/files_external.po | 15 +- l10n/ms_MY/files_sharing.po | 12 +- l10n/ms_MY/files_trashbin.po | 4 +- l10n/ms_MY/files_versions.po | 4 +- l10n/ms_MY/lib.po | 57 +- l10n/ms_MY/settings.po | 94 ++-- l10n/ms_MY/user_ldap.po | 6 +- l10n/my_MM/core.po | 75 ++- l10n/my_MM/files.po | 14 +- l10n/my_MM/files_encryption.po | 4 +- l10n/my_MM/files_external.po | 15 +- l10n/my_MM/files_sharing.po | 4 +- l10n/my_MM/files_trashbin.po | 4 +- l10n/my_MM/files_versions.po | 4 +- l10n/my_MM/lib.po | 56 +- l10n/my_MM/settings.po | 80 +-- l10n/my_MM/user_ldap.po | 4 +- l10n/nb_NO/core.po | 83 ++- l10n/nb_NO/files.po | 37 +- l10n/nb_NO/files_encryption.po | 6 +- l10n/nb_NO/files_external.po | 17 +- l10n/nb_NO/files_sharing.po | 6 +- l10n/nb_NO/files_trashbin.po | 5 +- l10n/nb_NO/files_versions.po | 8 +- l10n/nb_NO/lib.po | 64 ++- l10n/nb_NO/settings.po | 110 ++-- l10n/nb_NO/user_ldap.po | 6 +- l10n/ne/core.po | 74 ++- l10n/ne/files.po | 14 +- l10n/ne/files_encryption.po | 4 +- l10n/ne/files_external.po | 15 +- l10n/ne/files_sharing.po | 4 +- l10n/ne/files_trashbin.po | 4 +- l10n/ne/files_versions.po | 4 +- l10n/ne/lib.po | 55 +- l10n/ne/settings.po | 78 +-- l10n/ne/user_ldap.po | 4 +- l10n/nl/core.po | 97 ++-- l10n/nl/files.po | 54 +- l10n/nl/files_encryption.po | 7 +- l10n/nl/files_external.po | 20 +- l10n/nl/files_sharing.po | 6 +- l10n/nl/files_trashbin.po | 5 +- l10n/nl/files_versions.po | 6 +- l10n/nl/lib.po | 59 ++- l10n/nl/settings.po | 109 ++-- l10n/nl/user_ldap.po | 7 +- l10n/nn_NO/core.po | 251 +++++---- l10n/nn_NO/files.po | 167 +++--- l10n/nn_NO/files_encryption.po | 4 +- l10n/nn_NO/files_external.po | 15 +- l10n/nn_NO/files_sharing.po | 12 +- l10n/nn_NO/files_trashbin.po | 14 +- l10n/nn_NO/files_versions.po | 4 +- l10n/nn_NO/lib.po | 79 +-- l10n/nn_NO/settings.po | 261 +++++----- l10n/nn_NO/user_ldap.po | 6 +- l10n/oc/core.po | 105 ++-- l10n/oc/files.po | 19 +- l10n/oc/files_encryption.po | 4 +- l10n/oc/files_external.po | 15 +- l10n/oc/files_sharing.po | 12 +- l10n/oc/files_trashbin.po | 4 +- l10n/oc/files_versions.po | 4 +- l10n/oc/lib.po | 56 +- l10n/oc/settings.po | 95 ++-- l10n/oc/user_ldap.po | 6 +- l10n/pl/core.po | 89 ++-- l10n/pl/files.po | 38 +- l10n/pl/files_encryption.po | 8 +- l10n/pl/files_external.po | 19 +- l10n/pl/files_sharing.po | 7 +- l10n/pl/files_trashbin.po | 9 +- l10n/pl/files_versions.po | 8 +- l10n/pl/lib.po | 71 ++- l10n/pl/settings.po | 98 ++-- l10n/pl/user_ldap.po | 11 +- l10n/pl_PL/core.po | 76 ++- l10n/pl_PL/files.po | 18 +- l10n/pl_PL/lib.po | 57 +- l10n/pl_PL/settings.po | 84 +-- l10n/pt_BR/core.po | 97 ++-- l10n/pt_BR/files.po | 40 +- l10n/pt_BR/files_encryption.po | 8 +- l10n/pt_BR/files_external.po | 23 +- l10n/pt_BR/files_sharing.po | 7 +- l10n/pt_BR/files_trashbin.po | 5 +- l10n/pt_BR/files_versions.po | 8 +- l10n/pt_BR/lib.po | 60 ++- l10n/pt_BR/settings.po | 106 ++-- l10n/pt_BR/user_ldap.po | 9 +- l10n/pt_PT/core.po | 96 ++-- l10n/pt_PT/files.po | 42 +- l10n/pt_PT/files_encryption.po | 6 +- l10n/pt_PT/files_external.po | 18 +- l10n/pt_PT/files_sharing.po | 6 +- l10n/pt_PT/files_trashbin.po | 8 +- l10n/pt_PT/files_versions.po | 7 +- l10n/pt_PT/lib.po | 67 ++- l10n/pt_PT/settings.po | 98 ++-- l10n/pt_PT/user_ldap.po | 11 +- l10n/ro/core.po | 111 ++-- l10n/ro/files.po | 53 +- l10n/ro/files_encryption.po | 6 +- l10n/ro/files_external.po | 21 +- l10n/ro/files_sharing.po | 5 +- l10n/ro/files_trashbin.po | 6 +- l10n/ro/files_versions.po | 23 +- l10n/ro/lib.po | 58 ++- l10n/ro/settings.po | 125 +++-- l10n/ro/user_ldap.po | 7 +- l10n/ru/core.po | 97 ++-- l10n/ru/files.po | 48 +- l10n/ru/files_encryption.po | 8 +- l10n/ru/files_external.po | 19 +- l10n/ru/files_sharing.po | 8 +- l10n/ru/files_trashbin.po | 5 +- l10n/ru/files_versions.po | 8 +- l10n/ru/lib.po | 69 ++- l10n/ru/settings.po | 106 ++-- l10n/ru/user_ldap.po | 9 +- l10n/ru_RU/core.po | 349 ++++++------- l10n/ru_RU/files.po | 22 +- l10n/ru_RU/lib.po | 122 +++-- l10n/ru_RU/settings.po | 214 ++++---- l10n/si_LK/core.po | 89 ++-- l10n/si_LK/files.po | 28 +- l10n/si_LK/files_encryption.po | 5 +- l10n/si_LK/files_external.po | 16 +- l10n/si_LK/files_sharing.po | 9 +- l10n/si_LK/files_trashbin.po | 4 +- l10n/si_LK/files_versions.po | 7 +- l10n/si_LK/lib.po | 59 ++- l10n/si_LK/settings.po | 107 ++-- l10n/si_LK/user_ldap.po | 5 +- l10n/sk/core.po | 74 ++- l10n/sk/files.po | 14 +- l10n/sk/files_encryption.po | 4 +- l10n/sk/files_external.po | 15 +- l10n/sk/files_sharing.po | 4 +- l10n/sk/files_trashbin.po | 4 +- l10n/sk/files_versions.po | 4 +- l10n/sk/lib.po | 55 +- l10n/sk/settings.po | 78 +-- l10n/sk/user_ldap.po | 4 +- l10n/sk_SK/core.po | 94 ++-- l10n/sk_SK/files.po | 45 +- l10n/sk_SK/files_encryption.po | 9 +- l10n/sk_SK/files_external.po | 23 +- l10n/sk_SK/files_sharing.po | 8 +- l10n/sk_SK/files_trashbin.po | 8 +- l10n/sk_SK/files_versions.po | 7 +- l10n/sk_SK/lib.po | 61 ++- l10n/sk_SK/settings.po | 95 ++-- l10n/sk_SK/user_ldap.po | 6 +- l10n/sl/core.po | 67 ++- l10n/sl/files.po | 35 +- l10n/sl/files_encryption.po | 7 +- l10n/sl/files_external.po | 25 +- l10n/sl/files_sharing.po | 6 +- l10n/sl/files_trashbin.po | 8 +- l10n/sl/files_versions.po | 7 +- l10n/sl/lib.po | 64 ++- l10n/sl/settings.po | 95 ++-- l10n/sl/user_ldap.po | 7 +- l10n/sq/core.po | 78 ++- l10n/sq/files.po | 15 +- l10n/sq/files_encryption.po | 4 +- l10n/sq/files_external.po | 15 +- l10n/sq/files_sharing.po | 5 +- l10n/sq/files_trashbin.po | 5 +- l10n/sq/files_versions.po | 4 +- l10n/sq/lib.po | 58 ++- l10n/sq/settings.po | 83 +-- l10n/sq/user_ldap.po | 4 +- l10n/sr/core.po | 89 ++-- l10n/sr/files.po | 20 +- l10n/sr/files_encryption.po | 6 +- l10n/sr/files_external.po | 15 +- l10n/sr/files_sharing.po | 6 +- l10n/sr/files_trashbin.po | 5 +- l10n/sr/files_versions.po | 5 +- l10n/sr/lib.po | 60 ++- l10n/sr/settings.po | 87 ++-- l10n/sr/user_ldap.po | 5 +- l10n/sr@latin/core.po | 77 ++- l10n/sr@latin/files.po | 15 +- l10n/sr@latin/files_encryption.po | 4 +- l10n/sr@latin/files_external.po | 15 +- l10n/sr@latin/files_sharing.po | 10 +- l10n/sr@latin/files_trashbin.po | 4 +- l10n/sr@latin/files_versions.po | 4 +- l10n/sr@latin/lib.po | 57 +- l10n/sr@latin/settings.po | 81 +-- l10n/sr@latin/user_ldap.po | 6 +- l10n/sv/core.po | 85 ++- l10n/sv/files.po | 33 +- l10n/sv/files_encryption.po | 6 +- l10n/sv/files_external.po | 17 +- l10n/sv/files_sharing.po | 5 +- l10n/sv/files_trashbin.po | 6 +- l10n/sv/files_versions.po | 5 +- l10n/sv/lib.po | 61 ++- l10n/sv/settings.po | 107 ++-- l10n/sv/user_ldap.po | 7 +- l10n/sw_KE/core.po | 74 ++- l10n/sw_KE/files.po | 14 +- l10n/sw_KE/files_encryption.po | 4 +- l10n/sw_KE/files_external.po | 15 +- l10n/sw_KE/files_sharing.po | 4 +- l10n/sw_KE/files_trashbin.po | 4 +- l10n/sw_KE/files_versions.po | 4 +- l10n/sw_KE/lib.po | 55 +- l10n/sw_KE/settings.po | 78 +-- l10n/sw_KE/user_ldap.po | 4 +- l10n/ta_LK/core.po | 90 ++-- l10n/ta_LK/files.po | 19 +- l10n/ta_LK/files_encryption.po | 5 +- l10n/ta_LK/files_external.po | 16 +- l10n/ta_LK/files_sharing.po | 5 +- l10n/ta_LK/files_trashbin.po | 4 +- l10n/ta_LK/files_versions.po | 7 +- l10n/ta_LK/lib.po | 58 ++- l10n/ta_LK/settings.po | 87 ++-- l10n/ta_LK/user_ldap.po | 5 +- l10n/te/core.po | 75 ++- l10n/te/files.po | 15 +- l10n/te/files_encryption.po | 4 +- l10n/te/files_external.po | 15 +- l10n/te/files_sharing.po | 4 +- l10n/te/files_trashbin.po | 4 +- l10n/te/files_versions.po | 4 +- l10n/te/lib.po | 55 +- l10n/te/settings.po | 81 +-- l10n/te/user_ldap.po | 4 +- l10n/templates/core.pot | 34 +- l10n/templates/files.pot | 58 +-- l10n/templates/files_encryption.pot | 2 +- l10n/templates/files_external.pot | 13 +- l10n/templates/files_sharing.pot | 2 +- l10n/templates/files_trashbin.pot | 2 +- l10n/templates/files_versions.pot | 2 +- l10n/templates/lib.pot | 19 +- l10n/templates/settings.pot | 74 +-- l10n/templates/user_ldap.pot | 2 +- l10n/templates/user_webdavauth.pot | 2 +- l10n/th_TH/core.po | 84 ++- l10n/th_TH/files.po | 34 +- l10n/th_TH/files_encryption.po | 7 +- l10n/th_TH/files_external.po | 16 +- l10n/th_TH/files_sharing.po | 5 +- l10n/th_TH/files_trashbin.po | 5 +- l10n/th_TH/files_versions.po | 7 +- l10n/th_TH/lib.po | 62 ++- l10n/th_TH/settings.po | 119 +++-- l10n/th_TH/user_ldap.po | 5 +- l10n/tr/core.po | 50 +- l10n/tr/files.po | 35 +- l10n/tr/files_encryption.po | 6 +- l10n/tr/files_external.po | 21 +- l10n/tr/files_sharing.po | 7 +- l10n/tr/files_trashbin.po | 6 +- l10n/tr/files_versions.po | 7 +- l10n/tr/lib.po | 28 +- l10n/tr/settings.po | 93 ++-- l10n/tr/user_ldap.po | 48 +- l10n/uk/core.po | 86 ++- l10n/uk/files.po | 22 +- l10n/uk/files_encryption.po | 6 +- l10n/uk/files_external.po | 18 +- l10n/uk/files_sharing.po | 8 +- l10n/uk/files_trashbin.po | 5 +- l10n/uk/files_versions.po | 6 +- l10n/uk/lib.po | 60 ++- l10n/uk/settings.po | 86 +-- l10n/uk/user_ldap.po | 7 +- l10n/ur_PK/core.po | 75 ++- l10n/ur_PK/files.po | 16 +- l10n/ur_PK/files_encryption.po | 4 +- l10n/ur_PK/files_external.po | 15 +- l10n/ur_PK/files_sharing.po | 4 +- l10n/ur_PK/files_trashbin.po | 4 +- l10n/ur_PK/files_versions.po | 4 +- l10n/ur_PK/lib.po | 55 +- l10n/ur_PK/settings.po | 80 +-- l10n/ur_PK/user_ldap.po | 4 +- l10n/vi/core.po | 94 ++-- l10n/vi/files.po | 35 +- l10n/vi/files_encryption.po | 8 +- l10n/vi/files_external.po | 18 +- l10n/vi/files_sharing.po | 6 +- l10n/vi/files_trashbin.po | 5 +- l10n/vi/files_versions.po | 9 +- l10n/vi/lib.po | 63 ++- l10n/vi/settings.po | 119 +++-- l10n/vi/user_ldap.po | 7 +- l10n/zh_CN.GB2312/core.po | 89 ++-- l10n/zh_CN.GB2312/files.po | 38 +- l10n/zh_CN.GB2312/files_encryption.po | 5 +- l10n/zh_CN.GB2312/files_external.po | 17 +- l10n/zh_CN.GB2312/files_sharing.po | 5 +- l10n/zh_CN.GB2312/files_trashbin.po | 4 +- l10n/zh_CN.GB2312/files_versions.po | 6 +- l10n/zh_CN.GB2312/lib.po | 56 +- l10n/zh_CN.GB2312/settings.po | 101 ++-- l10n/zh_CN.GB2312/user_ldap.po | 5 +- l10n/zh_CN/core.po | 99 ++-- l10n/zh_CN/files.po | 37 +- l10n/zh_CN/files_encryption.po | 6 +- l10n/zh_CN/files_external.po | 18 +- l10n/zh_CN/files_sharing.po | 5 +- l10n/zh_CN/files_trashbin.po | 5 +- l10n/zh_CN/files_versions.po | 6 +- l10n/zh_CN/lib.po | 64 ++- l10n/zh_CN/settings.po | 96 ++-- l10n/zh_CN/user_ldap.po | 6 +- l10n/zh_HK/core.po | 76 ++- l10n/zh_HK/files.po | 15 +- l10n/zh_HK/files_encryption.po | 5 +- l10n/zh_HK/files_external.po | 15 +- l10n/zh_HK/files_sharing.po | 4 +- l10n/zh_HK/files_trashbin.po | 4 +- l10n/zh_HK/files_versions.po | 5 +- l10n/zh_HK/lib.po | 55 +- l10n/zh_HK/settings.po | 80 +-- l10n/zh_HK/user_ldap.po | 4 +- l10n/zh_TW/core.po | 69 ++- l10n/zh_TW/files.po | 25 +- l10n/zh_TW/files_encryption.po | 7 +- l10n/zh_TW/files_external.po | 48 +- l10n/zh_TW/files_sharing.po | 16 +- l10n/zh_TW/files_trashbin.po | 8 +- l10n/zh_TW/files_versions.po | 6 +- l10n/zh_TW/lib.po | 62 ++- l10n/zh_TW/settings.po | 94 ++-- l10n/zh_TW/user_ldap.po | 5 +- lib/api.php | 6 +- lib/base.php | 26 +- lib/files/cache/cache.php | 49 +- lib/files/cache/scanner.php | 2 +- lib/files/cache/storage.php | 59 --- lib/files/filesystem.php | 39 +- lib/files/{mount => }/mount.php | 106 +++- lib/files/mount/manager.php | 120 ----- lib/files/storage/common.php | 10 +- lib/files/storage/local.php | 517 +++++++++---------- lib/files/storage/storage.php | 5 - lib/files/view.php | 2 +- lib/l10n/ar.php | 5 +- lib/l10n/bg_BG.php | 3 + lib/l10n/bn_BD.php | 10 +- lib/l10n/ca.php | 5 +- lib/l10n/cs_CZ.php | 9 +- lib/l10n/cy_GB.php | 3 + lib/l10n/da.php | 13 +- lib/l10n/de.php | 11 +- lib/l10n/de_DE.php | 7 +- lib/l10n/el.php | 9 +- lib/l10n/eo.php | 11 +- lib/l10n/es.php | 7 +- lib/l10n/es_AR.php | 15 +- lib/l10n/et_EE.php | 9 +- lib/l10n/eu.php | 13 +- lib/l10n/fi_FI.php | 5 +- lib/l10n/fr.php | 7 +- lib/l10n/gl.php | 7 +- lib/l10n/he.php | 3 + lib/l10n/hr.php | 1 - lib/l10n/hu_HU.php | 9 +- lib/l10n/ia.php | 1 - lib/l10n/id.php | 3 + lib/l10n/is.php | 3 + lib/l10n/it.php | 9 +- lib/l10n/ja_JP.php | 13 +- lib/l10n/ka_GE.php | 3 + lib/l10n/ko.php | 3 + lib/l10n/ku_IQ.php | 1 - lib/l10n/lb.php | 2 - lib/l10n/lt_LT.php | 13 +- lib/l10n/lv.php | 3 + lib/l10n/mk.php | 5 +- lib/l10n/ms_MY.php | 1 - lib/l10n/my_MM.php | 3 + lib/l10n/nb_NO.php | 7 +- lib/l10n/nl.php | 3 + lib/l10n/nn_NO.php | 13 +- lib/l10n/oc.php | 4 +- lib/l10n/pl.php | 15 +- lib/l10n/pt_BR.php | 3 + lib/l10n/pt_PT.php | 11 +- lib/l10n/ro.php | 3 + lib/l10n/ru.php | 9 +- lib/l10n/ru_RU.php | 36 +- lib/l10n/si_LK.php | 7 +- lib/l10n/sk_SK.php | 5 +- lib/l10n/sl.php | 9 +- lib/l10n/sq.php | 5 +- lib/l10n/sr.php | 5 +- lib/l10n/sr@latin.php | 1 - lib/l10n/sv.php | 7 +- lib/l10n/ta_LK.php | 5 +- lib/l10n/th_TH.php | 9 +- lib/l10n/tr.php | 5 +- lib/l10n/uk.php | 3 + lib/l10n/vi.php | 7 +- lib/l10n/zh_CN.GB2312.php | 5 +- lib/l10n/zh_CN.php | 9 +- lib/l10n/zh_TW.php | 3 + lib/public/share.php | 2 +- lib/request.php | 13 +- lib/templatelayout.php | 73 +-- lib/updater.php | 46 +- lib/user.php | 2 +- lib/util.php | 32 +- ocs/routes.php | 74 +-- settings/js/personal.js | 3 - settings/l10n/ar.php | 13 +- settings/l10n/bg_BG.php | 1 - settings/l10n/bn_BD.php | 6 +- settings/l10n/ca.php | 11 +- settings/l10n/cs_CZ.php | 6 +- settings/l10n/da.php | 9 +- settings/l10n/de.php | 6 +- settings/l10n/de_DE.php | 10 +- settings/l10n/el.php | 10 +- settings/l10n/eo.php | 12 - settings/l10n/es.php | 14 +- settings/l10n/es_AR.php | 9 +- settings/l10n/et_EE.php | 6 +- settings/l10n/eu.php | 9 +- settings/l10n/fa.php | 14 +- settings/l10n/fi_FI.php | 8 +- settings/l10n/fr.php | 8 +- settings/l10n/gl.php | 4 +- settings/l10n/he.php | 9 +- settings/l10n/hr.php | 3 - settings/l10n/hu_HU.php | 5 +- settings/l10n/ia.php | 2 - settings/l10n/id.php | 9 +- settings/l10n/it.php | 6 +- settings/l10n/ja_JP.php | 13 +- settings/l10n/ka_GE.php | 8 +- settings/l10n/ko.php | 5 +- settings/l10n/lb.php | 9 - settings/l10n/lt_LT.php | 8 +- settings/l10n/lv.php | 5 +- settings/l10n/mk.php | 4 +- settings/l10n/ms_MY.php | 7 +- settings/l10n/nb_NO.php | 13 +- settings/l10n/nl.php | 18 +- settings/l10n/nn_NO.php | 97 +--- settings/l10n/oc.php | 7 - settings/l10n/pl.php | 7 +- settings/l10n/pt_BR.php | 16 +- settings/l10n/pt_PT.php | 13 +- settings/l10n/ro.php | 22 +- settings/l10n/ru.php | 12 +- settings/l10n/ru_RU.php | 67 ++- settings/l10n/si_LK.php | 17 +- settings/l10n/sk_SK.php | 10 +- settings/l10n/sl.php | 10 +- settings/l10n/sq.php | 3 +- settings/l10n/sr.php | 7 +- settings/l10n/sv.php | 13 +- settings/l10n/ta_LK.php | 6 +- settings/l10n/th_TH.php | 21 +- settings/l10n/tr.php | 7 +- settings/l10n/uk.php | 5 +- settings/l10n/vi.php | 21 +- settings/l10n/zh_CN.GB2312.php | 16 +- settings/l10n/zh_CN.php | 11 +- settings/l10n/zh_TW.php | 9 +- settings/personal.php | 15 +- settings/templates/admin.php | 3 +- settings/templates/personal.php | 7 +- tests/lib/files/mount.php | 58 +++ tests/lib/files/mount/manager.php | 67 --- tests/lib/streamwrappers.php | 4 +- 1091 files changed, 15493 insertions(+), 14231 deletions(-) delete mode 100644 apps/files_sharing/l10n/hi.php delete mode 100644 apps/files_sharing/l10n/hr.php delete mode 100644 apps/files_sharing/l10n/hy.php delete mode 100644 apps/files_sharing/l10n/ia.php delete mode 100644 apps/files_sharing/l10n/ms_MY.php delete mode 100644 apps/files_sharing/l10n/nn_NO.php delete mode 100644 apps/files_sharing/l10n/oc.php delete mode 100644 apps/files_sharing/l10n/sr@latin.php delete mode 100644 core/l10n/hy.php delete mode 100644 lib/files/cache/storage.php rename lib/files/{mount => }/mount.php (54%) delete mode 100644 lib/files/mount/manager.php create mode 100644 tests/lib/files/mount.php delete mode 100644 tests/lib/files/mount/manager.php diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 296e54e356..a2d17fae7d 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -115,11 +115,6 @@ $(document).ready(function() { return false; }); - // Trigger cancelling of file upload - $('#uploadprogresswrapper .stop').on('click', function() { - Files.cancelUploads(); - }); - // Show trash bin $('#trash a').live('click', function() { window.location=OC.filePath('files_trashbin', '', 'index.php'); diff --git a/apps/files/l10n/ar.php b/apps/files/l10n/ar.php index a84adc3bb0..41e6a225a2 100644 --- a/apps/files/l10n/ar.php +++ b/apps/files/l10n/ar.php @@ -14,7 +14,7 @@ "Invalid directory." => "مسار غير صحيح.", "Files" => "الملÙات", "Delete permanently" => "حذ٠بشكل دائم", -"Delete" => "إلغاء", +"Delete" => "محذوÙ", "Rename" => "إعادة تسميه", "Pending" => "قيد الانتظار", "{new_name} already exists" => "{new_name} موجود مسبقا", @@ -37,14 +37,14 @@ "URL cannot be empty." => "عنوان ال URL لا يجوز أن يكون Ùارغا.", "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" => "إسم مجلد غير صحيح. استخدام مصطلح \"Shared\" محجوز للنظام", "Error" => "خطأ", -"Name" => "اسم", +"Name" => "الاسم", "Size" => "حجم", "Modified" => "معدل", "1 folder" => "مجلد عدد 1", "{count} folders" => "{count} مجلدات", "1 file" => "مل٠واحد", "{count} files" => "{count} ملÙات", -"Upload" => "رÙع", +"Upload" => "إرÙع", "File handling" => "التعامل مع الملÙ", "Maximum upload size" => "الحد الأقصى لحجم الملÙات التي يمكن رÙعها", "max. possible: " => "الحد الأقصى المسموح به", diff --git a/apps/files/l10n/bg_BG.php b/apps/files/l10n/bg_BG.php index 09e01745a4..c4bbca36f4 100644 --- a/apps/files/l10n/bg_BG.php +++ b/apps/files/l10n/bg_BG.php @@ -1,8 +1,4 @@ "Файлът е качен уÑпешно", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Файлът който Ñе опитвате да качите надвишава ÑтойноÑтите в MAX_FILE_SIZE в HTML формата.", -"The uploaded file was only partially uploaded" => "Файлът е качен чаÑтично", -"No file was uploaded" => "Фахлът не бе качен", "Missing a temporary folder" => "ЛипÑва временна папка", "Failed to write to disk" => "Възникна проблем при Ð·Ð°Ð¿Ð¸Ñ Ð² диÑка", "Invalid directory." => "Ðевалидна директориÑ.", @@ -33,7 +29,5 @@ "Cancel upload" => "Спри качването", "Nothing in here. Upload something!" => "ÐÑма нищо тук. Качете нещо.", "Download" => "ИзтеглÑне", -"Upload too large" => "Файлът който Ñте избрали за качване е прекалено голÑм", -"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Файловете които Ñе опитвате да качите Ñа по-големи от позволеното за Ñървъра.", -"Files are being scanned, please wait." => "Файловете Ñе претърÑват, изчакайте." +"Upload too large" => "Файлът който Ñте избрали за качване е прекалено голÑм" ); diff --git a/apps/files/l10n/bn_BD.php b/apps/files/l10n/bn_BD.php index 42c78ab347..640430716f 100644 --- a/apps/files/l10n/bn_BD.php +++ b/apps/files/l10n/bn_BD.php @@ -2,18 +2,17 @@ "Could not move %s - File with this name already exists" => "%s কে সà§à¦¥à¦¾à¦¨à¦¾à¦¨à§à¦¤à¦° করা সমà§à¦­à¦¬ হলো না - à¦à¦‡ নামের ফাইল বিদà§à¦¯à¦®à¦¾à¦¨", "Could not move %s" => "%s কে সà§à¦¥à¦¾à¦¨à¦¾à¦¨à§à¦¤à¦° করা সমà§à¦­à¦¬ হলো না", "Unable to rename file" => "ফাইলের নাম পরিবরà§à¦¤à¦¨ করা সমà§à¦­à¦¬ হলো না", -"No file was uploaded. Unknown error" => "কোন ফাইল আপলোড করা হয় নি। সমসà§à¦¯à¦¾à¦° কারণটি অজà§à¦žà¦¾à¦¤à¥¤", -"There is no error, the file uploaded with success" => "কোন সমসà§à¦¯à¦¾ হয় নি, ফাইল আপলোড সà§à¦¸à¦®à§à¦ªà¦¨à§à¦¨ হয়েছে।", +"No file was uploaded. Unknown error" => "কোন ফাইল আপলোড করা হয় নি। সমসà§à¦¯à¦¾ অজà§à¦žà¦¾à¦¤à¥¤", +"There is no error, the file uploaded with success" => "কোন সমসà§à¦¯à¦¾ নেই, ফাইল আপলোড সà§à¦¸à¦®à§à¦ªà¦¨à§à¦¨ হয়েছে", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "আপলোড করা ফাইলটি php.ini তে বরà§à¦£à¦¿à¦¤ upload_max_filesize নিরà§à¦¦à§‡à¦¶à¦¿à¦¤ আয়তন অতিকà§à¦°à¦® করছেঃ", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "আপলোড করা ফাইলটি HTML ফরà§à¦®à§‡ উলà§à¦²à¦¿à¦–িত MAX_FILE_SIZE নিরà§à¦§à¦¾à¦°à¦¿à¦¤ ফাইলের সরà§à¦¬à§‹à¦šà§à¦š আকার অতিকà§à¦°à¦® করতে চলেছে ", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "আপলোড করা ফাইলটি HTML ফরà§à¦®à§‡ নিরà§à¦§à¦¾à¦°à¦¿à¦¤ MAX_FILE_SIZE নিরà§à¦¦à§‡à¦¶à¦¿à¦¤ সরà§à¦¬à§‹à¦šà§à¦š আকার অতিকà§à¦°à¦® করেছে ", "The uploaded file was only partially uploaded" => "আপলোড করা ফাইলটি আংশিক আপলোড করা হয়েছে", "No file was uploaded" => "কোন ফাইল আপলোড করা হয় নি", -"Missing a temporary folder" => "অসà§à¦¥à¦¾à§Ÿà§€ ফোলà§à¦¡à¦¾à¦°à¦Ÿà¦¿ হারানো গিয়েছে", +"Missing a temporary folder" => "অসà§à¦¥à¦¾à§Ÿà§€ ফোলà§à¦¡à¦¾à¦° খোয়া গিয়েছে", "Failed to write to disk" => "ডিসà§à¦•à§‡ লিখতে বà§à¦¯à¦°à§à¦¥", "Invalid directory." => "ভà§à¦² ডিরেকà§à¦Ÿà¦°à¦¿", "Files" => "ফাইল", -"Share" => "ভাগাভাগি কর", -"Delete" => "মà§à¦›à§‡", +"Delete" => "মà§à¦›à§‡ ফেল", "Rename" => "পূনঃনামকরণ", "Pending" => "মà§à¦²à¦¤à§à¦¬à¦¿", "{new_name} already exists" => "{new_name} টি বিদà§à¦¯à¦®à¦¾à¦¨", @@ -33,7 +32,7 @@ "URL cannot be empty." => "URL ফাà¦à¦•à¦¾ রাখা যাবে না।", "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" => "ফোলà§à¦¡à¦¾à¦°à§‡à¦° নামটি সঠিক নয়। 'ভাগাভাগি করা' শà§à¦§à§à¦®à¦¾à¦¤à§à¦° Owncloud à¦à¦° জনà§à¦¯ সংরকà§à¦·à¦¿à¦¤à¥¤", "Error" => "সমসà§à¦¯à¦¾", -"Name" => "রাম", +"Name" => "নাম", "Size" => "আকার", "Modified" => "পরিবরà§à¦¤à¦¿à¦¤", "1 folder" => "১টি ফোলà§à¦¡à¦¾à¦°", @@ -48,7 +47,7 @@ "Enable ZIP-download" => "ZIP ডাউনলোড সকà§à¦°à¦¿à§Ÿ কর", "0 is unlimited" => "০ à¦à¦° অরà§à¦¥ অসীম", "Maximum input size for ZIP files" => "ZIP ফাইলের ইনপà§à¦Ÿà§‡à¦° সরà§à¦¬à§‹à¦šà§à¦š আকার", -"Save" => "সংরকà§à¦·à¦£", +"Save" => "সংরকà§à¦·à¦¨ কর", "New" => "নতà§à¦¨", "Text file" => "টেকà§à¦¸à¦Ÿ ফাইল", "Folder" => "ফোলà§à¦¡à¦¾à¦°", diff --git a/apps/files/l10n/ca.php b/apps/files/l10n/ca.php index a294fbdce4..d92dbeef67 100644 --- a/apps/files/l10n/ca.php +++ b/apps/files/l10n/ca.php @@ -3,20 +3,20 @@ "Could not move %s" => " No s'ha pogut moure %s", "Unable to rename file" => "No es pot canviar el nom del fitxer", "No file was uploaded. Unknown error" => "No s'ha carregat cap fitxer. Error desconegut", -"There is no error, the file uploaded with success" => "No hi ha errors, el fitxer s'ha carregat correctament", +"There is no error, the file uploaded with success" => "El fitxer s'ha pujat correctament", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "L’arxiu que voleu carregar supera el màxim definit en la directiva upload_max_filesize del php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "El fitxer carregat supera la directiva MAX_FILE_SIZE especificada al formulari HTML", -"The uploaded file was only partially uploaded" => "El fitxer només s'ha carregat parcialment", -"No file was uploaded" => "No s'ha carregat cap fitxer", -"Missing a temporary folder" => "Falta un fitxer temporal", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "El fitxer de pujada excedeix la directiva MAX_FILE_SIZE especificada al formulari HTML", +"The uploaded file was only partially uploaded" => "El fitxer només s'ha pujat parcialment", +"No file was uploaded" => "El fitxer no s'ha pujat", +"Missing a temporary folder" => "S'ha perdut un fitxer temporal", "Failed to write to disk" => "Ha fallat en escriure al disc", "Not enough storage available" => "No hi ha prou espai disponible", "Invalid directory." => "Directori no vàlid.", "Files" => "Fitxers", "Delete permanently" => "Esborra permanentment", -"Delete" => "Esborra", +"Delete" => "Suprimeix", "Rename" => "Reanomena", -"Pending" => "Pendent", +"Pending" => "Pendents", "{new_name} already exists" => "{new_name} ja existeix", "replace" => "substitueix", "suggest name" => "sugereix un nom", @@ -55,7 +55,7 @@ "0 is unlimited" => "0 és sense límit", "Maximum input size for ZIP files" => "Mida màxima d'entrada per fitxers ZIP", "Save" => "Desa", -"New" => "Nova", +"New" => "Nou", "Text file" => "Fitxer de text", "Folder" => "Carpeta", "From link" => "Des d'enllaç", diff --git a/apps/files/l10n/cs_CZ.php b/apps/files/l10n/cs_CZ.php index b434da7f28..66c748fbaa 100644 --- a/apps/files/l10n/cs_CZ.php +++ b/apps/files/l10n/cs_CZ.php @@ -16,7 +16,7 @@ "Delete permanently" => "Trvale odstranit", "Delete" => "Smazat", "Rename" => "PÅ™ejmenovat", -"Pending" => "Nevyřízené", +"Pending" => "ÄŒekající", "{new_name} already exists" => "{new_name} již existuje", "replace" => "nahradit", "suggest name" => "navrhnout název", @@ -32,7 +32,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "VaÅ¡e úložiÅ¡tÄ› je plné, nelze aktualizovat ani synchronizovat soubory.", "Your storage is almost full ({usedSpacePercent}%)" => "VaÅ¡e úložiÅ¡tÄ› je téměř plné ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "VaÅ¡e soubory ke stažení se pÅ™ipravují. Pokud jsou velké může to chvíli trvat.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Nelze odeslat Váš soubor, protože je to adresář, nebo je jeho velikost 0 bajtů", +"Unable to upload your file as it is a directory or has 0 bytes" => "Nelze odeslat Váš soubor, protože je to adresář nebo má velikost 0 bajtů", "Not enough space available" => "Nedostatek dostupného místa", "Upload cancelled." => "Odesílání zruÅ¡eno.", "File upload is in progress. Leaving the page now will cancel the upload." => "Probíhá odesílání souboru. OpuÅ¡tÄ›ní stránky vyústí ve zruÅ¡ení nahrávání.", @@ -41,7 +41,7 @@ "Error" => "Chyba", "Name" => "Název", "Size" => "Velikost", -"Modified" => "Upraveno", +"Modified" => "ZmÄ›nÄ›no", "1 folder" => "1 složka", "{count} folders" => "{count} složky", "1 file" => "1 soubor", @@ -65,7 +65,7 @@ "Nothing in here. Upload something!" => "Žádný obsah. Nahrajte nÄ›co.", "Download" => "Stáhnout", "Unshare" => "ZruÅ¡it sdílení", -"Upload too large" => "Odesílaný soubor je příliÅ¡ velký", +"Upload too large" => "Odeslaný soubor je příliÅ¡ velký", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Soubory, které se snažíte odeslat, pÅ™ekraÄují limit velikosti odesílání na tomto serveru.", "Files are being scanned, please wait." => "Soubory se prohledávají, prosím Äekejte.", "Current scanning" => "Aktuální prohledávání", diff --git a/apps/files/l10n/da.php b/apps/files/l10n/da.php index ff590aa9a3..7c065952ae 100644 --- a/apps/files/l10n/da.php +++ b/apps/files/l10n/da.php @@ -3,17 +3,16 @@ "Could not move %s" => "Kunne ikke flytte %s", "Unable to rename file" => "Kunne ikke omdøbe fil", "No file was uploaded. Unknown error" => "Ingen fil blev uploadet. Ukendt fejl.", -"There is no error, the file uploaded with success" => "Der skete ingen fejl, filen blev succesfuldt uploadet", +"There is no error, the file uploaded with success" => "Der er ingen fejl, filen blev uploadet med success", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Den uploadede fil overstiger upload_max_filesize direktivet i php.ini", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Den uploadede fil overstiger MAX_FILE_SIZE indstilingen, som specificeret i HTML formularen", -"The uploaded file was only partially uploaded" => "Filen blev kun delvist uploadet.", -"No file was uploaded" => "Ingen fil uploadet", -"Missing a temporary folder" => "Manglende midlertidig mappe.", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Den uploadede fil overskrider MAX_FILE_SIZE -direktivet som er specificeret i HTML-formularen", +"The uploaded file was only partially uploaded" => "Den uploadede file blev kun delvist uploadet", +"No file was uploaded" => "Ingen fil blev uploadet", +"Missing a temporary folder" => "Mangler en midlertidig mappe", "Failed to write to disk" => "Fejl ved skrivning til disk.", "Not enough storage available" => "Der er ikke nok plads til rÃ¥dlighed", "Invalid directory." => "Ugyldig mappe.", "Files" => "Filer", -"Share" => "Del", "Delete permanently" => "Slet permanent", "Delete" => "Slet", "Rename" => "Omdøb", @@ -26,15 +25,13 @@ "undo" => "fortryd", "perform delete operation" => "udfør slet operation", "1 file uploading" => "1 fil uploades", -"files uploading" => "uploader filer", "'.' is an invalid file name." => "'.' er et ugyldigt filnavn.", "File name cannot be empty." => "Filnavnet kan ikke stÃ¥ tomt.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ugyldigt navn, '\\', '/', '<', '>', ':' | '?', '\"', '', og '*' er ikke tilladt.", "Your storage is full, files can not be updated or synced anymore!" => "Din opbevaringsplads er fyldt op, filer kan ikke opdateres eller synkroniseres længere!", "Your storage is almost full ({usedSpacePercent}%)" => "Din opbevaringsplads er næsten fyldt op ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Dit download forberedes. Dette kan tage lidt tid ved større filer.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Kan ikke uploade din fil - det er enten en mappe eller en fil med et indhold pÃ¥ 0 bytes.", -"Not enough space available" => "ikke nok tilgængelig ledig plads ", +"Unable to upload your file as it is a directory or has 0 bytes" => "Kunne ikke uploade din fil, da det enten er en mappe eller er tom", "Upload cancelled." => "Upload afbrudt.", "File upload is in progress. Leaving the page now will cancel the upload." => "Fil upload kører. Hvis du forlader siden nu, vil uploadet blive annuleret.", "URL cannot be empty." => "URLen kan ikke være tom.", @@ -66,7 +63,7 @@ "Nothing in here. Upload something!" => "Her er tomt. Upload noget!", "Download" => "Download", "Unshare" => "Fjern deling", -"Upload too large" => "Upload er for stor", +"Upload too large" => "Upload for stor", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Filerne, du prøver at uploade, er større end den maksimale størrelse for fil-upload pÃ¥ denne server.", "Files are being scanned, please wait." => "Filerne bliver indlæst, vent venligst.", "Current scanning" => "Indlæser", diff --git a/apps/files/l10n/de.php b/apps/files/l10n/de.php index f8ad5993af..34f0233486 100644 --- a/apps/files/l10n/de.php +++ b/apps/files/l10n/de.php @@ -3,18 +3,17 @@ "Could not move %s" => "%s konnte nicht verschoben werden", "Unable to rename file" => "Die Datei konnte nicht umbenannt werden", "No file was uploaded. Unknown error" => "Keine Datei hochgeladen. Unbekannter Fehler", -"There is no error, the file uploaded with success" => "Es ist kein Fehler aufgetreten. Die Datei wurde erfolgreich übertragen.", +"There is no error, the file uploaded with success" => "Datei fehlerfrei hochgeladen.", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Die hochgeladene Datei überschreitet die upload_max_filesize Vorgabe in php.ini", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Die Datei ist größer, als die MAX_FILE_SIZE Direktive erlaubt, die im HTML-Formular spezifiziert ist", -"The uploaded file was only partially uploaded" => "Die Datei konnte nur teilweise übertragen werden", -"No file was uploaded" => "Keine Datei konnte übertragen werden.", -"Missing a temporary folder" => "Kein temporärer Ordner vorhanden", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Die Größe der hochzuladenden Datei überschreitet die MAX_FILE_SIZE-Richtlinie, die im HTML-Formular angegeben wurde", +"The uploaded file was only partially uploaded" => "Die Datei wurde nur teilweise hochgeladen.", +"No file was uploaded" => "Es wurde keine Datei hochgeladen.", +"Missing a temporary folder" => "Temporärer Ordner fehlt.", "Failed to write to disk" => "Fehler beim Schreiben auf die Festplatte", "Not enough storage available" => "Nicht genug Speicherplatz verfügbar", "Invalid directory." => "Ungültiges Verzeichnis.", "Files" => "Dateien", -"Share" => "Teilen", -"Delete permanently" => "Endgültig löschen", +"Delete permanently" => "Permanent löschen", "Delete" => "Löschen", "Rename" => "Umbenennen", "Pending" => "Ausstehend", @@ -42,7 +41,7 @@ "Error" => "Fehler", "Name" => "Name", "Size" => "Größe", -"Modified" => "Geändert", +"Modified" => "Bearbeitet", "1 folder" => "1 Ordner", "{count} folders" => "{count} Ordner", "1 file" => "1 Datei", @@ -64,9 +63,9 @@ "Cancel upload" => "Upload abbrechen", "You don’t have write permissions here." => "Du besitzt hier keine Schreib-Berechtigung.", "Nothing in here. Upload something!" => "Alles leer. Lade etwas hoch!", -"Download" => "Download", -"Unshare" => "Freigabe aufheben", -"Upload too large" => "Der Upload ist zu groß", +"Download" => "Herunterladen", +"Unshare" => "Nicht mehr freigeben", +"Upload too large" => "Upload zu groß", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Die Datei überschreitet die Maximalgröße für Uploads auf diesem Server.", "Files are being scanned, please wait." => "Dateien werden gescannt, bitte warten.", "Current scanning" => "Scanne", diff --git a/apps/files/l10n/de_DE.php b/apps/files/l10n/de_DE.php index 8a977710a2..8fc1c106d0 100644 --- a/apps/files/l10n/de_DE.php +++ b/apps/files/l10n/de_DE.php @@ -5,16 +5,15 @@ "No file was uploaded. Unknown error" => "Keine Datei hochgeladen. Unbekannter Fehler", "There is no error, the file uploaded with success" => "Es sind keine Fehler aufgetreten. Die Datei wurde erfolgreich hochgeladen.", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Die hochgeladene Datei überschreitet die upload_max_filesize Vorgabe in der php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Die Datei ist größer, als die MAX_FILE_SIZE Direktive erlaubt, die im HTML-Formular spezifiziert ist", -"The uploaded file was only partially uploaded" => "Die Datei konnte nur teilweise übertragen werden", -"No file was uploaded" => "Keine Datei konnte übertragen werden.", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Die Größe der hochzuladenden Datei überschreitet die MAX_FILE_SIZE-Richtlinie, die im HTML-Formular angegeben wurde", +"The uploaded file was only partially uploaded" => "Die Datei wurde nur teilweise hochgeladen.", +"No file was uploaded" => "Es wurde keine Datei hochgeladen.", "Missing a temporary folder" => "Der temporäre Ordner fehlt.", "Failed to write to disk" => "Fehler beim Schreiben auf die Festplatte", "Not enough storage available" => "Nicht genug Speicher vorhanden.", "Invalid directory." => "Ungültiges Verzeichnis.", "Files" => "Dateien", -"Share" => "Teilen", -"Delete permanently" => "Endgültig löschen", +"Delete permanently" => "Entgültig löschen", "Delete" => "Löschen", "Rename" => "Umbenennen", "Pending" => "Ausstehend", @@ -33,7 +32,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "Ihr Speicher ist voll. Daher können keine Dateien mehr aktualisiert oder synchronisiert werden!", "Your storage is almost full ({usedSpacePercent}%)" => "Ihr Speicher ist fast voll ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Ihr Download wird vorbereitet. Dies kann bei größeren Dateien einen Moment dauern.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Ihre Datei kann nicht hochgeladen werden, weil es sich um einen Ordner handelt oder 0 Bytes groß ist.", +"Unable to upload your file as it is a directory or has 0 bytes" => "Ihre Datei kann nicht hochgeladen werden, da sie entweder ein Verzeichnis oder 0 Bytes groß ist.", "Not enough space available" => "Nicht genügend Speicherplatz verfügbar", "Upload cancelled." => "Upload abgebrochen.", "File upload is in progress. Leaving the page now will cancel the upload." => "Der Dateiupload läuft. Wenn Sie die Seite jetzt verlassen, wird der Upload abgebrochen.", diff --git a/apps/files/l10n/el.php b/apps/files/l10n/el.php index 8ecb84eb3c..60d63c4142 100644 --- a/apps/files/l10n/el.php +++ b/apps/files/l10n/el.php @@ -5,7 +5,7 @@ "No file was uploaded. Unknown error" => "Δεν ανέβηκε κάποιο αÏχείο. Άγνωστο σφάλμα", "There is no error, the file uploaded with success" => "Δεν υπάÏχει σφάλμα, το αÏχείο εστάλει επιτυχώς", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Το αÏχείο που εστάλει υπεÏβαίνει την οδηγία μέγιστου επιτÏÎµÏ€Ï„Î¿Ï Î¼ÎµÎ³Î­Î¸Î¿Ï…Ï‚ \"upload_max_filesize\" του php.ini", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Το ανεβασμένο αÏχείο υπεÏβαίνει το MAX_FILE_SIZE που οÏίζεται στην HTML φόÏμα", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Το αÏχείο υπεÏβαίνει την οδηγία μέγιστου επιτÏÎµÏ€Ï„Î¿Ï Î¼ÎµÎ³Î­Î¸Î¿Ï…Ï‚ \"MAX_FILE_SIZE\" που έχει οÏιστεί στην HTML φόÏμα", "The uploaded file was only partially uploaded" => "Το αÏχείο εστάλει μόνο εν μέÏει", "No file was uploaded" => "Κανένα αÏχείο δεν στάλθηκε", "Missing a temporary folder" => "Λείπει ο Ï€ÏοσωÏινός φάκελος", @@ -46,7 +46,7 @@ "{count} folders" => "{count} φάκελοι", "1 file" => "1 αÏχείο", "{count} files" => "{count} αÏχεία", -"Upload" => "ΜεταφόÏτωση", +"Upload" => "Αποστολή", "File handling" => "ΔιαχείÏιση αÏχείων", "Maximum upload size" => "Μέγιστο μέγεθος αποστολής", "max. possible: " => "μέγιστο δυνατό:", @@ -64,7 +64,7 @@ "You don’t have write permissions here." => "Δεν έχετε δικαιώματα εγγÏαφής εδώ.", "Nothing in here. Upload something!" => "Δεν υπάÏχει τίποτα εδώ. Ανεβάστε κάτι!", "Download" => "Λήψη", -"Unshare" => "Σταμάτημα διαμοιÏασμοÏ", +"Unshare" => "Διακοπή κοινής χÏήσης", "Upload too large" => "Î Î¿Î»Ï Î¼ÎµÎ³Î¬Î»Î¿ αÏχείο Ï€Ïος αποστολή", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Τα αÏχεία που Ï€Ïοσπαθείτε να ανεβάσετε υπεÏβαίνουν το μέγιστο μέγεθος αποστολής αÏχείων σε αυτόν τον διακομιστή.", "Files are being scanned, please wait." => "Τα αÏχεία σαÏώνονται, παÏακαλώ πεÏιμένετε.", diff --git a/apps/files/l10n/eo.php b/apps/files/l10n/eo.php index 35683a35f1..3435f43059 100644 --- a/apps/files/l10n/eo.php +++ b/apps/files/l10n/eo.php @@ -3,12 +3,12 @@ "Could not move %s" => "Ne eblis movi %s", "Unable to rename file" => "Ne eblis alinomigi dosieron", "No file was uploaded. Unknown error" => "Neniu dosiero alÅutiÄis. Nekonata eraro.", -"There is no error, the file uploaded with success" => "Ne estas eraro, la dosiero alÅutiÄis sukcese.", +"There is no error, the file uploaded with success" => "Ne estas eraro, la dosiero alÅutiÄis sukcese", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "La dosiero alÅutita superas la regulon upload_max_filesize el php.ini: ", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "La dosiero alÅutita superas la regulon MAX_FILE_SIZE, kiu estas difinita en la HTML-formularo", -"The uploaded file was only partially uploaded" => "la alÅutita dosiero nur parte alÅutiÄis", -"No file was uploaded" => "Neniu dosiero alÅutiÄis.", -"Missing a temporary folder" => "Mankas provizora dosierujo.", +"The uploaded file was only partially uploaded" => "La alÅutita dosiero nur parte alÅutiÄis", +"No file was uploaded" => "Neniu dosiero estas alÅutita", +"Missing a temporary folder" => "Mankas tempa dosierujo", "Failed to write to disk" => "Malsukcesis skribo al disko", "Invalid directory." => "Nevalida dosierujo.", "Files" => "Dosieroj", @@ -22,7 +22,6 @@ "replaced {new_name} with {old_name}" => "anstataÅ­iÄis {new_name} per {old_name}", "undo" => "malfari", "1 file uploading" => "1 dosiero estas alÅutata", -"files uploading" => "dosieroj estas alÅutataj", "'.' is an invalid file name." => "'.' ne estas valida dosiernomo.", "File name cannot be empty." => "Dosiernomo devas ne malpleni.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nevalida nomo: “\\â€, “/â€, “<â€, “>â€, “:â€, “\"â€, “|â€, “?†kaj “*†ne permesatas.", @@ -58,7 +57,7 @@ "Nothing in here. Upload something!" => "Nenio estas ĉi tie. AlÅutu ion!", "Download" => "ElÅuti", "Unshare" => "Malkunhavigi", -"Upload too large" => "AlÅuto tro larÄa", +"Upload too large" => "ElÅuto tro larÄa", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "La dosieroj, kiujn vi provas alÅuti, transpasas la maksimuman grandon por dosieralÅutoj en ĉi tiu servilo.", "Files are being scanned, please wait." => "Dosieroj estas skanataj, bonvolu atendi.", "Current scanning" => "Nuna skano" diff --git a/apps/files/l10n/es.php b/apps/files/l10n/es.php index ff782d0c64..e231abe429 100644 --- a/apps/files/l10n/es.php +++ b/apps/files/l10n/es.php @@ -2,13 +2,13 @@ "Could not move %s - File with this name already exists" => "No se puede mover %s - Ya existe un archivo con ese nombre", "Could not move %s" => "No se puede mover %s", "Unable to rename file" => "No se puede renombrar el archivo", -"No file was uploaded. Unknown error" => "No se subió ningún archivo. Error desconocido", -"There is no error, the file uploaded with success" => "No hay ningún error, el archivo se ha subido con éxito", +"No file was uploaded. Unknown error" => "Fallo no se subió el fichero", +"There is no error, the file uploaded with success" => "No se ha producido ningún error, el archivo se ha subido con éxito", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "El archivo que intentas subir sobrepasa el tamaño definido por la variable upload_max_filesize en php.ini", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "El archivo subido sobrepasa la directiva MAX_FILE_SIZE especificada en el formulario HTML", -"The uploaded file was only partially uploaded" => "El archivo se ha subido parcialmente", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "El archivo que intentas subir sobrepasa el tamaño definido por la variable MAX_FILE_SIZE especificada en el formulario HTML", +"The uploaded file was only partially uploaded" => "El archivo que intentas subir solo se subió parcialmente", "No file was uploaded" => "No se ha subido ningún archivo", -"Missing a temporary folder" => "Falta la carpeta temporal", +"Missing a temporary folder" => "Falta un directorio temporal", "Failed to write to disk" => "La escritura en disco ha fallado", "Not enough storage available" => "No hay suficiente espacio disponible", "Invalid directory." => "Directorio invalido.", @@ -16,7 +16,7 @@ "Delete permanently" => "Eliminar permanentemente", "Delete" => "Eliminar", "Rename" => "Renombrar", -"Pending" => "Pendientes", +"Pending" => "Pendiente", "{new_name} already exists" => "{new_name} ya existe", "replace" => "reemplazar", "suggest name" => "sugerir nombre", @@ -32,7 +32,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "Su almacenamiento esta lleno, los archivos no pueden ser mas actualizados o sincronizados!", "Your storage is almost full ({usedSpacePercent}%)" => "Su almacenamiento esta lleno en un ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Tu descarga esta siendo preparada. Esto puede tardar algun tiempo si los archivos son muy grandes.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Imposible subir su archivo, es un directorio o tiene 0 bytes", +"Unable to upload your file as it is a directory or has 0 bytes" => "No ha sido posible subir tu archivo porque es un directorio o tiene 0 bytes", "Not enough space available" => "No hay suficiente espacio disponible", "Upload cancelled." => "Subida cancelada.", "File upload is in progress. Leaving the page now will cancel the upload." => "La subida del archivo está en proceso. Salir de la página ahora cancelará la subida.", @@ -64,8 +64,8 @@ "You don’t have write permissions here." => "No tienes permisos para escribir aquí.", "Nothing in here. Upload something!" => "Aquí no hay nada. ¡Sube algo!", "Download" => "Descargar", -"Unshare" => "No compartir", -"Upload too large" => "bida demasido grande", +"Unshare" => "Dejar de compartir", +"Upload too large" => "El archivo es demasiado grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Los archivos que estás intentando subir sobrepasan el tamaño máximo permitido por este servidor.", "Files are being scanned, please wait." => "Se están escaneando los archivos, por favor espere.", "Current scanning" => "Ahora escaneando", diff --git a/apps/files/l10n/es_AR.php b/apps/files/l10n/es_AR.php index 3248c241db..25c2f4ff69 100644 --- a/apps/files/l10n/es_AR.php +++ b/apps/files/l10n/es_AR.php @@ -3,12 +3,12 @@ "Could not move %s" => "No se pudo mover %s ", "Unable to rename file" => "No fue posible cambiar el nombre al archivo", "No file was uploaded. Unknown error" => "El archivo no fue subido. Error desconocido", -"There is no error, the file uploaded with success" => "No hay errores, el archivo fue subido con éxito", +"There is no error, the file uploaded with success" => "No se han producido errores, el archivo se ha subido con éxito", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "El archivo que intentás subir excede el tamaño definido por upload_max_filesize en el php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "El archivo subido sobrepasa el valor MAX_FILE_SIZE especificada en el formulario HTML", -"The uploaded file was only partially uploaded" => "El archivo fue subido parcialmente", -"No file was uploaded" => "No se subió ningún archivo ", -"Missing a temporary folder" => "Error en la carpera temporal", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "El archivo que intentás subir sobrepasa el tamaño definido por la variable MAX_FILE_SIZE especificada en el formulario HTML", +"The uploaded file was only partially uploaded" => "El archivo que intentás subir solo se subió parcialmente", +"No file was uploaded" => "El archivo no fue subido", +"Missing a temporary folder" => "Falta un directorio temporal", "Failed to write to disk" => "Error al escribir en el disco", "Not enough storage available" => "No hay suficiente capacidad de almacenamiento", "Invalid directory." => "Directorio invalido.", @@ -16,7 +16,7 @@ "Delete permanently" => "Borrar de manera permanente", "Delete" => "Borrar", "Rename" => "Cambiar nombre", -"Pending" => "Pendientes", +"Pending" => "Pendiente", "{new_name} already exists" => "{new_name} ya existe", "replace" => "reemplazar", "suggest name" => "sugerir nombre", @@ -65,7 +65,7 @@ "Nothing in here. Upload something!" => "No hay nada. ¡Subí contenido!", "Download" => "Descargar", "Unshare" => "Dejar de compartir", -"Upload too large" => "El tamaño del archivo que querés subir es demasiado grande", +"Upload too large" => "El archivo es demasiado grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Los archivos que intentás subir sobrepasan el tamaño máximo ", "Files are being scanned, please wait." => "Se están escaneando los archivos, por favor esperá.", "Current scanning" => "Escaneo actual", diff --git a/apps/files/l10n/et_EE.php b/apps/files/l10n/et_EE.php index fa48cb2cc4..64a2f71b27 100644 --- a/apps/files/l10n/et_EE.php +++ b/apps/files/l10n/et_EE.php @@ -3,9 +3,9 @@ "Could not move %s" => "%s liigutamine ebaõnnestus", "Unable to rename file" => "Faili ümbernimetamine ebaõnnestus", "No file was uploaded. Unknown error" => "Ãœhtegi faili ei laetud üles. Tundmatu viga", -"There is no error, the file uploaded with success" => "Ãœhtegi tõrget polnud, fail on üles laetud", +"There is no error, the file uploaded with success" => "Ãœhtegi viga pole, fail on üles laetud", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Ãœleslaetava faili suurus ületab php.ini poolt määratud upload_max_filesize suuruse", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Ãœleslaetud fail ületab MAX_FILE_SIZE suuruse, mis on HTML vormi jaoks määratud", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Ãœles laetud faili suurus ületab HTML vormis määratud upload_max_filesize suuruse", "The uploaded file was only partially uploaded" => "Fail laeti üles ainult osaliselt", "No file was uploaded" => "Ãœhtegi faili ei laetud üles", "Missing a temporary folder" => "Ajutiste failide kaust puudub", @@ -32,7 +32,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "Sinu andmemaht on täis! Faile ei uuendata ja sünkroniseerimist ei toimu!", "Your storage is almost full ({usedSpacePercent}%)" => "Su andmemaht on peaaegu täis ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Valmistatakse allalaadimist. See võib võtta veidi aega kui on tegu suurte failidega. ", -"Unable to upload your file as it is a directory or has 0 bytes" => "Faili ei saa üles laadida, kuna see on kaust või selle suurus on 0 baiti", +"Unable to upload your file as it is a directory or has 0 bytes" => "Sinu faili üleslaadimine ebaõnnestus, kuna see on kaust või selle suurus on 0 baiti", "Not enough space available" => "Pole piisavalt ruumi", "Upload cancelled." => "Ãœleslaadimine tühistati.", "File upload is in progress. Leaving the page now will cancel the upload." => "Faili üleslaadimine on töös. Lehelt lahkumine katkestab selle üleslaadimise.", diff --git a/apps/files/l10n/eu.php b/apps/files/l10n/eu.php index 7d938cffd2..8c244babf0 100644 --- a/apps/files/l10n/eu.php +++ b/apps/files/l10n/eu.php @@ -3,12 +3,12 @@ "Could not move %s" => "Ezin dira fitxategiak mugitu %s", "Unable to rename file" => "Ezin izan da fitxategia berrizendatu", "No file was uploaded. Unknown error" => "Ez da fitxategirik igo. Errore ezezaguna", -"There is no error, the file uploaded with success" => "Ez da errorerik egon, fitxategia ongi igo da", +"There is no error, the file uploaded with success" => "Ez da arazorik izan, fitxategia ongi igo da", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Igotako fitxategiak php.ini fitxategian ezarritako upload_max_filesize muga gainditu du:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Igotako fitxategia HTML formularioan zehaztutako MAX_FILE_SIZE direktiba baino handidagoa da.", -"The uploaded file was only partially uploaded" => "Igotako fitxategiaren zati bat bakarrik igo da", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Igotako fitxategiaren tamaina HTML inprimakiko MAX_FILESIZE direktiban adierazitakoa baino handiagoa da", +"The uploaded file was only partially uploaded" => "Igotako fitxategiaren zati bat baino gehiago ez da igo", "No file was uploaded" => "Ez da fitxategirik igo", -"Missing a temporary folder" => "Aldi bateko karpeta falta da", +"Missing a temporary folder" => "Aldi baterako karpeta falta da", "Failed to write to disk" => "Errore bat izan da diskoan idazterakoan", "Not enough storage available" => "Ez dago behar aina leku erabilgarri,", "Invalid directory." => "Baliogabeko karpeta.", @@ -25,14 +25,13 @@ "undo" => "desegin", "perform delete operation" => "Ezabatu", "1 file uploading" => "fitxategi 1 igotzen", -"files uploading" => "fitxategiak igotzen", "'.' is an invalid file name." => "'.' ez da fitxategi izen baliogarria.", "File name cannot be empty." => "Fitxategi izena ezin da hutsa izan.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "IZen aliogabea, '\\', '/', '<', '>', ':', '\"', '|', '?' eta '*' ez daude baimenduta.", "Your storage is full, files can not be updated or synced anymore!" => "Zure biltegiratzea beterik dago, ezingo duzu aurrerantzean fitxategirik igo edo sinkronizatu!", "Your storage is almost full ({usedSpacePercent}%)" => "Zure biltegiratzea nahiko beterik dago (%{usedSpacePercent})", "Your download is being prepared. This might take some time if the files are big." => "Zure deskarga prestatu egin behar da. Denbora bat har lezake fitxategiak handiak badira. ", -"Unable to upload your file as it is a directory or has 0 bytes" => "Ezin izan da zure fitxategia igo karpeta bat delako edo 0 byte dituelako", +"Unable to upload your file as it is a directory or has 0 bytes" => "Ezin da zure fitxategia igo, karpeta bat da edo 0 byt ditu", "Not enough space available" => "Ez dago leku nahikorik.", "Upload cancelled." => "Igoera ezeztatuta", "File upload is in progress. Leaving the page now will cancel the upload." => "Fitxategien igoera martxan da. Orria orain uzteak igoera ezeztatutko du.", @@ -65,7 +64,7 @@ "Nothing in here. Upload something!" => "Ez dago ezer. Igo zerbait!", "Download" => "Deskargatu", "Unshare" => "Ez elkarbanatu", -"Upload too large" => "Igoera handiegia da", +"Upload too large" => "Igotakoa handiegia da", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Igotzen saiatzen ari zaren fitxategiak zerbitzari honek igotzeko onartzen duena baino handiagoak dira.", "Files are being scanned, please wait." => "Fitxategiak eskaneatzen ari da, itxoin mezedez.", "Current scanning" => "Orain eskaneatzen ari da", diff --git a/apps/files/l10n/fa.php b/apps/files/l10n/fa.php index 10132fdf9e..13ef465199 100644 --- a/apps/files/l10n/fa.php +++ b/apps/files/l10n/fa.php @@ -3,19 +3,18 @@ "Could not move %s" => "%s نمی تواند حرکت کند ", "Unable to rename file" => "قادر به تغییر نام پرونده نیست.", "No file was uploaded. Unknown error" => "هیچ Ùایلی آپلود نشد.خطای ناشناس", -"There is no error, the file uploaded with success" => "هیچ خطایی نیست بارگذاری پرونده موÙقیت آمیز بود", +"There is no error, the file uploaded with success" => "هیچ خطایی وجود ندارد Ùایل با موÙقیت بار گذاری شد", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "پرونده آپلود شده بیش ازدستور ماکزیمم_حجم Ùایل_برای آپلود در php.ini استÙاده کرده است.", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "حداکثر حجم قابل بار گذاری از طریق HTML MAX_FILE_SIZE است", -"The uploaded file was only partially uploaded" => "پرونده بارگذاری شده Ùقط تاحدودی بارگذاری شده", -"No file was uploaded" => "هیچ پروندهای بارگذاری نشده", -"Missing a temporary folder" => "یک پوشه موقت Ú¯Ù… شده", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "حداکثر حجم مجاز برای بارگذاری از طریق HTML \nMAX_FILE_SIZE", +"The uploaded file was only partially uploaded" => "مقدار Ú©Ù…ÛŒ از Ùایل بارگذاری شده", +"No file was uploaded" => "هیچ Ùایلی بارگذاری نشده", +"Missing a temporary folder" => "یک پوشه موقت Ú¯Ù… شده است", "Failed to write to disk" => "نوشتن بر روی دیسک سخت ناموÙÙ‚ بود", "Not enough storage available" => "Ùضای کاÙÛŒ در دسترس نیست", "Invalid directory." => "Ùهرست راهنما نامعتبر Ù…ÛŒ باشد.", -"Files" => "پرونده‌ها", -"Share" => "اشتراک‌گذاری", +"Files" => "Ùایل ها", "Delete permanently" => "حذ٠قطعی", -"Delete" => "حذÙ", +"Delete" => "پاک کردن", "Rename" => "تغییرنام", "Pending" => "در انتظار", "{new_name} already exists" => "{نام _جدید} در حال حاضر وجود دارد.", @@ -42,12 +41,12 @@ "Error" => "خطا", "Name" => "نام", "Size" => "اندازه", -"Modified" => "تاریخ", +"Modified" => "تغییر یاÙته", "1 folder" => "1 پوشه", "{count} folders" => "{ شمار} پوشه ها", "1 file" => "1 پرونده", "{count} files" => "{ شمار } Ùایل ها", -"Upload" => "بارگزاری", +"Upload" => "بارگذاری", "File handling" => "اداره پرونده ها", "Maximum upload size" => "حداکثر اندازه بارگزاری", "max. possible: " => "حداکثرمقدارممکن:", @@ -64,9 +63,9 @@ "Cancel upload" => "متوق٠کردن بار گذاری", "You don’t have write permissions here." => "شما اجازه ÛŒ نوشتن در اینجا را ندارید", "Nothing in here. Upload something!" => "اینجا هیچ چیز نیست.", -"Download" => "دانلود", +"Download" => "بارگیری", "Unshare" => "لغو اشتراک", -"Upload too large" => "سایز Ùایل برای آپلود زیاد است(Ù….تنظیمات در php.ini)", +"Upload too large" => "حجم بارگذاری بسیار زیاد است", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Ùایلها بیش از حد تعیین شده در این سرور هستند\nمترجم:با تغییر Ùایل php,ini میتوان این محدودیت را برطر٠کرد", "Files are being scanned, please wait." => "پرونده ها در حال بازرسی هستند لطÙا صبر کنید", "Current scanning" => "بازرسی کنونی", diff --git a/apps/files/l10n/fi_FI.php b/apps/files/l10n/fi_FI.php index 08a0718323..b797273d51 100644 --- a/apps/files/l10n/fi_FI.php +++ b/apps/files/l10n/fi_FI.php @@ -4,16 +4,14 @@ "Unable to rename file" => "Tiedoston nimeäminen uudelleen ei onnistunut", "No file was uploaded. Unknown error" => "Tiedostoa ei lähetetty. Tuntematon virhe", "There is no error, the file uploaded with success" => "Ei virheitä, tiedosto lähetettiin onnistuneesti", -"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Lähetetyn tiedoston koko ylittää php.ini-tiedoston upload_max_filesize-säännön:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Ladattavan tiedoston maksimikoko ylittää MAX_FILE_SIZE dirketiivin, joka on määritelty HTML-lomakkeessa", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Lähetetty tiedosto ylittää HTML-lomakkeessa määritetyn MAX_FILE_SIZE-arvon ylärajan", "The uploaded file was only partially uploaded" => "Tiedoston lähetys onnistui vain osittain", "No file was uploaded" => "Yhtäkään tiedostoa ei lähetetty", -"Missing a temporary folder" => "Tilapäiskansio puuttuu", +"Missing a temporary folder" => "Väliaikaiskansiota ei ole olemassa", "Failed to write to disk" => "Levylle kirjoitus epäonnistui", "Not enough storage available" => "Tallennustilaa ei ole riittävästi käytettävissä", "Invalid directory." => "Virheellinen kansio.", "Files" => "Tiedostot", -"Share" => "Jaa", "Delete permanently" => "Poista pysyvästi", "Delete" => "Poista", "Rename" => "Nimeä uudelleen", @@ -30,7 +28,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "Tallennustila on loppu, tiedostoja ei voi enää päivittää tai synkronoida!", "Your storage is almost full ({usedSpacePercent}%)" => "Tallennustila on melkein loppu ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Lataustasi valmistellaan. Tämä saattaa kestää hetken, jos tiedostot ovat suuria kooltaan.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Tiedoston lähetys epäonnistui, koska sen koko on 0 tavua tai kyseessä on kansio.", +"Unable to upload your file as it is a directory or has 0 bytes" => "Tiedoston lähetys epäonnistui, koska sen koko on 0 tavua tai kyseessä on kansio", "Not enough space available" => "Tilaa ei ole riittävästi", "Upload cancelled." => "Lähetys peruttu.", "File upload is in progress. Leaving the page now will cancel the upload." => "Tiedoston lähetys on meneillään. Sivulta poistuminen nyt peruu tiedoston lähetyksen.", @@ -38,7 +36,7 @@ "Error" => "Virhe", "Name" => "Nimi", "Size" => "Koko", -"Modified" => "Muokattu", +"Modified" => "Muutettu", "1 folder" => "1 kansio", "{count} folders" => "{count} kansiota", "1 file" => "1 tiedosto", diff --git a/apps/files/l10n/fr.php b/apps/files/l10n/fr.php index f901e6c2f7..093a0b891c 100644 --- a/apps/files/l10n/fr.php +++ b/apps/files/l10n/fr.php @@ -3,12 +3,12 @@ "Could not move %s" => "Impossible de déplacer %s", "Unable to rename file" => "Impossible de renommer le fichier", "No file was uploaded. Unknown error" => "Aucun fichier n'a été chargé. Erreur inconnue", -"There is no error, the file uploaded with success" => "Il n'y a pas d'erreur, le fichier a été envoyé avec succes.", +"There is no error, the file uploaded with success" => "Aucune erreur, le fichier a été téléversé avec succès", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Le fichier envoyé dépasse la valeur upload_max_filesize située dans le fichier php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Le fichier envoyé dépasse la directive MAX_FILE_SIZE qui est spécifiée dans le formulaire HTML.", -"The uploaded file was only partially uploaded" => "Le fichier envoyé n'a été que partiellement envoyé.", -"No file was uploaded" => "Pas de fichier envoyé.", -"Missing a temporary folder" => "Absence de dossier temporaire.", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Le fichier téléversé excède la valeur de MAX_FILE_SIZE spécifiée dans le formulaire HTML", +"The uploaded file was only partially uploaded" => "Le fichier n'a été que partiellement téléversé", +"No file was uploaded" => "Aucun fichier n'a été téléversé", +"Missing a temporary folder" => "Il manque un répertoire temporaire", "Failed to write to disk" => "Erreur d'écriture sur le disque", "Not enough storage available" => "Plus assez d'espace de stockage disponible", "Invalid directory." => "Dossier invalide.", @@ -16,7 +16,7 @@ "Delete permanently" => "Supprimer de façon définitive", "Delete" => "Supprimer", "Rename" => "Renommer", -"Pending" => "En attente", +"Pending" => "En cours", "{new_name} already exists" => "{new_name} existe déjà", "replace" => "remplacer", "suggest name" => "Suggérer un nom", @@ -32,7 +32,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "Votre espage de stockage est plein, les fichiers ne peuvent plus être téléversés ou synchronisés !", "Your storage is almost full ({usedSpacePercent}%)" => "Votre espace de stockage est presque plein ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Votre téléchargement est cours de préparation. Ceci peut nécessiter un certain temps si les fichiers sont volumineux.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Impossible de téléverser votre fichier dans la mesure où il s'agit d'un répertoire ou d'un fichier de taille nulle", +"Unable to upload your file as it is a directory or has 0 bytes" => "Impossible de charger vos fichiers car il s'agit d'un dossier ou le fichier fait 0 octet.", "Not enough space available" => "Espace disponible insuffisant", "Upload cancelled." => "Chargement annulé.", "File upload is in progress. Leaving the page now will cancel the upload." => "L'envoi du fichier est en cours. Quitter cette page maintenant annulera l'envoi du fichier.", @@ -65,7 +65,7 @@ "Nothing in here. Upload something!" => "Il n'y a rien ici ! Envoyez donc quelque chose :)", "Download" => "Télécharger", "Unshare" => "Ne plus partager", -"Upload too large" => "Téléversement trop volumineux", +"Upload too large" => "Fichier trop volumineux", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Les fichiers que vous essayez d'envoyer dépassent la taille maximale permise par ce serveur.", "Files are being scanned, please wait." => "Les fichiers sont en cours d'analyse, veuillez patienter.", "Current scanning" => "Analyse en cours", diff --git a/apps/files/l10n/gl.php b/apps/files/l10n/gl.php index c371684313..14992f5838 100644 --- a/apps/files/l10n/gl.php +++ b/apps/files/l10n/gl.php @@ -2,13 +2,13 @@ "Could not move %s - File with this name already exists" => "Non se moveu %s - Xa existe un ficheiro con ese nome.", "Could not move %s" => "Non foi posíbel mover %s", "Unable to rename file" => "Non é posíbel renomear o ficheiro", -"No file was uploaded. Unknown error" => "Non se enviou ningún ficheiro. Produciuse un erro descoñecido.", -"There is no error, the file uploaded with success" => "Non houbo erros, o ficheiro enviouse correctamente", +"No file was uploaded. Unknown error" => "Non foi enviado ningún ficheiro. Produciuse un erro descoñecido.", +"There is no error, the file uploaded with success" => "Non se produciu ningún erro. O ficheiro enviouse correctamente", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "O ficheiro enviado excede a directiva indicada por upload_max_filesize de php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "O ficheiro enviado excede da directiva MAX_FILE_SIZE especificada no formulario HTML", -"The uploaded file was only partially uploaded" => "O ficheiro so foi parcialmente enviado", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "O ficheiro enviado excede a directiva MAX_FILE_SIZE que foi indicada no formulario HTML", +"The uploaded file was only partially uploaded" => "O ficheiro enviado foi só parcialmente enviado", "No file was uploaded" => "Non se enviou ningún ficheiro", -"Missing a temporary folder" => "Falta o cartafol temporal", +"Missing a temporary folder" => "Falta un cartafol temporal", "Failed to write to disk" => "Produciuse un erro ao escribir no disco", "Not enough storage available" => "Non hai espazo de almacenamento abondo", "Invalid directory." => "O directorio é incorrecto.", diff --git a/apps/files/l10n/he.php b/apps/files/l10n/he.php index 3facc4f859..36ba7cc5de 100644 --- a/apps/files/l10n/he.php +++ b/apps/files/l10n/he.php @@ -1,11 +1,11 @@ "×œ× ×”×•×¢×œ×” קובץ. טעות בלתי מזוהה.", -"There is no error, the file uploaded with success" => "×œ× ×”×ª×¨×—×©×” שגי××”, הקובץ הועלה בהצלחה", +"There is no error, the file uploaded with success" => "×œ× ×ירעה תקלה, ×”×§×‘×¦×™× ×”×•×¢×œ×• בהצלחה", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "×”×§×‘×¦×™× ×©× ×©×œ×—×• ×—×•×¨×’×™× ×ž×”×’×•×“×œ שצוין בהגדרה upload_max_filesize שבקובץ php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "הקובץ שהועלה גדוך מהערך MAX_FILE_SIZE שהוגדר בתופס HTML", -"The uploaded file was only partially uploaded" => "הקובץ הועלה ב×ופן חלקי בלבד", -"No file was uploaded" => "×©×•× ×§×•×‘×¥ ×œ× ×”×•×¢×œ×”", -"Missing a temporary folder" => "תקיה זמנית חסרה", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "הקובץ שהועלה חרג מההנחיה MAX_FILE_SIZE שצוינה בטופס ×”Ö¾HTML", +"The uploaded file was only partially uploaded" => "הקובץ שהועלה הועלה בצורה חלקית", +"No file was uploaded" => "×œ× ×”×•×¢×œ×• קבצי×", +"Missing a temporary folder" => "תיקייה זמנית חסרה", "Failed to write to disk" => "הכתיבה לכונן נכשלה", "Files" => "קבצי×", "Delete permanently" => "מחק לצמיתות", diff --git a/apps/files/l10n/hr.php b/apps/files/l10n/hr.php index d634faee75..a6b83b3d67 100644 --- a/apps/files/l10n/hr.php +++ b/apps/files/l10n/hr.php @@ -1,13 +1,12 @@ "Nema pogreÅ¡ke, datoteka je poslana uspjeÅ¡no.", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Poslana datoteka prelazi veliÄinu prikazanu u MAX_FILE_SIZE direktivi u HTML formi", -"The uploaded file was only partially uploaded" => "Poslana datoteka je parcijalno poslana", -"No file was uploaded" => "Datoteka nije poslana", -"Missing a temporary folder" => "Nedostaje privremeni direktorij", +"There is no error, the file uploaded with success" => "Datoteka je poslana uspjeÅ¡no i bez pogreÅ¡aka", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Poslana datoteka izlazi iz okvira MAX_FILE_SIZE direktive postavljene u HTML obrascu", +"The uploaded file was only partially uploaded" => "Datoteka je poslana samo djelomiÄno", +"No file was uploaded" => "Ni jedna datoteka nije poslana", +"Missing a temporary folder" => "Nedostaje privremena mapa", "Failed to write to disk" => "Neuspjelo pisanje na disk", "Files" => "Datoteke", -"Share" => "Podijeli", -"Delete" => "ObriÅ¡i", +"Delete" => "BriÅ¡i", "Rename" => "Promjeni ime", "Pending" => "U tijeku", "replace" => "zamjeni", @@ -15,15 +14,14 @@ "cancel" => "odustani", "undo" => "vrati", "1 file uploading" => "1 datoteka se uÄitava", -"files uploading" => "datoteke se uÄitavaju", "Unable to upload your file as it is a directory or has 0 bytes" => "Nemoguće poslati datoteku jer je prazna ili je direktorij", "Upload cancelled." => "Slanje poniÅ¡teno.", "File upload is in progress. Leaving the page now will cancel the upload." => "UÄitavanje datoteke. NapuÅ¡tanjem stranice će prekinuti uÄitavanje.", "Error" => "GreÅ¡ka", -"Name" => "Ime", +"Name" => "Naziv", "Size" => "VeliÄina", "Modified" => "Zadnja promjena", -"Upload" => "UÄitaj", +"Upload" => "PoÅ¡alji", "File handling" => "datoteka za rukovanje", "Maximum upload size" => "Maksimalna veliÄina prijenosa", "max. possible: " => "maksimalna moguća: ", @@ -37,8 +35,8 @@ "Folder" => "mapa", "Cancel upload" => "Prekini upload", "Nothing in here. Upload something!" => "Nema niÄega u ovoj mapi. PoÅ¡alji neÅ¡to!", -"Download" => "Preuzimanje", -"Unshare" => "Makni djeljenje", +"Download" => "Preuzmi", +"Unshare" => "Prekini djeljenje", "Upload too large" => "Prijenos je preobiman", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Datoteke koje pokuÅ¡avate prenijeti prelaze maksimalnu veliÄinu za prijenos datoteka na ovom poslužitelju.", "Files are being scanned, please wait." => "Datoteke se skeniraju, molimo priÄekajte.", diff --git a/apps/files/l10n/hu_HU.php b/apps/files/l10n/hu_HU.php index 9a4e519969..103523b65f 100644 --- a/apps/files/l10n/hu_HU.php +++ b/apps/files/l10n/hu_HU.php @@ -7,7 +7,7 @@ "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "A feltöltött fájl mérete meghaladja a php.ini állományban megadott upload_max_filesize paraméter értékét.", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "A feltöltött fájl mérete meghaladja a MAX_FILE_SIZE paramétert, ami a HTML formban került megadásra.", "The uploaded file was only partially uploaded" => "Az eredeti fájlt csak részben sikerült feltölteni.", -"No file was uploaded" => "Nem töltÅ‘dött fel állomány", +"No file was uploaded" => "Nem töltÅ‘dött fel semmi", "Missing a temporary folder" => "Hiányzik egy ideiglenes mappa", "Failed to write to disk" => "Nem sikerült a lemezre történÅ‘ írás", "Not enough storage available" => "Nincs elég szabad hely.", @@ -64,7 +64,7 @@ "You don’t have write permissions here." => "Itt nincs írásjoga.", "Nothing in here. Upload something!" => "Itt nincs semmi. Töltsön fel valamit!", "Download" => "Letöltés", -"Unshare" => "A megosztás visszavonása", +"Unshare" => "Megosztás visszavonása", "Upload too large" => "A feltöltés túl nagy", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "A feltöltendÅ‘ állományok mérete meghaladja a kiszolgálón megengedett maximális méretet.", "Files are being scanned, please wait." => "A fájllista ellenÅ‘rzése zajlik, kis türelmet!", diff --git a/apps/files/l10n/ia.php b/apps/files/l10n/ia.php index 457f771e46..b3233cc37d 100644 --- a/apps/files/l10n/ia.php +++ b/apps/files/l10n/ia.php @@ -1,6 +1,6 @@ "Le file incargate solmente esseva incargate partialmente", -"No file was uploaded" => "Nulle file esseva incargate.", +"No file was uploaded" => "Nulle file esseva incargate", "Missing a temporary folder" => "Manca un dossier temporari", "Files" => "Files", "Delete" => "Deler", diff --git a/apps/files/l10n/id.php b/apps/files/l10n/id.php index 187ccfc67f..3894ce0de9 100644 --- a/apps/files/l10n/id.php +++ b/apps/files/l10n/id.php @@ -2,7 +2,7 @@ "Could not move %s - File with this name already exists" => "Tidak dapat memindahkan %s - Berkas dengan nama ini sudah ada", "Could not move %s" => "Tidak dapat memindahkan %s", "Unable to rename file" => "Tidak dapat mengubah nama berkas", -"No file was uploaded. Unknown error" => "Tidak ada berkas yang diunggah. Galat tidak dikenal.", +"No file was uploaded. Unknown error" => "Tidak ada berkas yang diunggah. Galat tidak dikenal", "There is no error, the file uploaded with success" => "Tidak ada galat, berkas sukses diunggah", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Berkas yang diunggah melampaui direktif upload_max_filesize pada php.ini", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Berkas yang diunggah melampaui direktif MAX_FILE_SIZE yang ditentukan dalam formulir HTML.", @@ -32,7 +32,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "Ruang penyimpanan Anda penuh, berkas tidak dapat diperbarui atau disinkronkan lagi!", "Your storage is almost full ({usedSpacePercent}%)" => "Ruang penyimpanan hampir penuh ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Unduhan Anda sedang disiapkan. Prosesnya dapat berlangsung agak lama jika ukuran berkasnya besar.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Gagal mengunggah berkas Anda karena berupa direktori atau mempunyai ukuran 0 byte", +"Unable to upload your file as it is a directory or has 0 bytes" => "Gagal mengunggah berkas Anda karena berupa direktori atau ukurannya 0 byte", "Not enough space available" => "Ruang penyimpanan tidak mencukupi", "Upload cancelled." => "Pengunggahan dibatalkan.", "File upload is in progress. Leaving the page now will cancel the upload." => "Berkas sedang diunggah. Meninggalkan halaman ini akan membatalkan proses.", @@ -65,7 +65,7 @@ "Nothing in here. Upload something!" => "Tidak ada apa-apa di sini. Unggah sesuatu!", "Download" => "Unduh", "Unshare" => "Batalkan berbagi", -"Upload too large" => "Yang diunggah terlalu besar", +"Upload too large" => "Unggahan terlalu besar", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Berkas yang dicoba untuk diunggah melebihi ukuran maksimum pengunggahan berkas di server ini.", "Files are being scanned, please wait." => "Berkas sedang dipindai, silakan tunggu.", "Current scanning" => "Yang sedang dipindai", diff --git a/apps/files/l10n/it.php b/apps/files/l10n/it.php index 9f54b2efb9..20819e2564 100644 --- a/apps/files/l10n/it.php +++ b/apps/files/l10n/it.php @@ -3,12 +3,12 @@ "Could not move %s" => "Impossibile spostare %s", "Unable to rename file" => "Impossibile rinominare il file", "No file was uploaded. Unknown error" => "Nessun file è stato inviato. Errore sconosciuto", -"There is no error, the file uploaded with success" => "Non ci sono errori, il file è stato caricato correttamente", +"There is no error, the file uploaded with success" => "Non ci sono errori, file caricato con successo", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Il file caricato supera la direttiva upload_max_filesize in php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Il file inviato supera la direttiva MAX_FILE_SIZE specificata nel modulo HTML", -"The uploaded file was only partially uploaded" => "Il file è stato caricato solo parzialmente", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Il file caricato supera il valore MAX_FILE_SIZE definito nel form HTML", +"The uploaded file was only partially uploaded" => "Il file è stato parzialmente caricato", "No file was uploaded" => "Nessun file è stato caricato", -"Missing a temporary folder" => "Manca una cartella temporanea", +"Missing a temporary folder" => "Cartella temporanea mancante", "Failed to write to disk" => "Scrittura su disco non riuscita", "Not enough storage available" => "Spazio di archiviazione insufficiente", "Invalid directory." => "Cartella non valida.", @@ -32,7 +32,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "Lo spazio di archiviazione è pieno, i file non possono essere più aggiornati o sincronizzati!", "Your storage is almost full ({usedSpacePercent}%)" => "Lo spazio di archiviazione è quasi pieno ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Il tuo scaricamento è in fase di preparazione. Ciò potrebbe richiedere del tempo se i file sono grandi.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Impossibile caricare il file poiché è una cartella o ha una dimensione di 0 byte", +"Unable to upload your file as it is a directory or has 0 bytes" => "Impossibile inviare il file poiché è una cartella o ha dimensione 0 byte", "Not enough space available" => "Spazio disponibile insufficiente", "Upload cancelled." => "Invio annullato", "File upload is in progress. Leaving the page now will cancel the upload." => "Caricamento del file in corso. La chiusura della pagina annullerà il caricamento.", @@ -65,7 +65,7 @@ "Nothing in here. Upload something!" => "Non c'è niente qui. Carica qualcosa!", "Download" => "Scarica", "Unshare" => "Rimuovi condivisione", -"Upload too large" => "Caricamento troppo grande", +"Upload too large" => "Il file caricato è troppo grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "I file che stai provando a caricare superano la dimensione massima consentita su questo server.", "Files are being scanned, please wait." => "Scansione dei file in corso, attendi", "Current scanning" => "Scansione corrente", diff --git a/apps/files/l10n/ja_JP.php b/apps/files/l10n/ja_JP.php index afc2f54b6d..402a9f33b3 100644 --- a/apps/files/l10n/ja_JP.php +++ b/apps/files/l10n/ja_JP.php @@ -5,10 +5,10 @@ "No file was uploaded. Unknown error" => "ファイルã¯ä½•ã‚‚アップロードã•ã‚Œã¦ã„ã¾ã›ã‚“。ä¸æ˜Žãªã‚¨ãƒ©ãƒ¼", "There is no error, the file uploaded with success" => "エラーã¯ã‚ã‚Šã¾ã›ã‚“。ファイルã®ã‚¢ãƒƒãƒ—ロードã¯æˆåŠŸã—ã¾ã—ãŸ", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "アップロードã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã¯php.ini ã® upload_max_filesize ã«è¨­å®šã•ã‚ŒãŸã‚µã‚¤ã‚ºã‚’超ãˆã¦ã„ã¾ã™:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "アップロードファイルã¯HTMLフォームã§æŒ‡å®šã•ã‚ŒãŸ MAX_FILE_SIZE ã®åˆ¶é™ã‚’超ãˆã¦ã„ã¾ã™", -"The uploaded file was only partially uploaded" => "アップロードファイルã¯ä¸€éƒ¨åˆ†ã ã‘アップロードã•ã‚Œã¾ã—ãŸ", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "アップロードã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«ã¯HTMLã®ãƒ•ã‚©ãƒ¼ãƒ ã«è¨­å®šã•ã‚ŒãŸMAX_FILE_SIZEã«è¨­å®šã•ã‚ŒãŸã‚µã‚¤ã‚ºã‚’超ãˆã¦ã„ã¾ã™", +"The uploaded file was only partially uploaded" => "ファイルã¯ä¸€éƒ¨åˆ†ã—ã‹ã‚¢ãƒƒãƒ—ロードã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ", "No file was uploaded" => "ファイルã¯ã‚¢ãƒƒãƒ—ロードã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ", -"Missing a temporary folder" => "一時ä¿å­˜ãƒ•ã‚©ãƒ«ãƒ€ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“", +"Missing a temporary folder" => "テンãƒãƒ©ãƒªãƒ•ã‚©ãƒ«ãƒ€ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“", "Failed to write to disk" => "ディスクã¸ã®æ›¸ãè¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ", "Not enough storage available" => "ストレージã«å分ãªç©ºã容é‡ãŒã‚ã‚Šã¾ã›ã‚“", "Invalid directory." => "無効ãªãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã™ã€‚", @@ -16,7 +16,7 @@ "Delete permanently" => "完全ã«å‰Šé™¤ã™ã‚‹", "Delete" => "削除", "Rename" => "åå‰ã®å¤‰æ›´", -"Pending" => "中断", +"Pending" => "ä¿ç•™", "{new_name} already exists" => "{new_name} ã¯ã™ã§ã«å­˜åœ¨ã—ã¦ã„ã¾ã™", "replace" => "ç½®ãæ›ãˆ", "suggest name" => "推奨å称", @@ -41,7 +41,7 @@ "Error" => "エラー", "Name" => "åå‰", "Size" => "サイズ", -"Modified" => "変更", +"Modified" => "更新日時", "1 folder" => "1 フォルダ", "{count} folders" => "{count} フォルダ", "1 file" => "1 ファイル", @@ -64,8 +64,8 @@ "You don’t have write permissions here." => "ã‚ãªãŸã«ã¯æ›¸ãè¾¼ã¿æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。", "Nothing in here. Upload something!" => "ã“ã“ã«ã¯ä½•ã‚‚ã‚ã‚Šã¾ã›ã‚“。何ã‹ã‚¢ãƒƒãƒ—ロードã—ã¦ãã ã•ã„。", "Download" => "ダウンロード", -"Unshare" => "共有解除", -"Upload too large" => "アップロードã«ã¯å¤§ãã™ãŽã¾ã™ã€‚", +"Unshare" => "共有ã—ãªã„", +"Upload too large" => "ファイルサイズãŒå¤§ãã™ãŽã¾ã™", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "アップロードã—よã†ã¨ã—ã¦ã„るファイルã¯ã€ã‚µãƒ¼ãƒã§è¦å®šã•ã‚ŒãŸæœ€å¤§ã‚µã‚¤ã‚ºã‚’超ãˆã¦ã„ã¾ã™ã€‚", "Files are being scanned, please wait." => "ファイルをスキャンã—ã¦ã„ã¾ã™ã€ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。", "Current scanning" => "スキャン中", diff --git a/apps/files/l10n/ka_GE.php b/apps/files/l10n/ka_GE.php index 82b9c5df93..6ea75a2ea9 100644 --- a/apps/files/l10n/ka_GE.php +++ b/apps/files/l10n/ka_GE.php @@ -64,7 +64,7 @@ "You don’t have write permissions here." => "თქვენ áƒáƒ  გáƒáƒ¥áƒ•áƒ— ჩáƒáƒ¬áƒ”რის უფლებრáƒáƒ¥.", "Nothing in here. Upload something!" => "áƒáƒ¥ áƒáƒ áƒáƒ¤áƒ”რი áƒáƒ  áƒáƒ áƒ˜áƒ¡. áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ე რáƒáƒ›áƒ”!", "Download" => "ჩáƒáƒ›áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვáƒ", -"Unshare" => "გáƒáƒ£áƒ–იáƒáƒ áƒ”ბáƒáƒ“ი", +"Unshare" => "გáƒáƒ–იáƒáƒ áƒ”ბის მáƒáƒ®áƒ¡áƒœáƒ", "Upload too large" => "áƒáƒ¡áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ი ფáƒáƒ˜áƒšáƒ˜ ძáƒáƒšáƒ˜áƒáƒœ დიდიáƒ", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "ფáƒáƒ˜áƒšáƒ˜áƒ¡ ზáƒáƒ›áƒ რáƒáƒ›áƒšáƒ˜áƒ¡ áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვáƒáƒ¡áƒáƒª თქვენ áƒáƒžáƒ˜áƒ áƒ”ბთ, áƒáƒ­áƒáƒ áƒ‘ებს სერვერზე დáƒáƒ¨áƒ•áƒ”ბულ მáƒáƒ¥áƒ¡áƒ˜áƒ›áƒ£áƒ›áƒ¡.", "Files are being scanned, please wait." => "მიმდინáƒáƒ áƒ”áƒáƒ‘ს ფáƒáƒ˜áƒšáƒ”ბის სკáƒáƒœáƒ˜áƒ áƒ”ბáƒ, გთხáƒáƒ•áƒ— დáƒáƒ”ლáƒáƒ“áƒáƒ—.", diff --git a/apps/files/l10n/ko.php b/apps/files/l10n/ko.php index c35bdd115e..88378bb486 100644 --- a/apps/files/l10n/ko.php +++ b/apps/files/l10n/ko.php @@ -3,24 +3,24 @@ "Could not move %s" => "%s í•­ëª©ì„ ì´ë”©ì‹œí‚¤ì§€ 못하였ìŒ", "Unable to rename file" => "íŒŒì¼ ì´ë¦„바꾸기 í•  수 ì—†ìŒ", "No file was uploaded. Unknown error" => "파ì¼ì´ 업로드ë˜ì§€ 않았습니다. ì•Œ 수 없는 오류입니다", -"There is no error, the file uploaded with success" => "íŒŒì¼ ì—…ë¡œë“œì— ì„±ê³µí•˜ì˜€ìŠµë‹ˆë‹¤.", +"There is no error, the file uploaded with success" => "ì—…ë¡œë“œì— ì„±ê³µí•˜ì˜€ìŠµë‹ˆë‹¤.", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "업로드한 파ì¼ì´ php.iniì˜ upload_max_filesize보다 í½ë‹ˆë‹¤:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "업로드한 íŒŒì¼ í¬ê¸°ê°€ HTML í¼ì˜ MAX_FILE_SIZE보다 í¼", -"The uploaded file was only partially uploaded" => "파ì¼ì˜ ì¼ë¶€ë¶„만 업로드ë¨", -"No file was uploaded" => "파ì¼ì´ 업로드ë˜ì§€ 않았ìŒ", -"Missing a temporary folder" => "ìž„ì‹œ í´ë”ê°€ ì—†ìŒ", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "업로드한 파ì¼ì´ HTML ë¬¸ì„œì— ì§€ì •í•œ MAX_FILE_SIZE보다 ë” í¼", +"The uploaded file was only partially uploaded" => "파ì¼ì´ 부분ì ìœ¼ë¡œ 업로드ë¨", +"No file was uploaded" => "ì—…ë¡œë“œëœ íŒŒì¼ ì—†ìŒ", +"Missing a temporary folder" => "ìž„ì‹œ í´ë”ê°€ 사ë¼ì§", "Failed to write to disk" => "디스í¬ì— 쓰지 못했습니다", "Invalid directory." => "올바르지 ì•Šì€ ë””ë ‰í„°ë¦¬ìž…ë‹ˆë‹¤.", "Files" => "파ì¼", "Delete" => "ì‚­ì œ", "Rename" => "ì´ë¦„ 바꾸기", -"Pending" => "대기 중", +"Pending" => "보류 중", "{new_name} already exists" => "{new_name}ì´(ê°€) ì´ë¯¸ 존재함", "replace" => "바꾸기", "suggest name" => "ì´ë¦„ 제안", "cancel" => "취소", "replaced {new_name} with {old_name}" => "{old_name}ì´(ê°€) {new_name}(으)ë¡œ 대체ë¨", -"undo" => "ë˜ëŒë¦¬ê¸°", +"undo" => "실행 취소", "1 file uploading" => "íŒŒì¼ 1ê°œ 업로드 중", "'.' is an invalid file name." => "'.' 는 올바르지 ì•Šì€ íŒŒì¼ ì´ë¦„ 입니다.", "File name cannot be empty." => "íŒŒì¼ ì´ë¦„ì´ ë¹„ì–´ ìžˆì„ ìˆ˜ 없습니다.", @@ -28,7 +28,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "저장 ê³µê°„ì´ ê°€ë“ ì°¼ìŠµë‹ˆë‹¤. 파ì¼ì„ ì—…ë°ì´íŠ¸í•˜ê±°ë‚˜ ë™ê¸°í™”í•  수 없습니다!", "Your storage is almost full ({usedSpacePercent}%)" => "저장 ê³µê°„ì´ ê±°ì˜ ê°€ë“ ì°¼ìŠµë‹ˆë‹¤ ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "다운로드가 준비 중입니다. íŒŒì¼ í¬ê¸°ê°€ í¬ë‹¤ë©´ ì‹œê°„ì´ ì˜¤ëž˜ 걸릴 ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤.", -"Unable to upload your file as it is a directory or has 0 bytes" => "디렉터리 ë° ë¹ˆ 파ì¼ì€ 업로드할 수 없습니다", +"Unable to upload your file as it is a directory or has 0 bytes" => "ì´ íŒŒì¼ì€ 디렉터리ì´ê±°ë‚˜ 비어 있기 ë•Œë¬¸ì— ì—…ë¡œë“œí•  수 없습니다", "Not enough space available" => "여유 ê³µê°„ì´ ë¶€ì¡±í•©ë‹ˆë‹¤", "Upload cancelled." => "업로드가 취소ë˜ì—ˆìŠµë‹ˆë‹¤.", "File upload is in progress. Leaving the page now will cancel the upload." => "íŒŒì¼ ì—…ë¡œë“œê°€ 진행 중입니다. ì´ íŽ˜ì´ì§€ë¥¼ 벗어나면 업로드가 취소ë©ë‹ˆë‹¤.", @@ -59,7 +59,7 @@ "Nothing in here. Upload something!" => "ë‚´ìš©ì´ ì—†ìŠµë‹ˆë‹¤. 업로드할 수 있습니다!", "Download" => "다운로드", "Unshare" => "공유 í•´ì œ", -"Upload too large" => "업로드한 파ì¼ì´ 너무 í¼", +"Upload too large" => "업로드 용량 초과", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "ì´ íŒŒì¼ì´ 서버ì—ì„œ 허용하는 최대 업로드 가능 용량보다 í½ë‹ˆë‹¤.", "Files are being scanned, please wait." => "파ì¼ì„ 검색하고 있습니다. 기다려 주십시오.", "Current scanning" => "현재 검색", diff --git a/apps/files/l10n/lb.php b/apps/files/l10n/lb.php index 948a114acc..6533a12308 100644 --- a/apps/files/l10n/lb.php +++ b/apps/files/l10n/lb.php @@ -2,7 +2,7 @@ "There is no error, the file uploaded with success" => "Keen Feeler, Datei ass komplett ropgelueden ginn", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Déi ropgelueden Datei ass méi grouss wei d'MAX_FILE_SIZE Eegenschaft déi an der HTML form uginn ass", "The uploaded file was only partially uploaded" => "Déi ropgelueden Datei ass nëmmen hallef ropgelueden ginn", -"No file was uploaded" => "Et ass kee Fichier ropgeluede ginn", +"No file was uploaded" => "Et ass keng Datei ropgelueden ginn", "Missing a temporary folder" => "Et feelt en temporären Dossier", "Failed to write to disk" => "Konnt net op den Disk schreiwen", "Files" => "Dateien", @@ -31,7 +31,7 @@ "Folder" => "Dossier", "Cancel upload" => "Upload ofbriechen", "Nothing in here. Upload something!" => "Hei ass näischt. Lued eppes rop!", -"Download" => "Download", +"Download" => "Eroflueden", "Unshare" => "Net méi deelen", "Upload too large" => "Upload ze grouss", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Déi Dateien déi Dir probéiert erop ze lueden sinn méi grouss wei déi Maximal Gréisst déi op dësem Server erlaabt ass.", diff --git a/apps/files/l10n/lt_LT.php b/apps/files/l10n/lt_LT.php index 199b6978ce..750500a3d5 100644 --- a/apps/files/l10n/lt_LT.php +++ b/apps/files/l10n/lt_LT.php @@ -1,8 +1,8 @@ "Failas įkeltas sÄ—kmingai, be klaidų", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Ä®keliamo failo dydis virÅ¡ija MAX_FILE_SIZE nustatymÄ…, kuris naudojamas HTML formoje.", +"There is no error, the file uploaded with success" => "Klaidų nÄ—ra, failas įkeltas sÄ—kmingai", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Ä®keliamo failo dydis virÅ¡ija MAX_FILE_SIZE parametrÄ…, kuris yra nustatytas HTML formoje", "The uploaded file was only partially uploaded" => "Failas buvo įkeltas tik dalinai", -"No file was uploaded" => "Nebuvo įkeltas joks failas", +"No file was uploaded" => "Nebuvo įkeltas nÄ— vienas failas", "Missing a temporary folder" => "NÄ—ra laikinojo katalogo", "Failed to write to disk" => "Nepavyko įraÅ¡yti į diskÄ…", "Files" => "Failai", @@ -44,7 +44,7 @@ "Download" => "Atsisiųsti", "Unshare" => "Nebesidalinti", "Upload too large" => "Ä®kÄ—limui failas per didelis", -"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Bandomų įkelti failų dydis virÅ¡ija maksimalų, kuris leidžiamas Å¡iame serveryje", +"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Bandomų įkelti failų dydis virÅ¡ija maksimalų leidžiamÄ… Å¡iame serveryje", "Files are being scanned, please wait." => "Skenuojami failai, praÅ¡ome palaukti.", "Current scanning" => "Å iuo metu skenuojama" ); diff --git a/apps/files/l10n/lv.php b/apps/files/l10n/lv.php index 99304be9e0..1292514547 100644 --- a/apps/files/l10n/lv.php +++ b/apps/files/l10n/lv.php @@ -3,7 +3,7 @@ "Could not move %s" => "NevarÄ“ja pÄrvietot %s", "Unable to rename file" => "NevarÄ“ja pÄrsaukt datni", "No file was uploaded. Unknown error" => "Netika augÅ¡upielÄdÄ“ta neviena datne. NezinÄma kļūda", -"There is no error, the file uploaded with success" => "Viss kÄrtÄ«bÄ, datne augÅ¡upielÄdÄ“ta veiksmÄ«ga", +"There is no error, the file uploaded with success" => "AugÅ¡upielÄde pabeigta bez kļūdÄm", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "AugÅ¡upielÄdÄ“tÄ datne pÄrsniedz upload_max_filesize norÄdÄ«jumu php.ini datnÄ“:", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "AugÅ¡upielÄdÄ“tÄ datne pÄrsniedz MAX_FILE_SIZE norÄdi, kas ir norÄdÄ«ta HTML formÄ", "The uploaded file was only partially uploaded" => "AugÅ¡upielÄdÄ“tÄ datne ir tikai daļēji augÅ¡upielÄdÄ“ta", @@ -31,7 +31,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "JÅ«su krÄtuve ir pilna, datnes vairs nevar augÅ¡upielÄdÄ“t vai sinhronizÄ“t!", "Your storage is almost full ({usedSpacePercent}%)" => "JÅ«su krÄtuve ir gandrÄ«z pilna ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Tiek sagatavota lejupielÄde. Tas var aizņemt kÄdu laiciņu, ja datnes ir lielas.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Nevar augÅ¡upielÄdÄ“t jÅ«su datni, jo tÄ ir direktorija vai arÄ« tÄ ir 0 baitu liela", +"Unable to upload your file as it is a directory or has 0 bytes" => "Nevar augÅ¡upielÄdÄ“t jÅ«su datni, jo tÄ ir direktorija vai arÄ« tÄs izmÄ“rs ir 0 baiti", "Not enough space available" => "Nepietiek brÄ«vas vietas", "Upload cancelled." => "AugÅ¡upielÄde ir atcelta.", "File upload is in progress. Leaving the page now will cancel the upload." => "Notiek augÅ¡upielÄde. Pametot lapu tagad, tiks atcelta augÅ¡upielÄde.", diff --git a/apps/files/l10n/mk.php b/apps/files/l10n/mk.php index 32e7eadb93..78fed25cf9 100644 --- a/apps/files/l10n/mk.php +++ b/apps/files/l10n/mk.php @@ -1,11 +1,11 @@ "Ðиту еден фајл не Ñе вчита. Ðепозната грешка", -"There is no error, the file uploaded with success" => "Датотеката беше уÑпешно подигната.", +"There is no error, the file uploaded with success" => "Ðема грешка, датотеката беше подигната уÑпешно", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Подигнатата датотека ја надминува upload_max_filesize директивата во php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Големината на датотеката ја надминува MAX_FILE_SIZE директивата која беше Ñпецифицирана во HTML формата", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Подигнатата датотеката ја надминува MAX_FILE_SIZE директивата која беше поÑтавена во HTML формата", "The uploaded file was only partially uploaded" => "Датотеката беше Ñамо делумно подигната.", -"No file was uploaded" => "Ðе беше подигната датотека.", -"Missing a temporary folder" => "ÐедоÑтаÑува привремена папка", +"No file was uploaded" => "Ðе беше подигната датотека", +"Missing a temporary folder" => "Ðе поÑтои привремена папка", "Failed to write to disk" => "ÐеуÑпеав да запишам на диÑк", "Files" => "Датотеки", "Delete" => "Избриши", @@ -48,7 +48,7 @@ "Nothing in here. Upload something!" => "Тука нема ништо. Снимете нешто!", "Download" => "Преземи", "Unshare" => "Ðе Ñподелувај", -"Upload too large" => "Фајлот кој Ñе вчитува е преголем", +"Upload too large" => "Датотеката е премногу голема", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Датотеките кои Ñе обидувате да ги подигнете ја надминуваат макÑималната големина за подигнување датотеки на овој Ñервер.", "Files are being scanned, please wait." => "Се Ñкенираат датотеки, ве молам почекајте.", "Current scanning" => "Моментално Ñкенирам" diff --git a/apps/files/l10n/ms_MY.php b/apps/files/l10n/ms_MY.php index 2ce4f16332..a390288b36 100644 --- a/apps/files/l10n/ms_MY.php +++ b/apps/files/l10n/ms_MY.php @@ -1,13 +1,12 @@ "Tiada fail dimuatnaik. Ralat tidak diketahui.", -"There is no error, the file uploaded with success" => "Tiada ralat berlaku, fail berjaya dimuatnaik", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Saiz fail yang dimuatnaik melebihi MAX_FILE_SIZE yang ditetapkan dalam borang HTML", -"The uploaded file was only partially uploaded" => "Fail yang dimuatnaik tidak lengkap", -"No file was uploaded" => "Tiada fail dimuatnaik", -"Missing a temporary folder" => "Direktori sementara hilang", +"There is no error, the file uploaded with success" => "Tiada ralat, fail berjaya dimuat naik.", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Fail yang dimuat naik melebihi MAX_FILE_SIZE yang dinyatakan dalam form HTML ", +"The uploaded file was only partially uploaded" => "Sebahagian daripada fail telah dimuat naik. ", +"No file was uploaded" => "Tiada fail yang dimuat naik", +"Missing a temporary folder" => "Folder sementara hilang", "Failed to write to disk" => "Gagal untuk disimpan", -"Files" => "Fail-fail", -"Share" => "Kongsi", +"Files" => "fail", "Delete" => "Padam", "Pending" => "Dalam proses", "replace" => "ganti", @@ -15,7 +14,7 @@ "Unable to upload your file as it is a directory or has 0 bytes" => "Tidak boleh memuatnaik fail anda kerana mungkin ianya direktori atau saiz fail 0 bytes", "Upload cancelled." => "Muatnaik dibatalkan.", "Error" => "Ralat", -"Name" => "Nama", +"Name" => "Nama ", "Size" => "Saiz", "Modified" => "Dimodifikasi", "Upload" => "Muat naik", @@ -33,7 +32,7 @@ "Cancel upload" => "Batal muat naik", "Nothing in here. Upload something!" => "Tiada apa-apa di sini. Muat naik sesuatu!", "Download" => "Muat turun", -"Upload too large" => "Muatnaik terlalu besar", +"Upload too large" => "Muat naik terlalu besar", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Fail yang cuba dimuat naik melebihi saiz maksimum fail upload server", "Files are being scanned, please wait." => "Fail sedang diimbas, harap bersabar.", "Current scanning" => "Imbasan semasa" diff --git a/apps/files/l10n/nb_NO.php b/apps/files/l10n/nb_NO.php index 98f91b3eb5..54042c9124 100644 --- a/apps/files/l10n/nb_NO.php +++ b/apps/files/l10n/nb_NO.php @@ -1,10 +1,10 @@ "Ingen filer ble lastet opp. Ukjent feil.", -"There is no error, the file uploaded with success" => "Pust ut, ingen feil. Filen ble lastet opp problemfritt", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Filen du prøvde Ã¥ laste opp var større enn grensen satt i MAX_FILE_SIZE i HTML-skjemaet.", -"The uploaded file was only partially uploaded" => "Filen du prøvde Ã¥ laste opp ble kun delvis lastet opp", -"No file was uploaded" => "Ingen filer ble lastet opp", -"Missing a temporary folder" => "Mangler midlertidig mappe", +"There is no error, the file uploaded with success" => "Det er ingen feil. Filen ble lastet opp.", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Filstørrelsen overskrider maksgrensen pÃ¥ MAX_FILE_SIZE som ble oppgitt i HTML-skjemaet", +"The uploaded file was only partially uploaded" => "Filopplastningen ble bare delvis gjennomført", +"No file was uploaded" => "Ingen fil ble lastet opp", +"Missing a temporary folder" => "Mangler en midlertidig mappe", "Failed to write to disk" => "Klarte ikke Ã¥ skrive til disk", "Files" => "Filer", "Delete permanently" => "Slett permanent", @@ -18,7 +18,6 @@ "replaced {new_name} with {old_name}" => "erstatt {new_name} med {old_name}", "undo" => "angre", "1 file uploading" => "1 fil lastes opp", -"files uploading" => "filer lastes opp", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ugyldig navn, '\\', '/', '<', '>', ':', '\"', '|', '?' og '*' er ikke tillatt.", "Unable to upload your file as it is a directory or has 0 bytes" => "Kan ikke laste opp filen din siden det er en mappe eller den har 0 bytes", "Upload cancelled." => "Opplasting avbrutt.", @@ -49,7 +48,7 @@ "Nothing in here. Upload something!" => "Ingenting her. Last opp noe!", "Download" => "Last ned", "Unshare" => "Avslutt deling", -"Upload too large" => "Filen er for stor", +"Upload too large" => "Opplasting for stor", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Filene du prøver Ã¥ laste opp er for store for Ã¥ laste opp til denne serveren.", "Files are being scanned, please wait." => "Skanner etter filer, vennligst vent.", "Current scanning" => "PÃ¥gÃ¥ende skanning" diff --git a/apps/files/l10n/nl.php b/apps/files/l10n/nl.php index b9a05fdf23..38b55d34d9 100644 --- a/apps/files/l10n/nl.php +++ b/apps/files/l10n/nl.php @@ -3,12 +3,12 @@ "Could not move %s" => "Kon %s niet verplaatsen", "Unable to rename file" => "Kan bestand niet hernoemen", "No file was uploaded. Unknown error" => "Er was geen bestand geladen. Onbekende fout", -"There is no error, the file uploaded with success" => "De upload van het bestand is goedgegaan.", +"There is no error, the file uploaded with success" => "Geen fout opgetreden, bestand successvol geupload.", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Het geüploade bestand overscheidt de upload_max_filesize optie in php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Het bestand overschrijdt de MAX_FILE_SIZE instelling dat is opgegeven in het HTML formulier", -"The uploaded file was only partially uploaded" => "Het bestand is gedeeltelijk geüpload", -"No file was uploaded" => "Er is geen bestand geüpload", -"Missing a temporary folder" => "Er ontbreekt een tijdelijke map", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Het geüploade bestand is groter dan de MAX_FILE_SIZE richtlijn die is opgegeven in de HTML-formulier", +"The uploaded file was only partially uploaded" => "Het bestand is slechts gedeeltelijk geupload", +"No file was uploaded" => "Geen bestand geüpload", +"Missing a temporary folder" => "Een tijdelijke map mist", "Failed to write to disk" => "Schrijven naar schijf mislukt", "Not enough storage available" => "Niet genoeg opslagruimte beschikbaar", "Invalid directory." => "Ongeldige directory.", @@ -16,7 +16,7 @@ "Delete permanently" => "Verwijder definitief", "Delete" => "Verwijder", "Rename" => "Hernoem", -"Pending" => "In behandeling", +"Pending" => "Wachten", "{new_name} already exists" => "{new_name} bestaat al", "replace" => "vervang", "suggest name" => "Stel een naam voor", @@ -32,7 +32,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "Uw opslagruimte zit vol, Bestanden kunnen niet meer worden ge-upload of gesynchroniseerd!", "Your storage is almost full ({usedSpacePercent}%)" => "Uw opslagruimte zit bijna vol ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Uw download wordt voorbereid. Dit kan enige tijd duren bij grote bestanden.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Het lukt niet om uw bestand te uploaded, omdat het een folder of 0 bytes is", +"Unable to upload your file as it is a directory or has 0 bytes" => "uploaden van de file mislukt, het is of een directory of de bestandsgrootte is 0 bytes", "Not enough space available" => "Niet genoeg ruimte beschikbaar", "Upload cancelled." => "Uploaden geannuleerd.", "File upload is in progress. Leaving the page now will cancel the upload." => "Bestandsupload is bezig. Wanneer de pagina nu verlaten wordt, stopt de upload.", @@ -40,13 +40,13 @@ "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" => "Ongeldige mapnaam. Gebruik van'Gedeeld' is voorbehouden aan Owncloud", "Error" => "Fout", "Name" => "Naam", -"Size" => "Grootte", -"Modified" => "Aangepast", +"Size" => "Bestandsgrootte", +"Modified" => "Laatst aangepast", "1 folder" => "1 map", "{count} folders" => "{count} mappen", "1 file" => "1 bestand", "{count} files" => "{count} bestanden", -"Upload" => "Uploaden", +"Upload" => "Upload", "File handling" => "Bestand", "Maximum upload size" => "Maximale bestandsgrootte voor uploads", "max. possible: " => "max. mogelijk: ", @@ -54,7 +54,7 @@ "Enable ZIP-download" => "Zet ZIP-download aan", "0 is unlimited" => "0 is ongelimiteerd", "Maximum input size for ZIP files" => "Maximale grootte voor ZIP bestanden", -"Save" => "Bewaren", +"Save" => "Opslaan", "New" => "Nieuw", "Text file" => "Tekstbestand", "Folder" => "Map", @@ -63,9 +63,9 @@ "Cancel upload" => "Upload afbreken", "You don’t have write permissions here." => "U hebt hier geen schrijfpermissies.", "Nothing in here. Upload something!" => "Er bevindt zich hier niets. Upload een bestand!", -"Download" => "Downloaden", -"Unshare" => "Stop met delen", -"Upload too large" => "Upload is te groot", +"Download" => "Download", +"Unshare" => "Stop delen", +"Upload too large" => "Bestanden te groot", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "De bestanden die u probeert te uploaden zijn groter dan de maximaal toegestane bestandsgrootte voor deze server.", "Files are being scanned, please wait." => "Bestanden worden gescand, even wachten.", "Current scanning" => "Er wordt gescand", diff --git a/apps/files/l10n/nn_NO.php b/apps/files/l10n/nn_NO.php index 2042e7bf8a..8f32dc012e 100644 --- a/apps/files/l10n/nn_NO.php +++ b/apps/files/l10n/nn_NO.php @@ -1,74 +1,23 @@ "Klarte ikkje Ã¥ flytta %s – det finst allereie ei fil med dette namnet", -"Could not move %s" => "Klarte ikkje Ã¥ flytta %s", -"Unable to rename file" => "Klarte ikkje Ã¥ endra filnamnet", -"No file was uploaded. Unknown error" => "Ingen filer lasta opp. Ukjend feil", "There is no error, the file uploaded with success" => "Ingen feil, fila vart lasta opp", -"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Fila du lasta opp er større enn det «upload_max_filesize» i php.ini tillater: ", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Den opplasta fila er større enn variabelen MAX_FILE_SIZE i HTML-skjemaet", "The uploaded file was only partially uploaded" => "Fila vart berre delvis lasta opp", "No file was uploaded" => "Ingen filer vart lasta opp", "Missing a temporary folder" => "Manglar ei mellombels mappe", -"Failed to write to disk" => "Klarte ikkje Ã¥ skriva til disk", -"Not enough storage available" => "Ikkje nok lagringsplass tilgjengeleg", -"Invalid directory." => "Ugyldig mappe.", "Files" => "Filer", -"Share" => "Del", -"Delete permanently" => "Slett for godt", "Delete" => "Slett", -"Rename" => "Endra namn", -"Pending" => "Under vegs", -"{new_name} already exists" => "{new_name} finst allereie", -"replace" => "byt ut", -"suggest name" => "føreslÃ¥ namn", -"cancel" => "avbryt", -"replaced {new_name} with {old_name}" => "bytte ut {new_name} med {old_name}", -"undo" => "angre", -"perform delete operation" => "utfør sletting", -"1 file uploading" => "1 fil lastar opp", -"files uploading" => "filer lastar opp", -"'.' is an invalid file name." => "«.» er eit ugyldig filnamn.", -"File name cannot be empty." => "Filnamnet kan ikkje vera tomt.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ugyldig namn, «\\», «/», «<», «>», «:», «\"», «|», «?» og «*» er ikkje tillate.", -"Your storage is full, files can not be updated or synced anymore!" => "Lagringa di er full, kan ikkje lenger oppdatera eller synkronisera!", -"Your storage is almost full ({usedSpacePercent}%)" => "Lagringa di er nesten full ({usedSpacePercent} %)", -"Your download is being prepared. This might take some time if the files are big." => "Gjer klar nedlastinga di. Dette kan ta ei stund viss filene er store.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Klarte ikkje Ã¥ lasta opp fila sidan ho er ei mappe eller er pÃ¥ 0 byte", -"Not enough space available" => "Ikkje nok lagringsplass tilgjengeleg", -"Upload cancelled." => "Opplasting avbroten.", -"File upload is in progress. Leaving the page now will cancel the upload." => "Fila lastar no opp. Viss du forlèt sida no vil opplastinga bli avbroten.", -"URL cannot be empty." => "URL-en kan ikkje vera tom.", -"Invalid folder name. Usage of 'Shared' is reserved by Owncloud" => "Ugyldig mappenamn. Mappa «Shared» er reservert av ownCloud", "Error" => "Feil", "Name" => "Namn", "Size" => "Storleik", "Modified" => "Endra", -"1 folder" => "1 mappe", -"{count} folders" => "{count} mapper", -"1 file" => "1 fil", -"{count} files" => "{count} filer", "Upload" => "Last opp", -"File handling" => "Filhandtering", "Maximum upload size" => "Maksimal opplastingsstorleik", -"max. possible: " => "maks. moglege:", -"Needed for multi-file and folder downloads." => "Naudsynt for fleirfils- og mappenedlastingar.", -"Enable ZIP-download" => "Skru pÃ¥ ZIP-nedlasting", -"0 is unlimited" => "0 er ubegrensa", -"Maximum input size for ZIP files" => "Maksimal storleik for ZIP-filer", "Save" => "Lagre", "New" => "Ny", "Text file" => "Tekst fil", "Folder" => "Mappe", -"From link" => "FrÃ¥ lenkje", -"Deleted files" => "Sletta filer", -"Cancel upload" => "Avbryt opplasting", -"You don’t have write permissions here." => "Du har ikkje skriverettar her.", "Nothing in here. Upload something!" => "Ingenting her. Last noko opp!", "Download" => "Last ned", -"Unshare" => "Udel", "Upload too large" => "For stor opplasting", -"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Filene du prøver Ã¥ laste opp er større enn maksgrensa til denne tenaren.", -"Files are being scanned, please wait." => "Skannar filer, ver venleg og vent.", -"Current scanning" => "Køyrande skanning", -"Upgrading filesystem cache..." => "Oppgraderer mellomlageret av filsystemet …" +"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Filene du prøver Ã¥ laste opp er større enn maksgrensa til denne tenaren." ); diff --git a/apps/files/l10n/oc.php b/apps/files/l10n/oc.php index 03b46444b6..b1ef621658 100644 --- a/apps/files/l10n/oc.php +++ b/apps/files/l10n/oc.php @@ -14,7 +14,6 @@ "cancel" => "anulla", "undo" => "defar", "1 file uploading" => "1 fichièr al amontcargar", -"files uploading" => "fichièrs al amontcargar", "Unable to upload your file as it is a directory or has 0 bytes" => "Impossible d'amontcargar lo teu fichièr qu'es un repertòri o que ten pas que 0 octet.", "Upload cancelled." => "Amontcargar anullat.", "File upload is in progress. Leaving the page now will cancel the upload." => "Un amontcargar es a se far. Daissar aquesta pagina ara tamparà lo cargament. ", @@ -37,7 +36,7 @@ "Cancel upload" => " Anulla l'amontcargar", "Nothing in here. Upload something!" => "Pas res dedins. Amontcarga qualquaren", "Download" => "Avalcarga", -"Unshare" => "Pas partejador", +"Unshare" => "Non parteja", "Upload too large" => "Amontcargament tròp gròs", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Los fichièrs que sias a amontcargar son tròp pesucs per la talha maxi pel servidor.", "Files are being scanned, please wait." => "Los fiichièrs son a èsser explorats, ", diff --git a/apps/files/l10n/pl.php b/apps/files/l10n/pl.php index 8b7f665cee..e9a78e2f44 100644 --- a/apps/files/l10n/pl.php +++ b/apps/files/l10n/pl.php @@ -3,12 +3,12 @@ "Could not move %s" => "Nie można byÅ‚o przenieść %s", "Unable to rename file" => "Nie można zmienić nazwy pliku", "No file was uploaded. Unknown error" => "Å»aden plik nie zostaÅ‚ zaÅ‚adowany. Nieznany bÅ‚Ä…d", -"There is no error, the file uploaded with success" => "Nie byÅ‚o bÅ‚Ä™dów, plik wysÅ‚ano poprawnie.", +"There is no error, the file uploaded with success" => "PrzesÅ‚ano plik", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Wgrany plik przekracza wartość upload_max_filesize zdefiniowanÄ… w php.ini: ", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "WysÅ‚any plik przekracza wielkość dyrektywy MAX_FILE_SIZE okreÅ›lonej w formularzu HTML", "The uploaded file was only partially uploaded" => "ZaÅ‚adowany plik zostaÅ‚ wysÅ‚any tylko częściowo.", -"No file was uploaded" => "Nie wysÅ‚ano żadnego pliku", -"Missing a temporary folder" => "Brak folderu tymczasowego", +"No file was uploaded" => "Nie przesÅ‚ano żadnego pliku", +"Missing a temporary folder" => "Brak katalogu tymczasowego", "Failed to write to disk" => "BÅ‚Ä…d zapisu na dysk", "Not enough storage available" => "Za maÅ‚o dostÄ™pnego miejsca", "Invalid directory." => "ZÅ‚a Å›cieżka.", @@ -46,7 +46,7 @@ "{count} folders" => "Ilość folderów: {count}", "1 file" => "1 plik", "{count} files" => "Ilość plików: {count}", -"Upload" => "WyÅ›lij", +"Upload" => "PrzeÅ›lij", "File handling" => "ZarzÄ…dzanie plikami", "Maximum upload size" => "Maksymalny rozmiar wysyÅ‚anego pliku", "max. possible: " => "maks. możliwy:", @@ -57,15 +57,15 @@ "Save" => "Zapisz", "New" => "Nowy", "Text file" => "Plik tekstowy", -"Folder" => "Folder", +"Folder" => "Katalog", "From link" => "Z odnoÅ›nika", "Deleted files" => "Pliki usuniÄ™te", "Cancel upload" => "Anuluj wysyÅ‚anie", "You don’t have write permissions here." => "Nie masz uprawnieÅ„ do zapisu w tym miejscu.", "Nothing in here. Upload something!" => "Pusto. WyÅ›lij coÅ›!", "Download" => "Pobierz", -"Unshare" => "Zatrzymaj współdzielenie", -"Upload too large" => "Åadowany plik jest za duży", +"Unshare" => "Nie udostÄ™pniaj", +"Upload too large" => "WysyÅ‚any plik ma za duży rozmiar", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Pliki, które próbujesz przesÅ‚ać, przekraczajÄ… maksymalnÄ… dopuszczalnÄ… wielkość.", "Files are being scanned, please wait." => "Skanowanie plików, proszÄ™ czekać.", "Current scanning" => "Aktualnie skanowane", diff --git a/apps/files/l10n/pt_BR.php b/apps/files/l10n/pt_BR.php index bd038806d2..ad8f37c24f 100644 --- a/apps/files/l10n/pt_BR.php +++ b/apps/files/l10n/pt_BR.php @@ -3,11 +3,11 @@ "Could not move %s" => "Impossível mover %s", "Unable to rename file" => "Impossível renomear arquivo", "No file was uploaded. Unknown error" => "Nenhum arquivo foi enviado. Erro desconhecido", -"There is no error, the file uploaded with success" => "Sem erros, o arquivo foi enviado com sucesso", +"There is no error, the file uploaded with success" => "Não houve nenhum erro, o arquivo foi transferido com sucesso", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "O arquivo enviado excede a diretiva upload_max_filesize no php.ini: ", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "O arquivo carregado excede o argumento MAX_FILE_SIZE especificado no formulário HTML", -"The uploaded file was only partially uploaded" => "O arquivo foi parcialmente enviado", -"No file was uploaded" => "Nenhum arquivo enviado", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "O arquivo carregado excede o MAX_FILE_SIZE que foi especificado no formulário HTML", +"The uploaded file was only partially uploaded" => "O arquivo foi transferido parcialmente", +"No file was uploaded" => "Nenhum arquivo foi transferido", "Missing a temporary folder" => "Pasta temporária não encontrada", "Failed to write to disk" => "Falha ao escrever no disco", "Not enough storage available" => "Espaço de armazenamento insuficiente", @@ -46,7 +46,7 @@ "{count} folders" => "{count} pastas", "1 file" => "1 arquivo", "{count} files" => "{count} arquivos", -"Upload" => "Upload", +"Upload" => "Carregar", "File handling" => "Tratamento de Arquivo", "Maximum upload size" => "Tamanho máximo para carregar", "max. possible: " => "max. possível:", @@ -54,7 +54,7 @@ "Enable ZIP-download" => "Habilitar ZIP-download", "0 is unlimited" => "0 para ilimitado", "Maximum input size for ZIP files" => "Tamanho máximo para arquivo ZIP", -"Save" => "Guardar", +"Save" => "Salvar", "New" => "Novo", "Text file" => "Arquivo texto", "Folder" => "Pasta", @@ -65,7 +65,7 @@ "Nothing in here. Upload something!" => "Nada aqui.Carrege alguma coisa!", "Download" => "Baixar", "Unshare" => "Descompartilhar", -"Upload too large" => "Upload muito grande", +"Upload too large" => "Arquivo muito grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Os arquivos que você está tentando carregar excedeu o tamanho máximo para arquivos no servidor.", "Files are being scanned, please wait." => "Arquivos sendo escaneados, por favor aguarde.", "Current scanning" => "Scanning atual", diff --git a/apps/files/l10n/pt_PT.php b/apps/files/l10n/pt_PT.php index b799a4b81a..c06108cf2b 100644 --- a/apps/files/l10n/pt_PT.php +++ b/apps/files/l10n/pt_PT.php @@ -3,18 +3,18 @@ "Could not move %s" => "Não foi possível move o ficheiro %s", "Unable to rename file" => "Não foi possível renomear o ficheiro", "No file was uploaded. Unknown error" => "Nenhum ficheiro foi carregado. Erro desconhecido", -"There is no error, the file uploaded with success" => "Não ocorreram erros, o ficheiro foi submetido com sucesso", +"There is no error, the file uploaded with success" => "Sem erro, ficheiro enviado com sucesso", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "O ficheiro enviado excede o limite permitido na directiva do php.ini upload_max_filesize", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "O tamanho do ficheiro carregado ultrapassa o valor MAX_FILE_SIZE definido no formulário HTML", -"The uploaded file was only partially uploaded" => "O ficheiro seleccionado foi apenas carregado parcialmente", -"No file was uploaded" => "Nenhum ficheiro foi submetido", -"Missing a temporary folder" => "Está a faltar a pasta temporária", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "O ficheiro enviado excede o diretivo MAX_FILE_SIZE especificado no formulário HTML", +"The uploaded file was only partially uploaded" => "O ficheiro enviado só foi enviado parcialmente", +"No file was uploaded" => "Não foi enviado nenhum ficheiro", +"Missing a temporary folder" => "Falta uma pasta temporária", "Failed to write to disk" => "Falhou a escrita no disco", "Not enough storage available" => "Não há espaço suficiente em disco", "Invalid directory." => "Directório Inválido", "Files" => "Ficheiros", "Delete permanently" => "Eliminar permanentemente", -"Delete" => "Eliminar", +"Delete" => "Apagar", "Rename" => "Renomear", "Pending" => "Pendente", "{new_name} already exists" => "O nome {new_name} já existe", @@ -46,11 +46,11 @@ "{count} folders" => "{count} pastas", "1 file" => "1 ficheiro", "{count} files" => "{count} ficheiros", -"Upload" => "Carregar", +"Upload" => "Enviar", "File handling" => "Manuseamento de ficheiros", "Maximum upload size" => "Tamanho máximo de envio", "max. possible: " => "max. possivel: ", -"Needed for multi-file and folder downloads." => "Necessário para multi download de ficheiros e pastas", +"Needed for multi-file and folder downloads." => "Necessário para descarregamento múltiplo de ficheiros e pastas", "Enable ZIP-download" => "Permitir descarregar em ficheiro ZIP", "0 is unlimited" => "0 é ilimitado", "Maximum input size for ZIP files" => "Tamanho máximo para ficheiros ZIP", @@ -65,8 +65,8 @@ "Nothing in here. Upload something!" => "Vazio. Envie alguma coisa!", "Download" => "Transferir", "Unshare" => "Deixar de partilhar", -"Upload too large" => "Upload muito grande", -"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Os ficheiro que está a tentar enviar excedem o tamanho máximo de envio neste servidor.", +"Upload too large" => "Envio muito grande", +"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Os ficheiros que está a tentar enviar excedem o tamanho máximo de envio permitido neste servidor.", "Files are being scanned, please wait." => "Os ficheiros estão a ser analisados, por favor aguarde.", "Current scanning" => "Análise actual", "Upgrading filesystem cache..." => "Atualizar cache do sistema de ficheiros..." diff --git a/apps/files/l10n/ro.php b/apps/files/l10n/ro.php index b2b6ee4963..e3cab80fbc 100644 --- a/apps/files/l10n/ro.php +++ b/apps/files/l10n/ro.php @@ -3,18 +3,15 @@ "Could not move %s" => "Nu s-a putut muta %s", "Unable to rename file" => "Nu s-a putut redenumi fiÈ™ierul", "No file was uploaded. Unknown error" => "Nici un fiÈ™ier nu a fost încărcat. Eroare necunoscută", -"There is no error, the file uploaded with success" => "Nu a apărut nici o eroare, fiÈ™ierul a fost încărcat cu succes", +"There is no error, the file uploaded with success" => "Nicio eroare, fiÈ™ierul a fost încărcat cu succes", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Fisierul incarcat depaseste upload_max_filesize permisi in php.ini: ", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "FiÈ™ierul are o dimensiune mai mare decât variabile MAX_FILE_SIZE specificată în formularul HTML", "The uploaded file was only partially uploaded" => "FiÈ™ierul a fost încărcat doar parÈ›ial", -"No file was uploaded" => "Nu a fost încărcat nici un fiÈ™ier", -"Missing a temporary folder" => "LipseÈ™te un director temporar", +"No file was uploaded" => "Niciun fiÈ™ier încărcat", +"Missing a temporary folder" => "LipseÈ™te un dosar temporar", "Failed to write to disk" => "Eroare la scriere pe disc", -"Not enough storage available" => "Nu este suficient spaÈ›iu disponibil", "Invalid directory." => "Director invalid.", "Files" => "FiÈ™iere", -"Share" => "Partajează", -"Delete permanently" => "Stergere permanenta", "Delete" => "Șterge", "Rename" => "Redenumire", "Pending" => "ÃŽn aÈ™teptare", @@ -24,14 +21,10 @@ "cancel" => "anulare", "replaced {new_name} with {old_name}" => "{new_name} inlocuit cu {old_name}", "undo" => "Anulează ultima acÈ›iune", -"perform delete operation" => "efectueaza operatiunea de stergere", "1 file uploading" => "un fiÈ™ier se încarcă", -"files uploading" => "fiÈ™iere se încarcă", "'.' is an invalid file name." => "'.' este un nume invalid de fiÈ™ier.", "File name cannot be empty." => "Numele fiÈ™ierului nu poate rămâne gol.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nume invalid, '\\', '/', '<', '>', ':', '\"', '|', '?' si '*' nu sunt permise.", -"Your storage is full, files can not be updated or synced anymore!" => "Spatiul de stocare este plin, nu mai puteti incarca s-au sincroniza alte fisiere.", -"Your storage is almost full ({usedSpacePercent}%)" => "Spatiul de stocare este aproape plin ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Se pregăteÈ™te descărcarea. Aceasta poate să dureze ceva timp dacă fiÈ™ierele sunt mari.", "Unable to upload your file as it is a directory or has 0 bytes" => "Nu s-a putut încărca fiÈ™ierul tău deoarece pare să fie un director sau are 0 bytes.", "Not enough space available" => "Nu este suficient spaÈ›iu disponibil", @@ -47,7 +40,7 @@ "{count} folders" => "{count} foldare", "1 file" => "1 fisier", "{count} files" => "{count} fisiere", -"Upload" => "ÃŽncărcare", +"Upload" => "ÃŽncarcă", "File handling" => "Manipulare fiÈ™iere", "Maximum upload size" => "Dimensiune maximă admisă la încărcare", "max. possible: " => "max. posibil:", @@ -55,20 +48,17 @@ "Enable ZIP-download" => "Activează descărcare fiÈ™iere compresate", "0 is unlimited" => "0 e nelimitat", "Maximum input size for ZIP files" => "Dimensiunea maximă de intrare pentru fiÈ™iere compresate", -"Save" => "Salvează", +"Save" => "Salvare", "New" => "Nou", "Text file" => "FiÈ™ier text", "Folder" => "Dosar", "From link" => "de la adresa", -"Deleted files" => "Sterge fisierele", "Cancel upload" => "Anulează încărcarea", -"You don’t have write permissions here." => "Nu ai permisiunea de a sterge fisiere aici.", "Nothing in here. Upload something!" => "Nimic aici. ÃŽncarcă ceva!", "Download" => "Descarcă", -"Unshare" => "Anulare partajare", +"Unshare" => "Anulează partajarea", "Upload too large" => "FiÈ™ierul încărcat este prea mare", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "FiÈ™ierul care l-ai încărcat a depășită limita maximă admisă la încărcare pe acest server.", "Files are being scanned, please wait." => "FiÈ™ierele sunt scanate, te rog aÈ™teptă.", -"Current scanning" => "ÃŽn curs de scanare", -"Upgrading filesystem cache..." => "Modernizare fisiere de sistem cache.." +"Current scanning" => "ÃŽn curs de scanare" ); diff --git a/apps/files/l10n/ru.php b/apps/files/l10n/ru.php index 1bf3b174b8..37f2e083c4 100644 --- a/apps/files/l10n/ru.php +++ b/apps/files/l10n/ru.php @@ -3,12 +3,12 @@ "Could not move %s" => "Ðевозможно перемеÑтить %s", "Unable to rename file" => "Ðевозможно переименовать файл", "No file was uploaded. Unknown error" => "Файл не был загружен. ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°", -"There is no error, the file uploaded with success" => "Файл загружен уÑпешно.", +"There is no error, the file uploaded with success" => "Файл уÑпешно загружен", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Файл превышает размер уÑтановленный upload_max_filesize в php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Загружаемый файл превоÑходит значение переменной MAX_FILE_SIZE, указанной в форме HTML", -"The uploaded file was only partially uploaded" => "Файл загружен чаÑтично", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Файл превышает размер MAX_FILE_SIZE, указаный в HTML-форме", +"The uploaded file was only partially uploaded" => "Файл был загружен не полноÑтью", "No file was uploaded" => "Файл не был загружен", -"Missing a temporary folder" => "ОтÑутÑтвует Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°", +"Missing a temporary folder" => "Ðевозможно найти временную папку", "Failed to write to disk" => "Ошибка запиÑи на диÑк", "Not enough storage available" => "ÐедоÑтаточно доÑтупного меÑта в хранилище", "Invalid directory." => "Ðеправильный каталог.", @@ -25,28 +25,27 @@ "undo" => "отмена", "perform delete operation" => "выполнÑетÑÑ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ", "1 file uploading" => "загружаетÑÑ 1 файл", -"files uploading" => "файлы загружаютÑÑ", "'.' is an invalid file name." => "'.' - неправильное Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°.", "File name cannot be empty." => "Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° не может быть пуÑтым.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ðеправильное имÑ, '\\', '/', '<', '>', ':', '\"', '|', '?' и '*' недопуÑтимы.", "Your storage is full, files can not be updated or synced anymore!" => "Ваше диÑковое проÑтранÑтво полноÑтью заполнено, произведите очиÑтку перед загрузкой новых файлов.", "Your storage is almost full ({usedSpacePercent}%)" => "Ваше хранилище почти заполнено ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Загрузка началаÑÑŒ. Это может потребовать много времени, еÑли файл большого размера.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Файл не был загружен: его размер 0 байт либо Ñто не файл, а директориÑ.", +"Unable to upload your file as it is a directory or has 0 bytes" => "Ðе удаетÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ файл размером 0 байт в каталог", "Not enough space available" => "ÐедоÑтаточно Ñвободного меÑта", "Upload cancelled." => "Загрузка отменена.", "File upload is in progress. Leaving the page now will cancel the upload." => "Файл в процеÑÑе загрузки. Покинув Ñтраницу вы прервёте загрузку.", "URL cannot be empty." => "СÑылка не может быть пуÑтой.", "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" => "Ðеправильное Ð¸Ð¼Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð°. Ð˜Ð¼Ñ 'Shared' зарезервировано.", "Error" => "Ошибка", -"Name" => "ИмÑ", +"Name" => "Ðазвание", "Size" => "Размер", "Modified" => "Изменён", "1 folder" => "1 папка", "{count} folders" => "{count} папок", "1 file" => "1 файл", "{count} files" => "{count} файлов", -"Upload" => "Загрузка", +"Upload" => "Загрузить", "File handling" => "Управление файлами", "Maximum upload size" => "МакÑимальный размер загружаемого файла", "max. possible: " => "макÑ. возможно: ", @@ -64,8 +63,8 @@ "You don’t have write permissions here." => "У Ð²Ð°Ñ Ð½ÐµÑ‚ разрешений на запиÑÑŒ здеÑÑŒ.", "Nothing in here. Upload something!" => "ЗдеÑÑŒ ничего нет. Загрузите что-нибудь!", "Download" => "Скачать", -"Unshare" => "Закрыть общий доÑтуп", -"Upload too large" => "Файл Ñлишком велик", +"Unshare" => "Отменить публикацию", +"Upload too large" => "Файл Ñлишком большой", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Файлы, которые Ð’Ñ‹ пытаетеÑÑŒ загрузить, превышают лимит Ð´Ð»Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð² на Ñтом Ñервере.", "Files are being scanned, please wait." => "Подождите, файлы ÑканируютÑÑ.", "Current scanning" => "Текущее Ñканирование", diff --git a/apps/files/l10n/si_LK.php b/apps/files/l10n/si_LK.php index 351021a9f8..dfcca6f689 100644 --- a/apps/files/l10n/si_LK.php +++ b/apps/files/l10n/si_LK.php @@ -1,14 +1,13 @@ "ගොනුවක් උඩුගත නොවුනි. නොහà·à¶³à·’නු දà·à·‚යක්", -"There is no error, the file uploaded with success" => "දà·à·‚යක් නොමà·à¶­. à·ƒà·à¶»à·Šà¶®à¶šà·€ ගොනුව උඩුගත කෙරුණි", +"There is no error, the file uploaded with success" => "නිවà·à¶»à¶¯à·’ à·€ ගොනුව උඩුගත කෙරිනි", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "උඩුගත කළ ගොනුවේ විà·à·à¶½à¶­à·Šà·€à¶º HTML පà·à¶»à¶¸à¶ºà·š නියම කළ ඇති MAX_FILE_SIZE විà·à·à¶½à¶­à·Šà·€à¶ºà¶§ වඩ෠වà·à¶©à·’ය", "The uploaded file was only partially uploaded" => "උඩුගත කළ ගොනුවේ කොටසක් පමණක් උඩුගත විය", -"No file was uploaded" => "ගොනුවක් උඩුගත නොවුණි", -"Missing a temporary folder" => "තà·à·€à¶šà·à¶½à·’ක ෆොල්ඩරයක් අතුරුදහන්", +"No file was uploaded" => "කිසිදු ගොනවක් උඩුගත නොවිනි", +"Missing a temporary folder" => "තà·à·€à¶šà·à¶½à·’ක ෆොල්ඩරයක් සොයà·à¶œà¶­ නොහà·à¶š", "Failed to write to disk" => "තà·à¶§à·’ගත කිරීම අසà·à¶»à·Šà¶®à¶šà¶ºà·’", "Files" => "ගොනු", -"Share" => "බෙද෠හද෠ගන්න", -"Delete" => "මක෠දමන්න", +"Delete" => "මකන්න", "Rename" => "නà·à·€à¶­ නම් කරන්න", "replace" => "ප්â€à¶»à¶­à·’ස්ථà·à¶´à¶±à¶º කරන්න", "suggest name" => "නමක් යà·à¶¢à¶±à· කරන්න", @@ -24,7 +23,7 @@ "Modified" => "වෙනස් කළ", "1 folder" => "1 ෆොල්ඩරයක්", "1 file" => "1 ගොනුවක්", -"Upload" => "උඩුගත කරන්න", +"Upload" => "උඩුගත කිරීම", "File handling" => "ගොනු පරිහරණය", "Maximum upload size" => "උඩුගත කිරීමක උපරිම ප්â€à¶»à¶¸à·à¶«à¶º", "max. possible: " => "à·„à·à¶šà·’ උපරිමය:", @@ -39,7 +38,7 @@ "From link" => "යොමුවෙන්", "Cancel upload" => "උඩුගත කිරීම අත් හරින්න", "Nothing in here. Upload something!" => "මෙහි කිසිවක් නොමà·à¶­. යමක් උඩුගත කරන්න", -"Download" => "බà·à¶±à·Šà¶±", +"Download" => "බà·à¶œà¶­ කිරීම", "Unshare" => "නොබෙදු", "Upload too large" => "උඩුගත කිරීම විà·à·à¶½ à·€à·à¶©à·’ය", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "ඔබ උඩුගත කිරීමට තà·à¶­à·Š කරන ගොනු මෙම සේවà·à¶¯à·à¶ºà¶šà¶ºà· උඩුගත කිරීමට ඉඩදී ඇති උපරිම ගොනු විà·à·à¶½à¶­à·Šà·€à¶ºà¶§ වඩ෠වà·à¶©à·’ය", diff --git a/apps/files/l10n/sk_SK.php b/apps/files/l10n/sk_SK.php index 42eb3b1238..ee89a4c7d6 100644 --- a/apps/files/l10n/sk_SK.php +++ b/apps/files/l10n/sk_SK.php @@ -5,18 +5,18 @@ "No file was uploaded. Unknown error" => "Žiaden súbor nebol odoslaný. Neznáma chyba", "There is no error, the file uploaded with success" => "Nenastala žiadna chyba, súbor bol úspeÅ¡ne nahraný", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Nahraný súbor predÄil konfiguraÄnú direktívu upload_max_filesize v súbore php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Ukladaný súbor prekraÄuje nastavenie MAX_FILE_SIZE z volieb HTML formulára.", -"The uploaded file was only partially uploaded" => "Ukladaný súbor sa nahral len ÄiastoÄne", -"No file was uploaded" => "Žiadny súbor nebol uložený", -"Missing a temporary folder" => "Chýba doÄasný prieÄinok", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Nahrávaný súbor presiahol MAX_FILE_SIZE direktívu, ktorá bola Å¡pecifikovaná v HTML formulári", +"The uploaded file was only partially uploaded" => "Nahrávaný súbor bol iba ÄiastoÄne nahraný", +"No file was uploaded" => "Žiaden súbor nebol nahraný", +"Missing a temporary folder" => "Chýbajúci doÄasný prieÄinok", "Failed to write to disk" => "Zápis na disk sa nepodaril", "Not enough storage available" => "Nedostatok dostupného úložného priestoru", "Invalid directory." => "Neplatný prieÄinok", "Files" => "Súbory", "Delete permanently" => "ZmazaÅ¥ trvalo", -"Delete" => "ZmazaÅ¥", +"Delete" => "OdstrániÅ¥", "Rename" => "PremenovaÅ¥", -"Pending" => "Prebieha", +"Pending" => "ÄŒaká sa", "{new_name} already exists" => "{new_name} už existuje", "replace" => "nahradiÅ¥", "suggest name" => "pomôcÅ¥ s menom", @@ -32,14 +32,14 @@ "Your storage is full, files can not be updated or synced anymore!" => "VaÅ¡e úložisko je plné. Súbory nemožno aktualizovaÅ¥ ani synchronizovaÅ¥!", "Your storage is almost full ({usedSpacePercent}%)" => "VaÅ¡e úložisko je takmer plné ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "VaÅ¡e sÅ¥ahovanie sa pripravuje. Ak sú sÅ¥ahované súbory veľké, môže to chvíľu trvaÅ¥.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Nedá sa odoslaÅ¥ Váš súbor, pretože je to prieÄinok, alebo je jeho veľkosÅ¥ 0 bajtov", +"Unable to upload your file as it is a directory or has 0 bytes" => "Nemôžem nahraÅ¥ súbor lebo je to prieÄinok alebo má 0 bajtov.", "Not enough space available" => "Nie je k dispozícii dostatok miesta", "Upload cancelled." => "Odosielanie zruÅ¡ené", "File upload is in progress. Leaving the page now will cancel the upload." => "Opustenie stránky zruší práve prebiehajúce odosielanie súboru.", "URL cannot be empty." => "URL nemôže byÅ¥ prázdne", "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" => "Neplatné meno prieÄinka. Používanie mena 'Shared' je vyhradené len pre Owncloud", "Error" => "Chyba", -"Name" => "Názov", +"Name" => "Meno", "Size" => "VeľkosÅ¥", "Modified" => "Upravené", "1 folder" => "1 prieÄinok", @@ -55,7 +55,7 @@ "0 is unlimited" => "0 znamená neobmedzené", "Maximum input size for ZIP files" => "NajväÄÅ¡ia veľkosÅ¥ ZIP súborov", "Save" => "UložiÅ¥", -"New" => "Nová", +"New" => "Nový", "Text file" => "Textový súbor", "Folder" => "PrieÄinok", "From link" => "Z odkazu", @@ -63,9 +63,9 @@ "Cancel upload" => "ZruÅ¡iÅ¥ odosielanie", "You don’t have write permissions here." => "Nemáte oprávnenie na zápis.", "Nothing in here. Upload something!" => "Žiadny súbor. Nahrajte nieÄo!", -"Download" => "SÅ¥ahovanie", -"Unshare" => "ZruÅ¡iÅ¥ zdieľanie", -"Upload too large" => "Nahrávanie je príliÅ¡ veľké", +"Download" => "StiahnuÅ¥", +"Unshare" => "NezdielaÅ¥", +"Upload too large" => "Odosielaný súbor je príliÅ¡ veľký", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Súbory, ktoré sa snažíte nahraÅ¥, presahujú maximálnu veľkosÅ¥ pre nahratie súborov na tento server.", "Files are being scanned, please wait." => "ÄŒakajte, súbory sú prehľadávané.", "Current scanning" => "Práve prezerané", diff --git a/apps/files/l10n/sl.php b/apps/files/l10n/sl.php index 44c33d62fb..65d463e13d 100644 --- a/apps/files/l10n/sl.php +++ b/apps/files/l10n/sl.php @@ -2,19 +2,18 @@ "Could not move %s - File with this name already exists" => "Ni mogoÄe premakniti %s - datoteka s tem imenom že obstaja", "Could not move %s" => "Ni mogoÄe premakniti %s", "Unable to rename file" => "Ni mogoÄe preimenovati datoteke", -"No file was uploaded. Unknown error" => "Ni poslane datoteke. Neznana napaka.", -"There is no error, the file uploaded with success" => "Datoteka je uspeÅ¡no naložena.", +"No file was uploaded. Unknown error" => "Ni poslane nobene datoteke. Neznana napaka.", +"There is no error, the file uploaded with success" => "Datoteka je uspeÅ¡no poslana.", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Poslana datoteka presega dovoljeno velikost, ki je doloÄena z možnostjo upload_max_filesize v datoteki php.ini:", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Poslana datoteka presega velikost, ki jo doloÄa parameter najveÄje dovoljene velikosti v obrazcu HTML.", -"The uploaded file was only partially uploaded" => "Poslan je le del datoteke.", -"No file was uploaded" => "Ni poslane datoteke", +"The uploaded file was only partially uploaded" => "Datoteka je le delno naložena", +"No file was uploaded" => "Nobena datoteka ni bila naložena", "Missing a temporary folder" => "Manjka zaÄasna mapa", "Failed to write to disk" => "Pisanje na disk je spodletelo", "Not enough storage available" => "Na voljo ni dovolj prostora", "Invalid directory." => "Neveljavna mapa.", "Files" => "Datoteke", -"Share" => "Souporaba", -"Delete permanently" => "IzbriÅ¡i dokonÄno", +"Delete permanently" => "IzbriÅ¡i trajno", "Delete" => "IzbriÅ¡i", "Rename" => "Preimenuj", "Pending" => "V Äakanju ...", @@ -33,7 +32,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "Shramba je povsem napolnjena. Datotek ni veÄ mogoÄe posodabljati in usklajevati!", "Your storage is almost full ({usedSpacePercent}%)" => "Mesto za shranjevanje je skoraj polno ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Postopek priprave datoteke za prejem je lahko dolgotrajen, Äe je datoteka zelo velika.", -"Unable to upload your file as it is a directory or has 0 bytes" => "PoÅ¡iljanja ni mogoÄe izvesti, saj gre za mapo oziroma datoteko velikosti 0 bajtov.", +"Unable to upload your file as it is a directory or has 0 bytes" => "PoÅ¡iljanje ni mogoÄe, saj gre za mapo, ali pa je datoteka velikosti 0 bajtov.", "Not enough space available" => "Na voljo ni dovolj prostora.", "Upload cancelled." => "PoÅ¡iljanje je preklicano.", "File upload is in progress. Leaving the page now will cancel the upload." => "V teku je poÅ¡iljanje datoteke. ÄŒe zapustite to stran zdaj, bo poÅ¡iljanje preklicano.", @@ -56,7 +55,7 @@ "0 is unlimited" => "0 predstavlja neomejeno vrednost", "Maximum input size for ZIP files" => "NajveÄja vhodna velikost za datoteke ZIP", "Save" => "Shrani", -"New" => "Novo", +"New" => "Nova", "Text file" => "Besedilna datoteka", "Folder" => "Mapa", "From link" => "Iz povezave", @@ -65,7 +64,7 @@ "You don’t have write permissions here." => "Za to mesto ni ustreznih dovoljenj za pisanje.", "Nothing in here. Upload something!" => "Tukaj Å¡e ni niÄesar. Najprej je treba kakÅ¡no datoteko poslati v oblak!", "Download" => "Prejmi", -"Unshare" => "PrekliÄi souporabo", +"Unshare" => "Odstrani iz souporabe", "Upload too large" => "PrekoraÄenje omejitve velikosti", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Datoteke, ki jih želite poslati, presegajo najveÄjo dovoljeno velikost na strežniku.", "Files are being scanned, please wait." => "Poteka preuÄevanje datotek, poÄakajte ...", diff --git a/apps/files/l10n/sr.php b/apps/files/l10n/sr.php index 9c7e4e1fc0..50d587ebb2 100644 --- a/apps/files/l10n/sr.php +++ b/apps/files/l10n/sr.php @@ -39,7 +39,7 @@ "URL cannot be empty." => "ÐдреÑа не може бити празна.", "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" => "ÐеиÑправно име фаÑцикле. ФаÑцикла „Shared“ је резервиÑана за ownCloud.", "Error" => "Грешка", -"Name" => "Име", +"Name" => "Ðазив", "Size" => "Величина", "Modified" => "Измењено", "1 folder" => "1 фаÑцикла", diff --git a/apps/files/l10n/sv.php b/apps/files/l10n/sv.php index 54e4275ebb..125788ad13 100644 --- a/apps/files/l10n/sv.php +++ b/apps/files/l10n/sv.php @@ -3,12 +3,12 @@ "Could not move %s" => "Kan inte flytta %s", "Unable to rename file" => "Kan inte byta namn pÃ¥ filen", "No file was uploaded. Unknown error" => "Ingen fil uppladdad. Okänt fel", -"There is no error, the file uploaded with success" => "Inga fel uppstod. Filen laddades upp utan problem.", +"There is no error, the file uploaded with success" => "Inga fel uppstod. Filen laddades upp utan problem", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Den uppladdade filen överskrider upload_max_filesize direktivet php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Den uppladdade filen överskrider MAX_FILE_SIZE direktivet som har angetts i HTML formuläret", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Den uppladdade filen överstiger MAX_FILE_SIZE direktivet som anges i HTML-formulär", "The uploaded file was only partially uploaded" => "Den uppladdade filen var endast delvis uppladdad", -"No file was uploaded" => "Ingen fil laddades upp", -"Missing a temporary folder" => "En temporär mapp saknas", +"No file was uploaded" => "Ingen fil blev uppladdad", +"Missing a temporary folder" => "Saknar en tillfällig mapp", "Failed to write to disk" => "Misslyckades spara till disk", "Not enough storage available" => "Inte tillräckligt med lagringsutrymme tillgängligt", "Invalid directory." => "Felaktig mapp.", @@ -25,14 +25,13 @@ "undo" => "Ã¥ngra", "perform delete operation" => "utför raderingen", "1 file uploading" => "1 filuppladdning", -"files uploading" => "filer laddas upp", "'.' is an invalid file name." => "'.' är ett ogiltigt filnamn.", "File name cannot be empty." => "Filnamn kan inte vara tomt.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ogiltigt namn, '\\', '/', '<', '>', ':', '\"', '|', '?' och '*' är inte tillÃ¥tet.", "Your storage is full, files can not be updated or synced anymore!" => "Ditt lagringsutrymme är fullt, filer kan ej längre laddas upp eller synkas!", "Your storage is almost full ({usedSpacePercent}%)" => "Ditt lagringsutrymme är nästan fullt ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Din nedladdning förbereds. Det kan ta tid om det är stora filer.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Kan inte ladda upp din fil eftersom det är en katalog eller har 0 bytes", +"Unable to upload your file as it is a directory or has 0 bytes" => "Kunde inte ladda upp dina filer eftersom det antingen är en mapp eller har 0 bytes.", "Not enough space available" => "Inte tillräckligt med utrymme tillgängligt", "Upload cancelled." => "Uppladdning avbruten.", "File upload is in progress. Leaving the page now will cancel the upload." => "Filuppladdning pÃ¥gÃ¥r. Lämnar du sidan sÃ¥ avbryts uppladdningen.", diff --git a/apps/files/l10n/ta_LK.php b/apps/files/l10n/ta_LK.php index e5f7bbdf9b..b88379043d 100644 --- a/apps/files/l10n/ta_LK.php +++ b/apps/files/l10n/ta_LK.php @@ -7,8 +7,7 @@ "Missing a temporary folder" => "ஒர௠தறà¯à®•à®¾à®²à®¿à®•à®®à®¾à®© கோபà¯à®ªà¯à®±à¯ˆà®¯à¯ˆ காணவிலà¯à®²à¯ˆ", "Failed to write to disk" => "வடà¯à®Ÿà®¿à®²à¯ எழà¯à®¤ à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ", "Files" => "கோபà¯à®ªà¯à®•à®³à¯", -"Share" => "பகிரà¯à®µà¯", -"Delete" => "நீகà¯à®•à¯à®•", +"Delete" => "அழிகà¯à®•", "Rename" => "பெயரà¯à®®à®¾à®±à¯à®±à®®à¯", "Pending" => "நிலà¯à®µà¯ˆà®¯à®¿à®²à¯à®³à¯à®³", "{new_name} already exists" => "{new_name} à®à®±à¯à®•à®©à®µà¯‡ உளà¯à®³à®¤à¯", @@ -39,7 +38,7 @@ "Enable ZIP-download" => "ZIP பதிவிறகà¯à®•à®²à¯ˆ இயலà¯à®®à¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®•", "0 is unlimited" => "0 ஆனத௠எலà¯à®²à¯ˆà®¯à®±à¯à®±à®¤à¯", "Maximum input size for ZIP files" => "ZIP கோபà¯à®ªà¯à®•à®³à¯à®•à¯à®•à®¾à®© ஆககà¯à®•à¯‚டிய உளà¯à®³à¯€à®Ÿà¯à®Ÿà¯ அளவà¯", -"Save" => "சேமிகà¯à®• ", +"Save" => "சேமிகà¯à®•", "New" => "பà¯à®¤à®¿à®¯", "Text file" => "கோபà¯à®ªà¯ உரை", "Folder" => "கோபà¯à®ªà¯à®±à¯ˆ", diff --git a/apps/files/l10n/th_TH.php b/apps/files/l10n/th_TH.php index a879dba85a..0e7d32bf12 100644 --- a/apps/files/l10n/th_TH.php +++ b/apps/files/l10n/th_TH.php @@ -3,12 +3,12 @@ "Could not move %s" => "ไม่สามารถย้าย %s ได้", "Unable to rename file" => "ไม่สามารถเปลี่ยนชื่อไฟล์ได้", "No file was uploaded. Unknown error" => "ยังไม่มีไฟล์ใดที่ถูà¸à¸­à¸±à¸žà¹‚หลด เà¸à¸´à¸”ข้อผิดพลาดที่ไม่ทราบสาเหตุ", -"There is no error, the file uploaded with success" => "ไม่พบข้อผิดพลาดใดๆ, ไฟล์ถูà¸à¸­à¸±à¸žà¹‚หลดเรียบร้อยà¹à¸¥à¹‰à¸§", +"There is no error, the file uploaded with success" => "ไม่มีข้อผิดพลาดใดๆ ไฟล์ถูà¸à¸­à¸±à¸žà¹‚หลดเรียบร้อยà¹à¸¥à¹‰à¸§", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "ขนาดไฟล์ที่อัพโหลดมีขนาดเà¸à¸´à¸™ upload_max_filesize ที่ระบุไว้ใน php.ini", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "ไฟล์ที่อัพโหลดมีขนาดไฟล์ใหà¸à¹ˆà¹€à¸à¸´à¸™à¸ˆà¸³à¸™à¸§à¸™à¸—ี่à¸à¸³à¸«à¸™à¸”ไว้ในคำสั่ง MAX_FILE_SIZE ที่ถูà¸à¸£à¸°à¸šà¸¸à¹„ว้ในรูปà¹à¸šà¸šà¸‚อง HTML", -"The uploaded file was only partially uploaded" => "ไฟล์ถูà¸à¸­à¸±à¸žà¹‚หลดได้เพียงบางส่วนเท่านั้น", -"No file was uploaded" => "ไม่มีไฟล์ที่ถูà¸à¸­à¸±à¸žà¹‚หลด", -"Missing a temporary folder" => "โฟลเดอร์ชั่วคราวเà¸à¸´à¸”à¸à¸²à¸£à¸ªà¸¹à¸à¸«à¸²à¸¢", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "ไฟล์ที่อัพโหลดมีขนาดเà¸à¸´à¸™à¸„ำสั่ง MAX_FILE_SIZE ที่ระบุเอาไว้ในรูปà¹à¸šà¸šà¸„ำสั่งในภาษา HTML", +"The uploaded file was only partially uploaded" => "ไฟล์ที่อัพโหลดยังไม่ได้ถูà¸à¸­à¸±à¸žà¹‚หลดอย่างสมบูรณ์", +"No file was uploaded" => "ยังไม่มีไฟล์ที่ถูà¸à¸­à¸±à¸žà¹‚หลด", +"Missing a temporary folder" => "à¹à¸Ÿà¹‰à¸¡à¹€à¸­à¸à¸ªà¸²à¸£à¸Šà¸±à¹ˆà¸§à¸„ราวเà¸à¸´à¸”à¸à¸²à¸£à¸ªà¸¹à¸à¸«à¸²à¸¢", "Failed to write to disk" => "เขียนข้อมูลลงà¹à¸œà¹ˆà¸™à¸”ิสà¸à¹Œà¸¥à¹‰à¸¡à¹€à¸«à¸¥à¸§", "Not enough storage available" => "เหลือพื้นที่ไม่เพียงสำหรับใช้งาน", "Invalid directory." => "ไดเร็à¸à¸—อรี่ไม่ถูà¸à¸•à¹‰à¸­à¸‡", @@ -24,14 +24,13 @@ "undo" => "เลิà¸à¸—ำ", "perform delete operation" => "ดำเนินà¸à¸²à¸£à¸•à¸²à¸¡à¸„ำสั่งลบ", "1 file uploading" => "à¸à¸³à¸¥à¸±à¸‡à¸­à¸±à¸žà¹‚หลดไฟล์ 1 ไฟล์", -"files uploading" => "à¸à¸²à¸£à¸­à¸±à¸žà¹‚หลดไฟล์", "'.' is an invalid file name." => "'.' เป็นชื่อไฟล์ที่ไม่ถูà¸à¸•à¹‰à¸­à¸‡", "File name cannot be empty." => "ชื่อไฟล์ไม่สามารถเว้นว่างได้", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "ชื่อที่ใช้ไม่ถูà¸à¸•à¹‰à¸­à¸‡, '\\', '/', '<', '>', ':', '\"', '|', '?' à¹à¸¥à¸° '*' ไม่ได้รับอนุà¸à¸²à¸•à¹ƒà¸«à¹‰à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¹„ด้", "Your storage is full, files can not be updated or synced anymore!" => "พื้นที่จัดเà¸à¹‡à¸šà¸‚้อมูลของคุณเต็มà¹à¸¥à¹‰à¸§ ไม่สามารถอัพเดทหรือผสานไฟล์ต่างๆได้อีà¸à¸•à¹ˆà¸­à¹„ป", "Your storage is almost full ({usedSpacePercent}%)" => "พื้นที่จัดเà¸à¹‡à¸šà¸‚้อมูลของคุณใà¸à¸¥à¹‰à¹€à¸•à¹‡à¸¡à¹à¸¥à¹‰à¸§ ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "à¸à¸³à¸¥à¸±à¸‡à¹€à¸•à¸£à¸µà¸¢à¸¡à¸”าวน์โหลดข้อมูล หาà¸à¹„ฟล์มีขนาดใหà¸à¹ˆ อาจใช้เวลาสัà¸à¸„รู่", -"Unable to upload your file as it is a directory or has 0 bytes" => "ไม่สามารถอัพโหลดไฟล์ของคุณได้ เนื่องจาà¸à¹„ฟล์ดังà¸à¸¥à¹ˆà¸²à¸§à¹€à¸›à¹‡à¸™à¹„ดเร็à¸à¸—อรี่ หรือ มีขนาดไฟล์ 0 ไบต์", +"Unable to upload your file as it is a directory or has 0 bytes" => "ไม่สามารถอัพโหลดไฟล์ของคุณได้ เนื่องจาà¸à¹„ฟล์ดังà¸à¸¥à¹ˆà¸²à¸§à¹€à¸›à¹‡à¸™à¹„ดเร็à¸à¸—อรี่หรือมีขนาด 0 ไบต์", "Not enough space available" => "มีพื้นที่เหลือไม่เพียงพอ", "Upload cancelled." => "à¸à¸²à¸£à¸­à¸±à¸žà¹‚หลดถูà¸à¸¢à¸à¹€à¸¥à¸´à¸", "File upload is in progress. Leaving the page now will cancel the upload." => "à¸à¸²à¸£à¸­à¸±à¸žà¹‚หลดไฟล์à¸à¸³à¸¥à¸±à¸‡à¸­à¸¢à¸¹à¹ˆà¹ƒà¸™à¸£à¸°à¸«à¸§à¹ˆà¸²à¸‡à¸”ำเนินà¸à¸²à¸£ à¸à¸²à¸£à¸­à¸­à¸à¸ˆà¸²à¸à¸«à¸™à¹‰à¸²à¹€à¸§à¹‡à¸šà¸™à¸µà¹‰à¸ˆà¸°à¸—ำให้à¸à¸²à¸£à¸­à¸±à¸žà¹‚หลดถูà¸à¸¢à¸à¹€à¸¥à¸´à¸", @@ -40,7 +39,7 @@ "Error" => "ข้อผิดพลาด", "Name" => "ชื่อ", "Size" => "ขนาด", -"Modified" => "à¹à¸à¹‰à¹„ขà¹à¸¥à¹‰à¸§", +"Modified" => "ปรับปรุงล่าสุด", "1 folder" => "1 โฟลเดอร์", "{count} folders" => "{count} โฟลเดอร์", "1 file" => "1 ไฟล์", @@ -61,7 +60,7 @@ "Cancel upload" => "ยà¸à¹€à¸¥à¸´à¸à¸à¸²à¸£à¸­à¸±à¸žà¹‚หลด", "Nothing in here. Upload something!" => "ยังไม่มีไฟล์ใดๆอยู่ที่นี่ à¸à¸£à¸¸à¸“าอัพโหลดไฟล์!", "Download" => "ดาวน์โหลด", -"Unshare" => "ยà¸à¹€à¸¥à¸´à¸à¸à¸²à¸£à¹à¸Šà¸£à¹Œ", +"Unshare" => "ยà¸à¹€à¸¥à¸´à¸à¸à¸²à¸£à¹à¸Šà¸£à¹Œà¸‚้อมูล", "Upload too large" => "ไฟล์ที่อัพโหลดมีขนาดใหà¸à¹ˆà¹€à¸à¸´à¸™à¹„ป", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "ไฟล์ที่คุณพยายามที่จะอัพโหลดมีขนาดเà¸à¸´à¸™à¸à¸§à¹ˆà¸²à¸‚นาดสูงสุดที่à¸à¸³à¸«à¸™à¸”ไว้ให้อัพโหลดได้สำหรับเซิร์ฟเวอร์นี้", "Files are being scanned, please wait." => "ไฟล์à¸à¸³à¸¥à¸±à¸‡à¸­à¸¢à¸¹à¹ˆà¸£à¸°à¸«à¸§à¹ˆà¸²à¸‡à¸à¸²à¸£à¸ªà¹à¸à¸™, à¸à¸£à¸¸à¸“ารอสัà¸à¸„รู่.", diff --git a/apps/files/l10n/tr.php b/apps/files/l10n/tr.php index 17275e4753..84da59cee0 100644 --- a/apps/files/l10n/tr.php +++ b/apps/files/l10n/tr.php @@ -3,12 +3,12 @@ "Could not move %s" => "%s taşınamadı", "Unable to rename file" => "Dosya adı deÄŸiÅŸtirilemedi", "No file was uploaded. Unknown error" => "Dosya yüklenmedi. Bilinmeyen hata", -"There is no error, the file uploaded with success" => "Dosya baÅŸarıyla yüklendi, hata oluÅŸmadı", +"There is no error, the file uploaded with success" => "Bir hata yok, dosya baÅŸarıyla yüklendi", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "php.ini dosyasında upload_max_filesize ile belirtilen dosya yükleme sınırı aşıldı.", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Yüklenecek dosyanın boyutu HTML formunda belirtilen MAX_FILE_SIZE limitini aşıyor", -"The uploaded file was only partially uploaded" => "Dosya kısmen karşıya yüklenebildi", -"No file was uploaded" => "Hiç dosya gönderilmedi", -"Missing a temporary folder" => "Geçici dizin eksik", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Yüklenen dosya HTML formundaki MAX_FILE_SIZE sınırını aşıyor", +"The uploaded file was only partially uploaded" => "Yüklenen dosyanın sadece bir kısmı yüklendi", +"No file was uploaded" => "Hiç dosya yüklenmedi", +"Missing a temporary folder" => "Geçici bir klasör eksik", "Failed to write to disk" => "Diske yazılamadı", "Not enough storage available" => "Yeterli disk alanı yok", "Invalid directory." => "Geçersiz dizin.", @@ -39,7 +39,7 @@ "URL cannot be empty." => "URL boÅŸ olamaz.", "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" => "Geçersiz dizin adı. Shared isminin kullanımı Owncloud tarafından rezerver edilmiÅŸtir.", "Error" => "Hata", -"Name" => "Ä°sim", +"Name" => "Ad", "Size" => "Boyut", "Modified" => "DeÄŸiÅŸtirilme", "1 folder" => "1 dizin", @@ -65,7 +65,7 @@ "Nothing in here. Upload something!" => "Burada hiçbir ÅŸey yok. BirÅŸeyler yükleyin!", "Download" => "Ä°ndir", "Unshare" => "Paylaşılmayan", -"Upload too large" => "Yükleme çok büyük", +"Upload too large" => "Yüklemeniz çok büyük", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Yüklemeye çalıştığınız dosyalar bu sunucudaki maksimum yükleme boyutunu aşıyor.", "Files are being scanned, please wait." => "Dosyalar taranıyor, lütfen bekleyin.", "Current scanning" => "Güncel tarama", diff --git a/apps/files/l10n/uk.php b/apps/files/l10n/uk.php index db3120645f..65b4ec1433 100644 --- a/apps/files/l10n/uk.php +++ b/apps/files/l10n/uk.php @@ -46,7 +46,7 @@ "{count} folders" => "{count} папок", "1 file" => "1 файл", "{count} files" => "{count} файлів", -"Upload" => "Вивантажити", +"Upload" => "Відвантажити", "File handling" => "Робота з файлами", "Maximum upload size" => "МакÑимальний розмір відвантажень", "max. possible: " => "макÑ.можливе:", @@ -64,7 +64,7 @@ "You don’t have write permissions here." => "У Ð²Ð°Ñ Ñ‚ÑƒÑ‚ немає прав на запиÑ.", "Nothing in here. Upload something!" => "Тут нічого немає. Відвантажте що-небудь!", "Download" => "Завантажити", -"Unshare" => "Закрити доÑтуп", +"Unshare" => "Заборонити доÑтуп", "Upload too large" => "Файл занадто великий", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Файли,що ви намагаєтеÑÑŒ відвантажити перевищують макÑимальний дозволений розмір файлів на цьому Ñервері.", "Files are being scanned, please wait." => "Файли ÑкануютьÑÑ, зачекайте, будь-лаÑка.", diff --git a/apps/files/l10n/ur_PK.php b/apps/files/l10n/ur_PK.php index aa87eeda38..e13a623fec 100644 --- a/apps/files/l10n/ur_PK.php +++ b/apps/files/l10n/ur_PK.php @@ -1,4 +1,3 @@ "ایرر", -"Unshare" => "شئیرنگ ختم کریں" +"Error" => "ایرر" ); diff --git a/apps/files/l10n/vi.php b/apps/files/l10n/vi.php index 7a67f66b30..73cf154492 100644 --- a/apps/files/l10n/vi.php +++ b/apps/files/l10n/vi.php @@ -5,9 +5,9 @@ "No file was uploaded. Unknown error" => "Không có tập tin nào được tải lên. Lá»—i không xác định", "There is no error, the file uploaded with success" => "Không có lá»—i, các tập tin đã được tải lên thành công", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "The uploaded file exceeds the upload_max_filesize directive in php.ini: ", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Tập tin được tải lên vượt quá MAX_FILE_SIZE được quy định trong mẫu HTML", -"The uploaded file was only partially uploaded" => "Các tập tin được tải lên chỉ tải lên được má»™t phần", -"No file was uploaded" => "ChÆ°a có file nào được tải lên", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Kích thÆ°á»›c những tập tin tải lên vượt quá MAX_FILE_SIZE đã được quy định", +"The uploaded file was only partially uploaded" => "Tập tin tải lên má»›i chỉ tải lên được má»™t phần", +"No file was uploaded" => "Không có tập tin nào được tải lên", "Missing a temporary folder" => "Không tìm thấy thÆ° mục tạm", "Failed to write to disk" => "Không thể ghi ", "Not enough storage available" => "Không đủ không gian lÆ°u trữ", @@ -16,7 +16,7 @@ "Delete permanently" => "Xóa vÄ©nh vá»…n", "Delete" => "Xóa", "Rename" => "Sá»­a tên", -"Pending" => "Äang chá»", +"Pending" => "Chá»", "{new_name} already exists" => "{new_name} đã tồn tại", "replace" => "thay thế", "suggest name" => "tên gợi ý", @@ -25,14 +25,13 @@ "undo" => "lùi lại", "perform delete operation" => "thá»±c hiện việc xóa", "1 file uploading" => "1 tệp tin Ä‘ang được tải lên", -"files uploading" => "tệp tin Ä‘ang được tải lên", "'.' is an invalid file name." => "'.' là má»™t tên file không hợp lệ", "File name cannot be empty." => "Tên file không được rá»—ng", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Tên không hợp lệ, '\\', '/', '<', '>', ':', '\"', '|', '?' và '*' thì không được phép dùng.", "Your storage is full, files can not be updated or synced anymore!" => "Your storage is full, files can not be updated or synced anymore!", "Your storage is almost full ({usedSpacePercent}%)" => "Your storage is almost full ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Your download is being prepared. This might take some time if the files are big.", -"Unable to upload your file as it is a directory or has 0 bytes" => "Không thể tải lên tập tin của bạn ,nó nhÆ° là má»™t thÆ° mục hoặc có 0 byte", +"Unable to upload your file as it is a directory or has 0 bytes" => "Không thể tải lên tập tin này do nó là má»™t thÆ° mục hoặc kích thÆ°á»›c tập tin bằng 0 byte", "Upload cancelled." => "Hủy tải lên", "File upload is in progress. Leaving the page now will cancel the upload." => "Tập tin tải lên Ä‘ang được xá»­ lý. Nếu bạn rá»i khá»i trang bây giá» sẽ hủy quá trình này.", "URL cannot be empty." => "URL không được để trống.", @@ -61,8 +60,8 @@ "Deleted files" => "File đã bị xóa", "Cancel upload" => "Hủy upload", "Nothing in here. Upload something!" => "Không có gì ở đây .Hãy tải lên má»™t cái gì đó !", -"Download" => "Tải vá»", -"Unshare" => "Bá» chia sẻ", +"Download" => "Tải xuống", +"Unshare" => "Không chia sẽ", "Upload too large" => "Tập tin tải lên quá lá»›n", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Các tập tin bạn Ä‘ang tải lên vượt quá kích thÆ°á»›c tối Ä‘a cho phép trên máy chủ .", "Files are being scanned, please wait." => "Tập tin Ä‘ang được quét ,vui lòng chá».", diff --git a/apps/files/l10n/zh_CN.GB2312.php b/apps/files/l10n/zh_CN.GB2312.php index f0de736e7a..33e21e544c 100644 --- a/apps/files/l10n/zh_CN.GB2312.php +++ b/apps/files/l10n/zh_CN.GB2312.php @@ -1,15 +1,15 @@ "没有上传文件。未知错误", -"There is no error, the file uploaded with success" => "文件上传æˆåŠŸ", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "上传的文件超过了 HTML 表格中指定的 MAX_FILE_SIZE 选项", -"The uploaded file was only partially uploaded" => "文件部分上传", -"No file was uploaded" => "没有上传文件", -"Missing a temporary folder" => "缺失临时文件夹", +"There is no error, the file uploaded with success" => "没有任何错误,文件上传æˆåŠŸäº†", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "上传的文件超过了HTML表å•æŒ‡å®šçš„MAX_FILE_SIZE", +"The uploaded file was only partially uploaded" => "文件åªæœ‰éƒ¨åˆ†è¢«ä¸Šä¼ ", +"No file was uploaded" => "没有上传完æˆçš„文件", +"Missing a temporary folder" => "丢失了一个临时文件夹", "Failed to write to disk" => "写ç£ç›˜å¤±è´¥", "Files" => "文件", "Delete" => "删除", "Rename" => "é‡å‘½å", -"Pending" => "等待中", +"Pending" => "Pending", "{new_name} already exists" => "{new_name} 已存在", "replace" => "替æ¢", "suggest name" => "推èå称", @@ -17,13 +17,12 @@ "replaced {new_name} with {old_name}" => "已用 {old_name} æ›¿æ¢ {new_name}", "undo" => "撤销", "1 file uploading" => "1 个文件正在上传", -"files uploading" => "个文件正在上传", -"Unable to upload your file as it is a directory or has 0 bytes" => "ä¸èƒ½ä¸Šä¼ æ‚¨çš„文件,由于它是文件夹或者为空文件", +"Unable to upload your file as it is a directory or has 0 bytes" => "ä¸èƒ½ä¸Šä¼ ä½ æŒ‡å®šçš„文件,å¯èƒ½å› ä¸ºå®ƒæ˜¯ä¸ªæ–‡ä»¶å¤¹æˆ–者大å°ä¸º0", "Upload cancelled." => "上传å–消了", "File upload is in progress. Leaving the page now will cancel the upload." => "文件正在上传。关闭页é¢ä¼šå–消上传。", "URL cannot be empty." => "网å€ä¸èƒ½ä¸ºç©ºã€‚", "Error" => "出错", -"Name" => "å称", +"Name" => "åå­—", "Size" => "大å°", "Modified" => "修改日期", "1 folder" => "1 个文件夹", @@ -46,8 +45,8 @@ "Cancel upload" => "å–消上传", "Nothing in here. Upload something!" => "这里没有东西.上传点什么!", "Download" => "下载", -"Unshare" => "å–消分享", -"Upload too large" => "上传过大", +"Unshare" => "å–消共享", +"Upload too large" => "上传的文件太大了", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "你正在试图上传的文件超过了此æœåŠ¡å™¨æ”¯æŒçš„最大的文件大å°.", "Files are being scanned, please wait." => "正在扫æ文件,请ç¨å€™.", "Current scanning" => "正在扫æ" diff --git a/apps/files/l10n/zh_CN.php b/apps/files/l10n/zh_CN.php index 3ba7a78007..8740298c62 100644 --- a/apps/files/l10n/zh_CN.php +++ b/apps/files/l10n/zh_CN.php @@ -3,11 +3,11 @@ "Could not move %s" => "无法移动 %s", "Unable to rename file" => "无法é‡å‘½å文件", "No file was uploaded. Unknown error" => "没有文件被上传。未知错误", -"There is no error, the file uploaded with success" => "文件上传æˆåŠŸï¼Œæ²¡æœ‰é”™è¯¯å‘生", +"There is no error, the file uploaded with success" => "没有å‘生错误,文件上传æˆåŠŸã€‚", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "上传文件大å°å·²è¶…过php.ini中upload_max_filesize所规定的值", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "上传的文件长度超出了 HTML 表å•ä¸­ MAX_FILE_SIZE çš„é™åˆ¶", -"The uploaded file was only partially uploaded" => "已上传文件åªä¸Šä¼ äº†éƒ¨åˆ†ï¼ˆä¸å®Œæ•´ï¼‰", -"No file was uploaded" => "没有文件被上传", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "上传的文件超过了在HTML 表å•ä¸­æŒ‡å®šçš„MAX_FILE_SIZE", +"The uploaded file was only partially uploaded" => "åªä¸Šä¼ äº†æ–‡ä»¶çš„一部分", +"No file was uploaded" => "文件没有上传", "Missing a temporary folder" => "缺少临时目录", "Failed to write to disk" => "写入ç£ç›˜å¤±è´¥", "Not enough storage available" => "没有足够的存储空间", @@ -16,7 +16,7 @@ "Delete permanently" => "永久删除", "Delete" => "删除", "Rename" => "é‡å‘½å", -"Pending" => "等待", +"Pending" => "æ“作等待中", "{new_name} already exists" => "{new_name} 已存在", "replace" => "替æ¢", "suggest name" => "建议å称", @@ -31,7 +31,7 @@ "Your storage is full, files can not be updated or synced anymore!" => "您的存储空间已满,文件将无法更新或åŒæ­¥ï¼", "Your storage is almost full ({usedSpacePercent}%)" => "您的存储空间å³å°†ç”¨å®Œ ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "下载正在准备中。如果文件较大å¯èƒ½ä¼šèŠ±è´¹ä¸€äº›æ—¶é—´ã€‚", -"Unable to upload your file as it is a directory or has 0 bytes" => "无法上传您的文件,文件夹或者空文件", +"Unable to upload your file as it is a directory or has 0 bytes" => "无法上传文件,因为它是一个目录或者大å°ä¸º 0 字节", "Not enough space available" => "没有足够å¯ç”¨ç©ºé—´", "Upload cancelled." => "上传已å–消", "File upload is in progress. Leaving the page now will cancel the upload." => "文件正在上传中。现在离开此页会导致上传动作被å–消。", @@ -63,7 +63,7 @@ "You don’t have write permissions here." => "您没有写æƒé™", "Nothing in here. Upload something!" => "这里还什么都没有。上传些东西å§ï¼", "Download" => "下载", -"Unshare" => "å–消共享", +"Unshare" => "å–消分享", "Upload too large" => "上传文件过大", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "您正å°è¯•ä¸Šä¼ çš„文件超过了此æœåŠ¡å™¨å¯ä»¥ä¸Šä¼ çš„最大容é‡é™åˆ¶", "Files are being scanned, please wait." => "文件正在被扫æ,请ç¨å€™ã€‚", diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php index b576253f4f..69fcb94e68 100644 --- a/apps/files/templates/index.php +++ b/apps/files/templates/index.php @@ -34,7 +34,7 @@ value="(max )"> - + @@ -46,6 +46,7 @@
diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index e27054f0ec..25c2d091c4 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -45,12 +45,7 @@ class Hooks { $view = new \OC_FilesystemView( '/' ); - $userHome = \OC_User::getHome($params['uid']); - $dataDir = str_replace('/'.$params['uid'], '', $userHome); - - \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $dataDir .'/public-keys'), '/public-keys/' ); - - $util = new Util( $view, $params['uid'] ); + $util = new Util( $view, $params['uid'] ); // Check files_encryption infrastructure is ready for action if ( ! $util->ready() ) { diff --git a/apps/files_encryption/l10n/ca.php b/apps/files_encryption/l10n/ca.php index ce9fe38996..0c661353a7 100644 --- a/apps/files_encryption/l10n/ca.php +++ b/apps/files_encryption/l10n/ca.php @@ -3,5 +3,5 @@ "File encryption is enabled." => "L'encriptació de fitxers està activada.", "The following file types will not be encrypted:" => "Els tipus de fitxers següents no s'encriptaran:", "Exclude the following file types from encryption:" => "Exclou els tipus de fitxers següents de l'encriptatge:", -"None" => "cap" +"None" => "Cap" ); diff --git a/apps/files_encryption/l10n/de.php b/apps/files_encryption/l10n/de.php index bcf0ca5ad6..cdcd8a40b2 100644 --- a/apps/files_encryption/l10n/de.php +++ b/apps/files_encryption/l10n/de.php @@ -3,5 +3,5 @@ "File encryption is enabled." => "Dateiverschlüsselung ist aktiviert", "The following file types will not be encrypted:" => "Die folgenden Dateitypen werden nicht verschlüsselt:", "Exclude the following file types from encryption:" => "Schließe die folgenden Dateitypen von der Verschlüsselung aus:", -"None" => "Nichts" +"None" => "Keine" ); diff --git a/apps/files_encryption/l10n/de_DE.php b/apps/files_encryption/l10n/de_DE.php index 71fd7d9671..4f08b98eb2 100644 --- a/apps/files_encryption/l10n/de_DE.php +++ b/apps/files_encryption/l10n/de_DE.php @@ -3,5 +3,5 @@ "File encryption is enabled." => "Datei-Verschlüsselung ist aktiviert", "The following file types will not be encrypted:" => "Die folgenden Dateitypen werden nicht verschlüsselt:", "Exclude the following file types from encryption:" => "Die folgenden Dateitypen von der Verschlüsselung ausnehmen:", -"None" => "Nichts" +"None" => "Keine" ); diff --git a/apps/files_encryption/l10n/el.php b/apps/files_encryption/l10n/el.php index 82a4c92ec2..0031a73194 100644 --- a/apps/files_encryption/l10n/el.php +++ b/apps/files_encryption/l10n/el.php @@ -3,5 +3,5 @@ "File encryption is enabled." => "Η κÏυπτογÏάφηση αÏχείων είναι ενεÏγή.", "The following file types will not be encrypted:" => "Οι παÏακάτω Ï„Ïποι αÏχείων δεν θα κÏυπτογÏαφηθοÏν:", "Exclude the following file types from encryption:" => "ΕξαίÏεση των παÏακάτω Ï„Ïπων αÏχείων από την κÏυπτογÏάφηση:", -"None" => "Τίποτα" +"None" => "Καμία" ); diff --git a/apps/files_encryption/l10n/eu.php b/apps/files_encryption/l10n/eu.php index 7e3b7611ff..5a22b65728 100644 --- a/apps/files_encryption/l10n/eu.php +++ b/apps/files_encryption/l10n/eu.php @@ -3,5 +3,5 @@ "File encryption is enabled." => "Fitxategien enkriptazioa gaituta dago.", "The following file types will not be encrypted:" => "Hurrengo fitxategi motak ez dira enkriptatuko:", "Exclude the following file types from encryption:" => "Baztertu hurrengo fitxategi motak enkriptatzetik:", -"None" => "Ezer" +"None" => "Bat ere ez" ); diff --git a/apps/files_encryption/l10n/it.php b/apps/files_encryption/l10n/it.php index c717134526..9ab9bc492a 100644 --- a/apps/files_encryption/l10n/it.php +++ b/apps/files_encryption/l10n/it.php @@ -3,5 +3,5 @@ "File encryption is enabled." => "La cifratura dei file è abilitata.", "The following file types will not be encrypted:" => "I seguenti tipi di file non saranno cifrati:", "Exclude the following file types from encryption:" => "Escludi i seguenti tipi di file dalla cifratura:", -"None" => "Nessuno" +"None" => "Nessuna" ); diff --git a/apps/files_encryption/l10n/pl.php b/apps/files_encryption/l10n/pl.php index 836f545359..2fa86f454f 100644 --- a/apps/files_encryption/l10n/pl.php +++ b/apps/files_encryption/l10n/pl.php @@ -3,5 +3,5 @@ "File encryption is enabled." => "Szyfrowanie plików jest wÅ‚Ä…czone", "The following file types will not be encrypted:" => "Poniższe typy plików nie bÄ™dÄ… szyfrowane:", "Exclude the following file types from encryption:" => "WyÅ‚Ä…cz poniższe typy plików z szyfrowania:", -"None" => "Nic" +"None" => "Brak" ); diff --git a/apps/files_encryption/l10n/pt_BR.php b/apps/files_encryption/l10n/pt_BR.php index b41c6ed315..28807db72c 100644 --- a/apps/files_encryption/l10n/pt_BR.php +++ b/apps/files_encryption/l10n/pt_BR.php @@ -3,5 +3,5 @@ "File encryption is enabled." => "A criptografia de arquivos está ativada.", "The following file types will not be encrypted:" => "Os seguintes tipos de arquivo não serão criptografados:", "Exclude the following file types from encryption:" => "Excluir os seguintes tipos de arquivo da criptografia:", -"None" => "Nada" +"None" => "Nenhuma" ); diff --git a/apps/files_encryption/l10n/ru.php b/apps/files_encryption/l10n/ru.php index f07dec621d..22c1e3da37 100644 --- a/apps/files_encryption/l10n/ru.php +++ b/apps/files_encryption/l10n/ru.php @@ -3,5 +3,5 @@ "File encryption is enabled." => "Шифрование файла включено.", "The following file types will not be encrypted:" => "Следующие типы файлов не будут зашифрованы:", "Exclude the following file types from encryption:" => "ИÑключить Ñледующие типы файлов из шифрованных:", -"None" => "Ðет новоÑтей" +"None" => "Ðичего" ); diff --git a/apps/files_encryption/l10n/sk_SK.php b/apps/files_encryption/l10n/sk_SK.php index aaea9da21b..bebb623471 100644 --- a/apps/files_encryption/l10n/sk_SK.php +++ b/apps/files_encryption/l10n/sk_SK.php @@ -3,5 +3,5 @@ "File encryption is enabled." => "Å ifrovanie súborov nastavené.", "The following file types will not be encrypted:" => "Uvedené typy súborov nebudú Å¡ifrované:", "Exclude the following file types from encryption:" => "NeÅ¡ifrovaÅ¥ uvedené typy súborov", -"None" => "Žiadny" +"None" => "Žiadne" ); diff --git a/apps/files_encryption/l10n/th_TH.php b/apps/files_encryption/l10n/th_TH.php index 30c0324a98..e46d249118 100644 --- a/apps/files_encryption/l10n/th_TH.php +++ b/apps/files_encryption/l10n/th_TH.php @@ -1,4 +1,4 @@ "à¸à¸²à¸£à¹€à¸‚้ารหัส", -"None" => "ไม่มี" +"None" => "ไม่ต้อง" ); diff --git a/apps/files_encryption/l10n/vi.php b/apps/files_encryption/l10n/vi.php index 40d4b1d0fe..0a88d1b2db 100644 --- a/apps/files_encryption/l10n/vi.php +++ b/apps/files_encryption/l10n/vi.php @@ -3,5 +3,5 @@ "File encryption is enabled." => "Mã hóa file đã mở", "The following file types will not be encrypted:" => "Loại file sau sẽ không được mã hóa", "Exclude the following file types from encryption:" => "Việc mã hóa không bao gồm loại file sau", -"None" => "Không gì cả" +"None" => "Không có gì hết" ); diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index 4a85048ba4..7f9572f426 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -21,6 +21,7 @@ use OCA\Encryption; // This has to go here because otherwise session errors arise, and the private // encryption key needs to be saved in the session +\OC_User::login( 'admin', 'admin' ); /** * @note It would be better to use Mockery here for mocking out the session @@ -36,7 +37,7 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { // reset backend \OC_User::useBackend('database'); - // set content for encrypting / decrypting in tests + // set content for encrypting / decrypting in tests $this->dataLong = file_get_contents( realpath( dirname(__FILE__).'/../lib/crypt.php' ) ); $this->dataShort = 'hats'; $this->dataUrl = realpath( dirname(__FILE__).'/../lib/crypt.php' ); @@ -59,17 +60,13 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { \OC\Files\Filesystem::init($this->userId, '/'); \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $this->dataDir), '/' ); - - $params['uid'] = $this->userId; - $params['password'] = $this->pass; - OCA\Encryption\Hooks::login($params); } function tearDown() { } - function testGenerateKey() { + function testGenerateKey() { # TODO: use more accurate (larger) string length for test confirmation diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php index 33ca29997b..81034be54b 100644 --- a/apps/files_encryption/tests/keymanager.php +++ b/apps/files_encryption/tests/keymanager.php @@ -19,7 +19,7 @@ use OCA\Encryption; // This has to go here because otherwise session errors arise, and the private // encryption key needs to be saved in the session -//\OC_User::login( 'admin', 'admin' ); +\OC_User::login( 'admin', 'admin' ); class Test_Keymanager extends \PHPUnit_Framework_TestCase { @@ -52,10 +52,7 @@ class Test_Keymanager extends \PHPUnit_Framework_TestCase { \OC\Files\Filesystem::init( $this->userId, '/' ); \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $this->dataDir), '/' ); - - $params['uid'] = $this->userId; - $params['password'] = $this->pass; - OCA\Encryption\Hooks::login($params); + } function tearDown(){ diff --git a/apps/files_encryption/tests/stream.php b/apps/files_encryption/tests/stream.php index 633cc9e4fc..ba82ac80ea 100644 --- a/apps/files_encryption/tests/stream.php +++ b/apps/files_encryption/tests/stream.php @@ -1,4 +1,4 @@ - // * This file is licensed under the Affero General Public License version 3 or diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index e3ec0860fa..0659b468a3 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -24,6 +24,8 @@ $loader->register(); use \Mockery as m; use OCA\Encryption; +\OC_User::login( 'admin', 'admin' ); + class Test_Enc_Util extends \PHPUnit_Framework_TestCase { function setUp() { @@ -60,10 +62,6 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase { \OC\Files\Filesystem::init( $this->userId, '/' ); \OC\Files\Filesystem::mount( 'OC_Filestorage_Local', array('datadir' => $this->dataDir), '/' ); - $params['uid'] = $this->userId; - $params['password'] = $this->pass; - OCA\Encryption\Hooks::login($params); - $mockView = m::mock('OC_FilesystemView'); $this->util = new Encryption\Util( $mockView, $this->userId ); @@ -77,9 +75,6 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase { /** * @brief test that paths set during User construction are correct - * - * - * */ function testKeyPaths() { diff --git a/apps/files_external/l10n/ar.php b/apps/files_external/l10n/ar.php index a53bfe48bc..06837d5085 100644 --- a/apps/files_external/l10n/ar.php +++ b/apps/files_external/l10n/ar.php @@ -1,5 +1,5 @@ "مجموعات", "Users" => "المستخدمين", -"Delete" => "إلغاء" +"Delete" => "حذÙ" ); diff --git a/apps/files_external/l10n/bn_BD.php b/apps/files_external/l10n/bn_BD.php index 0f032df9f0..07ccd50074 100644 --- a/apps/files_external/l10n/bn_BD.php +++ b/apps/files_external/l10n/bn_BD.php @@ -12,7 +12,7 @@ "All Users" => "সমসà§à¦¤ বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€", "Groups" => "গোষà§à¦ à§€à¦¸à¦®à§‚হ", "Users" => "বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€", -"Delete" => "মà§à¦›à§‡", +"Delete" => "মà§à¦›à§‡ ফেল", "Enable User External Storage" => "বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€à¦° বাহà§à¦¯à¦¿à¦• সংরকà§à¦·à¦£à¦¾à¦—ার সকà§à¦°à¦¿à§Ÿ কর", "Allow users to mount their own external storage" => "বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€à¦¦à§‡à¦°à¦•à§‡ তাদের নিজসà§à¦¬ বাহà§à¦¯à¦¿à¦• সংরকà§à¦·à¦¨à¦¾à¦—ার সাউনà§à¦Ÿ করতে অনà§à¦®à§‹à¦¦à¦¨ দাও", "SSL root certificates" => "SSL রà§à¦Ÿ সনদপতà§à¦°", diff --git a/apps/files_external/l10n/ca.php b/apps/files_external/l10n/ca.php index e3b245babf..aa9304d330 100644 --- a/apps/files_external/l10n/ca.php +++ b/apps/files_external/l10n/ca.php @@ -17,7 +17,7 @@ "All Users" => "Tots els usuaris", "Groups" => "Grups", "Users" => "Usuaris", -"Delete" => "Esborra", +"Delete" => "Elimina", "Enable User External Storage" => "Habilita l'emmagatzemament extern d'usuari", "Allow users to mount their own external storage" => "Permet als usuaris muntar el seu emmagatzemament extern propi", "SSL root certificates" => "Certificats SSL root", diff --git a/apps/files_external/l10n/de.php b/apps/files_external/l10n/de.php index 8dfa0eafbb..2418377221 100644 --- a/apps/files_external/l10n/de.php +++ b/apps/files_external/l10n/de.php @@ -6,7 +6,6 @@ "Error configuring Google Drive storage" => "Fehler beim Einrichten von Google Drive", "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Warnung: \"smbclient\" ist nicht installiert. Das Einhängen von CIFS/SMB-Freigaben ist nicht möglich. Bitte Deinen System-Administrator, dies zu installieren.", "Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Warnung:: Die FTP Unterstützung von PHP ist nicht aktiviert oder installiert. Bitte wende Dich an Deinen Systemadministrator.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Warnung: Die Curl-Unterstützung in PHP ist nicht aktiviert oder installiert. Das Einbinden von ownCloud / WebDav der GoogleDrive-Freigaben ist nicht möglich. Bitte Deinen Systemadminstrator um die Installation. ", "External Storage" => "Externer Speicher", "Folder name" => "Ordnername", "External storage" => "Externer Speicher", diff --git a/apps/files_external/l10n/de_DE.php b/apps/files_external/l10n/de_DE.php index 8a8ae37ffd..d55c0c6909 100644 --- a/apps/files_external/l10n/de_DE.php +++ b/apps/files_external/l10n/de_DE.php @@ -6,7 +6,6 @@ "Error configuring Google Drive storage" => "Fehler beim Einrichten von Google Drive", "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Warnung: \"smbclient\" ist nicht installiert. Das Einhängen von CIFS/SMB-Freigaben ist nicht möglich. Bitten Sie Ihren Systemadministrator, dies zu installieren.", "Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Warnung:: Die FTP Unterstützung von PHP ist nicht aktiviert oder installiert. Bitte wenden Sie sich an Ihren Systemadministrator.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Achtung: Die Curl-Unterstützung von PHP ist nicht aktiviert oder installiert. Das Laden von ownCloud / WebDAV oder GoogleDrive Freigaben ist nicht möglich. Bitte Sie Ihren Systemadministrator, das Modul zu installieren.", "External Storage" => "Externer Speicher", "Folder name" => "Ordnername", "External storage" => "Externer Speicher", diff --git a/apps/files_external/l10n/el.php b/apps/files_external/l10n/el.php index 62703b08fb..6c519a1b41 100644 --- a/apps/files_external/l10n/el.php +++ b/apps/files_external/l10n/el.php @@ -6,7 +6,6 @@ "Error configuring Google Drive storage" => "Σφάλμα Ïυθμίζωντας αποθήκευση Google Drive ", "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "ΠÏοσοχή: Ο \"smbclient\" δεν εγκαταστάθηκε. Δεν είναι δυνατή η Ï€ÏοσάÏτηση CIFS/SMB. ΠαÏακαλώ ενημεÏώστε τον διαχειÏιστή συστήματος να το εγκαταστήσει.", "Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "ΠÏοσοχή: Η υποστήÏιξη FTP στην PHP δεν ενεÏγοποιήθηκε ή εγκαταστάθηκε. Δεν είναι δυνατή η Ï€ÏοσάÏτηση FTP. ΠαÏακαλώ ενημεÏώστε τον διαχειÏιστή συστήματος να το εγκαταστήσει.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "<ΠÏοειδοποίηση Η υποστήÏιξη του συστήματος Curl στο PHP δεν είναι ενεÏγοποιημένη ή εγκαταστημένη. Η αναπαÏαγωγή του ownCloud/WebDAV ή GoogleDrive δεν είναι δυνατή. ΠαÏακαλώ Ïωτήστε τον διαχειÏιστλη του συστήματος για την εγκατάσταση. ", "External Storage" => "ΕξωτεÏικό Αποθηκευτικό Μέσο", "Folder name" => "Όνομα φακέλου", "External storage" => "ΕξωτεÏική αποθήκευση", diff --git a/apps/files_external/l10n/es.php b/apps/files_external/l10n/es.php index 5c332690bf..da22f41032 100644 --- a/apps/files_external/l10n/es.php +++ b/apps/files_external/l10n/es.php @@ -17,7 +17,7 @@ "All Users" => "Todos los usuarios", "Groups" => "Grupos", "Users" => "Usuarios", -"Delete" => "Eliminar", +"Delete" => "Eliiminar", "Enable User External Storage" => "Habilitar almacenamiento de usuario externo", "Allow users to mount their own external storage" => "Permitir a los usuarios montar su propio almacenamiento externo", "SSL root certificates" => "Raíz de certificados SSL ", diff --git a/apps/files_external/l10n/et_EE.php b/apps/files_external/l10n/et_EE.php index 465201df4d..5d1eb0887b 100644 --- a/apps/files_external/l10n/et_EE.php +++ b/apps/files_external/l10n/et_EE.php @@ -5,8 +5,7 @@ "Please provide a valid Dropbox app key and secret." => "Palun sisesta korrektne Dropboxi rakenduse võti ja salasõna.", "Error configuring Google Drive storage" => "Viga Google Drive'i salvestusruumi seadistamisel", "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Hoiatus: \"smbclient\" pole paigaldatud. Jagatud CIFS/SMB hoidlate ühendamine pole võimalik. Palu oma süsteemihalduril paigaldata SAMBA tugi.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Hoiatus: PHP-s puudub FTP tugi. Jagatud FTP hoidlate ühendamine pole võimalik. Palu oma süsteemihalduril paigaldata FTP tugi.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Hoiatus: PHP-s puudub Curl tugi. Jagatud ownCloud / WebDAV või GoogleDrive ühendamine pole võimalik. Palu oma süsteemihalduril see paigaldada.", +"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Hoiatus: FTP tugi puudub PHP paigalduses. Jagatud FTP hoidlate ühendamine pole võimalik. Palu oma süsteemihalduril paigaldata FTP tugi.", "External Storage" => "Väline salvestuskoht", "Folder name" => "Kausta nimi", "External storage" => "Väline andmehoidla", diff --git a/apps/files_external/l10n/fr.php b/apps/files_external/l10n/fr.php index 5006133a7b..c42c89f857 100644 --- a/apps/files_external/l10n/fr.php +++ b/apps/files_external/l10n/fr.php @@ -6,7 +6,6 @@ "Error configuring Google Drive storage" => "Erreur lors de la configuration du support de stockage Google Drive", "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Attention : \"smbclient\" n'est pas installé. Le montage des partages CIFS/SMB n'est pas disponible. Contactez votre administrateur système pour l'installer.", "Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Attention : Le support FTP de PHP n'est pas activé ou installé. Le montage des partages FTP n'est pas disponible. Contactez votre administrateur système pour l'installer.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Attention : Le support de Curl n'est pas activé ou installé dans PHP. Le montage de ownCloud / WebDAV ou GoogleDrive n'est pas possible. Contactez votre administrateur système pour l'installer.", "External Storage" => "Stockage externe", "Folder name" => "Nom du dossier", "External storage" => "Stockage externe", diff --git a/apps/files_external/l10n/lb.php b/apps/files_external/l10n/lb.php index 4e78227ec4..2a62cad3fe 100644 --- a/apps/files_external/l10n/lb.php +++ b/apps/files_external/l10n/lb.php @@ -1,6 +1,5 @@ "Dossiers Numm:", "Groups" => "Gruppen", -"Users" => "Benotzer", "Delete" => "Läschen" ); diff --git a/apps/files_external/l10n/nl.php b/apps/files_external/l10n/nl.php index ded5a861a8..ad3eda9747 100644 --- a/apps/files_external/l10n/nl.php +++ b/apps/files_external/l10n/nl.php @@ -6,7 +6,6 @@ "Error configuring Google Drive storage" => "Fout tijdens het configureren van Google Drive opslag", "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Waarschuwing: \"smbclient\" is niet geïnstalleerd. Mounten van CIFS/SMB shares is niet mogelijk. Vraag uw beheerder om smbclient te installeren.", "Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Waarschuwing: FTP ondersteuning in PHP is niet geactiveerd of geïnstalleerd. Mounten van FTP shares is niet mogelijk. Vraag uw beheerder FTP ondersteuning te installeren.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Waarschuwing: Curl ondersteuning in PHP is niet geactiveerd of geïnstalleerd. Mounten van ownCloud / WebDAV of GoogleDrive is niet mogelijk. Vraag uw systeembeheerder dit te installeren.", "External Storage" => "Externe opslag", "Folder name" => "Mapnaam", "External storage" => "Externe opslag", diff --git a/apps/files_external/l10n/pt_BR.php b/apps/files_external/l10n/pt_BR.php index bc3c356a51..a358d56913 100644 --- a/apps/files_external/l10n/pt_BR.php +++ b/apps/files_external/l10n/pt_BR.php @@ -6,7 +6,6 @@ "Error configuring Google Drive storage" => "Erro ao configurar armazenamento do Google Drive", "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Aviso: \"smbclient\" não está instalado. Impossível montar compartilhamentos de CIFS/SMB. Por favor, peça ao seu administrador do sistema para instalá-lo.", "Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Aviso: O suporte para FTP do PHP não está ativado ou instalado. Impossível montar compartilhamentos FTP. Por favor, peça ao seu administrador do sistema para instalá-lo.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => " Aviso: O suport a Curl em PHP não está habilitado ou instalado. A montagem do ownCloud / WebDAV ou GoogleDrive não é possível. Por favor, solicite ao seu administrador do sistema instalá-lo.", "External Storage" => "Armazenamento Externo", "Folder name" => "Nome da pasta", "External storage" => "Armazenamento Externo", @@ -18,7 +17,7 @@ "All Users" => "Todos os Usuários", "Groups" => "Grupos", "Users" => "Usuários", -"Delete" => "Excluir", +"Delete" => "Remover", "Enable User External Storage" => "Habilitar Armazenamento Externo do Usuário", "Allow users to mount their own external storage" => "Permitir usuários a montar seus próprios armazenamentos externos", "SSL root certificates" => "Certificados SSL raíz", diff --git a/apps/files_external/l10n/ro.php b/apps/files_external/l10n/ro.php index ed23b4cca8..5747205dc0 100644 --- a/apps/files_external/l10n/ro.php +++ b/apps/files_external/l10n/ro.php @@ -6,14 +6,11 @@ "Error configuring Google Drive storage" => "Eroare la configurarea mediului de stocare Google Drive", "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "AtenÈ›ie: \"smbclient\" nu este instalat. Montarea mediilor CIFS/SMB partajate nu este posibilă. Solicită administratorului sistemului tău să îl instaleaze.", "Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "AtenÈ›ie: suportul pentru FTP în PHP nu este activat sau instalat. Montarea mediilor FPT partajate nu este posibilă. Solicită administratorului sistemului tău să îl instaleze.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Atentie: Suportul Curl nu este pornit / instalat in configuratia PHP! Montarea ownCloud / WebDAV / GoogleDrive nu este posibila! Intrebati administratorul sistemului despre aceasta problema!", "External Storage" => "Stocare externă", "Folder name" => "Denumire director", -"External storage" => "Stocare externă", "Configuration" => "ConfiguraÈ›ie", "Options" => "OpÈ›iuni", "Applicable" => "Aplicabil", -"Add storage" => "Adauga stocare", "None set" => "Niciunul", "All Users" => "ToÈ›i utilizatorii", "Groups" => "Grupuri", diff --git a/apps/files_external/l10n/ru.php b/apps/files_external/l10n/ru.php index d2c5292bac..46b73a67f0 100644 --- a/apps/files_external/l10n/ru.php +++ b/apps/files_external/l10n/ru.php @@ -6,7 +6,6 @@ "Error configuring Google Drive storage" => "Ошибка при наÑтройке хранилища Google Drive", "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Внимание: \"smbclient\" не уÑтановлен. Подключение по CIFS/SMB невозможно. ПожалуйÑта, обратитеÑÑŒ к ÑиÑтемному админиÑтратору, чтобы уÑтановить его.", "Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Внимание: Поддержка FTP не включена в PHP. Подключение по FTP невозможно. ПожалуйÑта, обратитеÑÑŒ к ÑиÑтемному админиÑтратору, чтобы включить.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Внимание: Поддержка Curl в PHP не включена или не уÑтановлена. Подключение ownCloud / WebDAV или GoogleDrive невозможно. ПопроÑите вашего ÑиÑтемного админиÑтратора уÑтановить его.", "External Storage" => "Внешний ноÑитель", "Folder name" => "Ð˜Ð¼Ñ Ð¿Ð°Ð¿ÐºÐ¸", "External storage" => "Внешний ноÑитель данных", diff --git a/apps/files_external/l10n/sk_SK.php b/apps/files_external/l10n/sk_SK.php index 33edcb9d4c..af6b7b4ae6 100644 --- a/apps/files_external/l10n/sk_SK.php +++ b/apps/files_external/l10n/sk_SK.php @@ -6,7 +6,6 @@ "Error configuring Google Drive storage" => "Chyba pri konfigurácii úložiska Google drive", "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Upozornenie: \"smbclient\" nie je nainÅ¡talovaný. Nie je možné pripojenie oddielov CIFS/SMB. Požiadajte administrátora systému, nech ho nainÅ¡taluje.", "Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Upozornenie: Podpora FTP v PHP nie je povolená alebo nainÅ¡talovaná. Nie je možné pripojenie oddielov FTP. Požiadajte administrátora systému, nech ho nainÅ¡taluje.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Varovanie: nie je nainÅ¡talovaná, alebo povolená, podpora Curl v PHP. Nie je možné pripojenie oddielov ownCloud, WebDAV, Äi GoogleDrive. Prosím požiadajte svojho administrátora systému, nech ju nainÅ¡taluje.", "External Storage" => "Externé úložisko", "Folder name" => "Meno prieÄinka", "External storage" => "Externé úložisko", @@ -18,7 +17,7 @@ "All Users" => "VÅ¡etci používatelia", "Groups" => "Skupiny", "Users" => "Používatelia", -"Delete" => "ZmazaÅ¥", +"Delete" => "OdstrániÅ¥", "Enable User External Storage" => "PovoliÅ¥ externé úložisko", "Allow users to mount their own external storage" => "PovoliÅ¥ používateľom pripojiÅ¥ ich vlastné externé úložisko", "SSL root certificates" => "Koreňové SSL certifikáty", diff --git a/apps/files_external/l10n/sl.php b/apps/files_external/l10n/sl.php index 09b91b913e..4ff2eed3bf 100644 --- a/apps/files_external/l10n/sl.php +++ b/apps/files_external/l10n/sl.php @@ -5,8 +5,7 @@ "Please provide a valid Dropbox app key and secret." => "Vpisati je treba veljaven kljuÄ programa in kodo za Dropbox", "Error configuring Google Drive storage" => "Napaka nastavljanja shrambe Google Drive", "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Opozorilo: paket \"smbclient\" ni nameÅ¡Äen. Priklapljanje pogonov CIFS/SMB ne bo mogoÄe.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Opozorilo: podpora FTP v PHP ni omogoÄena ali pa ni nameÅ¡Äena. Priklapljanje pogonov FTP zato ne bo mogoÄe.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Opozorilo: podpora za Curl v PHP ni omogoÄena ali pa ni nameÅ¡Äena. Priklapljanje toÄke ownCloud / WebDAV ali GoogleDrive zato ne bo mogoÄe. Zahtevane pakete je treba pred uporabo namestiti.", +"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Opozorilo: podpora FTP v PHP ni omogoÄena ali pa ni nameÅ¡Äena. Priklapljanje pogonov FTP zato ni mogoÄe.", "External Storage" => "Zunanja podatkovna shramba", "Folder name" => "Ime mape", "External storage" => "Zunanja shramba", @@ -19,7 +18,7 @@ "Groups" => "Skupine", "Users" => "Uporabniki", "Delete" => "IzbriÅ¡i", -"Enable User External Storage" => "OmogoÄi zunanjo uporabniÅ¡ko podatkovno shrambo", +"Enable User External Storage" => "OmogoÄi uporabniÅ¡ko zunanjo podatkovno shrambo", "Allow users to mount their own external storage" => "Dovoli uporabnikom priklop lastne zunanje podatkovne shrambe", "SSL root certificates" => "Korenska potrdila SSL", "Import Root Certificate" => "Uvozi korensko potrdilo" diff --git a/apps/files_external/l10n/zh_TW.php b/apps/files_external/l10n/zh_TW.php index a8314dcef0..873b555348 100644 --- a/apps/files_external/l10n/zh_TW.php +++ b/apps/files_external/l10n/zh_TW.php @@ -1,26 +1,16 @@ "å…許存å–", -"Error configuring Dropbox storage" => "設定 Dropbox 儲存時發生錯誤", -"Grant access" => "å…許存å–", -"Please provide a valid Dropbox app key and secret." => "è«‹æ供有效的 Dropbox app key å’Œ app secret 。", -"Error configuring Google Drive storage" => "設定 Google Drive 儲存時發生錯誤", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "è­¦å‘Šï¼šæœªå®‰è£ \"smbclient\" ,因此無法掛載 CIFS/SMB 分享,請洽您的系統管ç†å“¡å°‡å…¶å®‰è£ã€‚", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "警告:PHP 並未啓用 FTP 的支æ´ï¼Œå› æ­¤ç„¡æ³•æŽ›è¼‰ FTP 分享,請洽您的系統管ç†å“¡å°‡å…¶å®‰è£ä¸¦å•“用。", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "警告:PHP 並未啓用 Curl 的支æ´ï¼Œå› æ­¤ç„¡æ³•æŽ›è¼‰ ownCloud/WebDAV 或 Google Drive 分享,請洽您的系統管ç†å“¡å°‡å…¶å®‰è£ä¸¦å•“用。", -"External Storage" => "外部儲存", +"Access granted" => "訪å•æ¬Šå·²è¢«å‡†è¨±", +"Grant access" => "准許訪å•æ¬Š", +"External Storage" => "外部儲存è£ç½®", "Folder name" => "資料夾å稱", -"External storage" => "外部儲存", +"External storage" => "外部儲存è£ç½®", "Configuration" => "設定", "Options" => "é¸é …", -"Applicable" => "å¯ç”¨çš„", -"Add storage" => "增加儲存å€", +"Add storage" => "添加儲存å€", "None set" => "尚未設定", "All Users" => "所有使用者", "Groups" => "群組", "Users" => "使用者", "Delete" => "刪除", -"Enable User External Storage" => "啓用使用者外部儲存", -"Allow users to mount their own external storage" => "å…許使用者自行掛載他們的外部儲存", -"SSL root certificates" => "SSL 根憑證", "Import Root Certificate" => "匯入根憑證" ); diff --git a/apps/files_sharing/l10n/bn_BD.php b/apps/files_sharing/l10n/bn_BD.php index 5fdf6de50c..c3af434ee2 100644 --- a/apps/files_sharing/l10n/bn_BD.php +++ b/apps/files_sharing/l10n/bn_BD.php @@ -1,6 +1,6 @@ "কূটশবà§à¦¦", -"Submit" => "জমা দিন", +"Submit" => "জমা দাও", "%s shared the folder %s with you" => "%s আপনার সাথে %s ফোলà§à¦¡à¦¾à¦°à¦Ÿà¦¿ ভাগাভাগি করেছেন", "%s shared the file %s with you" => "%s আপনার সাথে %s ফাইলটি ভাগাভাগি করেছেন", "Download" => "ডাউনলোড", diff --git a/apps/files_sharing/l10n/de_DE.php b/apps/files_sharing/l10n/de_DE.php index ab81589b0e..b92d6d478c 100644 --- a/apps/files_sharing/l10n/de_DE.php +++ b/apps/files_sharing/l10n/de_DE.php @@ -1,9 +1,9 @@ "Passwort", -"Submit" => "Bestätigen", +"Submit" => "Absenden", "%s shared the folder %s with you" => "%s hat den Ordner %s mit Ihnen geteilt", "%s shared the file %s with you" => "%s hat die Datei %s mit Ihnen geteilt", -"Download" => "Herunterladen", +"Download" => "Download", "No preview available for" => "Es ist keine Vorschau verfügbar für", "web services under your control" => "Web-Services unter Ihrer Kontrolle" ); diff --git a/apps/files_sharing/l10n/he.php b/apps/files_sharing/l10n/he.php index 2ea5ba76ab..ff7be88af8 100644 --- a/apps/files_sharing/l10n/he.php +++ b/apps/files_sharing/l10n/he.php @@ -1,5 +1,5 @@ "סיסמ×", +"Password" => "ססמה", "Submit" => "שליחה", "%s shared the folder %s with you" => "%s שיתף עמך ×ת התיקייה %s", "%s shared the file %s with you" => "%s שיתף עמך ×ת הקובץ %s", diff --git a/apps/files_sharing/l10n/hi.php b/apps/files_sharing/l10n/hi.php deleted file mode 100644 index 560df54fc9..0000000000 --- a/apps/files_sharing/l10n/hi.php +++ /dev/null @@ -1,3 +0,0 @@ - "पासवरà¥à¤¡" -); diff --git a/apps/files_sharing/l10n/hr.php b/apps/files_sharing/l10n/hr.php deleted file mode 100644 index b2dca866bb..0000000000 --- a/apps/files_sharing/l10n/hr.php +++ /dev/null @@ -1,6 +0,0 @@ - "Lozinka", -"Submit" => "PoÅ¡alji", -"Download" => "Preuzimanje", -"web services under your control" => "web usluge pod vaÅ¡om kontrolom" -); diff --git a/apps/files_sharing/l10n/hy.php b/apps/files_sharing/l10n/hy.php deleted file mode 100644 index 438e8a7433..0000000000 --- a/apps/files_sharing/l10n/hy.php +++ /dev/null @@ -1,4 +0,0 @@ - "Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬", -"Download" => "Ô²Õ¥Õ¼Õ¶Õ¥Õ¬" -); diff --git a/apps/files_sharing/l10n/ia.php b/apps/files_sharing/l10n/ia.php deleted file mode 100644 index d229135a71..0000000000 --- a/apps/files_sharing/l10n/ia.php +++ /dev/null @@ -1,6 +0,0 @@ - "Contrasigno", -"Submit" => "Submitter", -"Download" => "Discargar", -"web services under your control" => "servicios web sub tu controlo" -); diff --git a/apps/files_sharing/l10n/ku_IQ.php b/apps/files_sharing/l10n/ku_IQ.php index 675fc372e1..f139b0a064 100644 --- a/apps/files_sharing/l10n/ku_IQ.php +++ b/apps/files_sharing/l10n/ku_IQ.php @@ -1,5 +1,5 @@ "وشەی تێپەربو", +"Password" => "تێپه‌ڕه‌وشه", "Submit" => "ناردن", "%s shared the folder %s with you" => "%s دابه‌شی کردووه‌ بوخچه‌ی %s له‌گه‌ڵ تۆ", "%s shared the file %s with you" => "%s دابه‌شی کردووه‌ په‌ڕگه‌یی %s له‌گه‌ڵ تۆ", diff --git a/apps/files_sharing/l10n/lb.php b/apps/files_sharing/l10n/lb.php index 630866ab4c..8aba5806aa 100644 --- a/apps/files_sharing/l10n/lb.php +++ b/apps/files_sharing/l10n/lb.php @@ -1,6 +1,3 @@ "Passwuert", -"Submit" => "Fortschécken", -"Download" => "Download", -"web services under your control" => "Web Servicer ënnert denger Kontroll" +"Password" => "Passwuert" ); diff --git a/apps/files_sharing/l10n/lt_LT.php b/apps/files_sharing/l10n/lt_LT.php index 96ab48cd2c..d21a3c14f4 100644 --- a/apps/files_sharing/l10n/lt_LT.php +++ b/apps/files_sharing/l10n/lt_LT.php @@ -1,6 +1,6 @@ "Slaptažodis", -"Submit" => "IÅ¡saugoti", -"Download" => "Atsisiųsti", -"web services under your control" => "jÅ«sų valdomos web paslaugos" +"Size" => "Dydis", +"Modified" => "Pakeista", +"Delete all" => "IÅ¡trinti viskÄ…", +"Delete" => "IÅ¡trinti" ); diff --git a/apps/files_sharing/l10n/lv.php b/apps/files_sharing/l10n/lv.php index 88faeaf9f1..0b22486708 100644 --- a/apps/files_sharing/l10n/lv.php +++ b/apps/files_sharing/l10n/lv.php @@ -5,5 +5,5 @@ "%s shared the file %s with you" => "%s ar jums dalÄ«jÄs ar datni %s", "Download" => "LejupielÄdÄ“t", "No preview available for" => "Nav pieejams priekÅ¡skatÄ«jums priekÅ¡", -"web services under your control" => "tÄ«mekļa servisi tavÄ varÄ" +"web services under your control" => "jÅ«su vadÄ«bÄ esoÅ¡ie tÄ«mekļa servisi" ); diff --git a/apps/files_sharing/l10n/ms_MY.php b/apps/files_sharing/l10n/ms_MY.php deleted file mode 100644 index 879524afce..0000000000 --- a/apps/files_sharing/l10n/ms_MY.php +++ /dev/null @@ -1,6 +0,0 @@ - "Kata laluan", -"Submit" => "Hantar", -"Download" => "Muat turun", -"web services under your control" => "Perkhidmatan web di bawah kawalan anda" -); diff --git a/apps/files_sharing/l10n/nn_NO.php b/apps/files_sharing/l10n/nn_NO.php deleted file mode 100644 index abd1ee394b..0000000000 --- a/apps/files_sharing/l10n/nn_NO.php +++ /dev/null @@ -1,6 +0,0 @@ - "Passord", -"Submit" => "Send", -"Download" => "Last ned", -"web services under your control" => "Vev tjenester under din kontroll" -); diff --git a/apps/files_sharing/l10n/oc.php b/apps/files_sharing/l10n/oc.php deleted file mode 100644 index 07bc26ecdd..0000000000 --- a/apps/files_sharing/l10n/oc.php +++ /dev/null @@ -1,6 +0,0 @@ - "Senhal", -"Submit" => "Sosmetre", -"Download" => "Avalcarga", -"web services under your control" => "Services web jos ton contraròtle" -); diff --git a/apps/files_sharing/l10n/pt_BR.php b/apps/files_sharing/l10n/pt_BR.php index ce4c28ddcb..4dde4bb5ad 100644 --- a/apps/files_sharing/l10n/pt_BR.php +++ b/apps/files_sharing/l10n/pt_BR.php @@ -5,5 +5,5 @@ "%s shared the file %s with you" => "%s compartilhou o arquivo %s com você", "Download" => "Baixar", "No preview available for" => "Nenhuma visualização disponível para", -"web services under your control" => "serviços web sob seu controle" +"web services under your control" => "web services sob seu controle" ); diff --git a/apps/files_sharing/l10n/si_LK.php b/apps/files_sharing/l10n/si_LK.php index 580f7b1990..1c69c60817 100644 --- a/apps/files_sharing/l10n/si_LK.php +++ b/apps/files_sharing/l10n/si_LK.php @@ -1,9 +1,9 @@ "මුර පදය", +"Password" => "මුරපදය", "Submit" => "යොමු කරන්න", "%s shared the folder %s with you" => "%s ඔබව %s à·†à·à¶½à·Šà¶©à¶»à¶ºà¶§ හවුල් කරගත්තේය", "%s shared the file %s with you" => "%s ඔබ සමඟ %s ගොනුව බෙදà·à·„දà·à¶œà¶­à·Šà¶­à·šà¶º", -"Download" => "බà·à¶±à·Šà¶±", +"Download" => "භà·à¶œà¶­ කරන්න", "No preview available for" => "පූර්වදර්à·à¶±à¶ºà¶šà·Š නොමà·à¶­", "web services under your control" => "ඔබට පà·à¶½à¶±à¶º කළ à·„à·à¶šà·’ වෙබ් සේවà·à·€à¶±à·Š" ); diff --git a/apps/files_sharing/l10n/sk_SK.php b/apps/files_sharing/l10n/sk_SK.php index 14124eeb87..2e781f76f3 100644 --- a/apps/files_sharing/l10n/sk_SK.php +++ b/apps/files_sharing/l10n/sk_SK.php @@ -3,7 +3,7 @@ "Submit" => "OdoslaÅ¥", "%s shared the folder %s with you" => "%s zdieľa s vami prieÄinok %s", "%s shared the file %s with you" => "%s zdieľa s vami súbor %s", -"Download" => "SÅ¥ahovanie", +"Download" => "StiahnuÅ¥", "No preview available for" => "Žiaden náhľad k dispozícii pre", "web services under your control" => "webové služby pod VaÅ¡ou kontrolou" ); diff --git a/apps/files_sharing/l10n/sr.php b/apps/files_sharing/l10n/sr.php index be24c06e46..6e277f6771 100644 --- a/apps/files_sharing/l10n/sr.php +++ b/apps/files_sharing/l10n/sr.php @@ -1,6 +1,5 @@ "Лозинка", "Submit" => "Пошаљи", -"Download" => "Преузми", -"web services under your control" => "веб ÑервиÑи под контролом" +"Download" => "Преузми" ); diff --git a/apps/files_sharing/l10n/sr@latin.php b/apps/files_sharing/l10n/sr@latin.php deleted file mode 100644 index cce6bd1f77..0000000000 --- a/apps/files_sharing/l10n/sr@latin.php +++ /dev/null @@ -1,5 +0,0 @@ - "Lozinka", -"Submit" => "PoÅ¡alji", -"Download" => "Preuzmi" -); diff --git a/apps/files_sharing/l10n/tr.php b/apps/files_sharing/l10n/tr.php index 42dfec8cc6..f2e6e5697d 100644 --- a/apps/files_sharing/l10n/tr.php +++ b/apps/files_sharing/l10n/tr.php @@ -1,5 +1,5 @@ "Parola", +"Password" => "Åžifre", "Submit" => "Gönder", "%s shared the folder %s with you" => "%s sizinle paylaşılan %s klasör", "%s shared the file %s with you" => "%s sizinle paylaşılan %s klasör", diff --git a/apps/files_sharing/l10n/uk.php b/apps/files_sharing/l10n/uk.php index 8e1fa4bc98..cdc103ad46 100644 --- a/apps/files_sharing/l10n/uk.php +++ b/apps/files_sharing/l10n/uk.php @@ -1,6 +1,6 @@ "Пароль", -"Submit" => "Передати", +"Submit" => "Submit", "%s shared the folder %s with you" => "%s опублікував каталог %s Ð´Ð»Ñ Ð’Ð°Ñ", "%s shared the file %s with you" => "%s опублікував файл %s Ð´Ð»Ñ Ð’Ð°Ñ", "Download" => "Завантажити", diff --git a/apps/files_sharing/l10n/zh_TW.php b/apps/files_sharing/l10n/zh_TW.php index 14e4466ecb..f1d28731a7 100644 --- a/apps/files_sharing/l10n/zh_TW.php +++ b/apps/files_sharing/l10n/zh_TW.php @@ -1,9 +1,9 @@ "密碼", "Submit" => "é€å‡º", -"%s shared the folder %s with you" => "%s 和您分享了資料夾 %s ", -"%s shared the file %s with you" => "%s 和您分享了檔案 %s", +"%s shared the folder %s with you" => "%s 分享了資料夾 %s 給您", +"%s shared the file %s with you" => "%s 分享了檔案 %s 給您", "Download" => "下載", "No preview available for" => "無法é è¦½", -"web services under your control" => "由您控制的網路æœå‹™" +"web services under your control" => "在您掌控之下的網路æœå‹™" ); diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 733b783876..9fccd0b46f 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -44,7 +44,7 @@ class Shared_Cache extends Cache { $source = \OC_Share_Backend_File::getSource($target); if (isset($source['path']) && isset($source['fileOwner'])) { \OC\Files\Filesystem::initMountPoints($source['fileOwner']); - $mount = \OC\Files\Filesystem::getMountByNumericId($source['storage']); + $mount = \OC\Files\Mount::findByNumericId($source['storage']); if ($mount) { $fullPath = $mount->getMountPoint().$source['path']; list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($fullPath); diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 2facad0f7e..ffd4e5ced2 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -71,7 +71,7 @@ class Shared extends \OC\Files\Storage\Common { if ($source) { if (!isset($source['fullPath'])) { \OC\Files\Filesystem::initMountPoints($source['fileOwner']); - $mount = \OC\Files\Filesystem::getMountByNumericId($source['storage']); + $mount = \OC\Files\Mount::findByNumericId($source['storage']); if ($mount) { $this->files[$target]['fullPath'] = $mount->getMountPoint().$source['path']; } else { diff --git a/apps/files_trashbin/l10n/id.php b/apps/files_trashbin/l10n/id.php index 62a63d515a..e06c66784f 100644 --- a/apps/files_trashbin/l10n/id.php +++ b/apps/files_trashbin/l10n/id.php @@ -2,13 +2,13 @@ "Couldn't delete %s permanently" => "Tidak dapat menghapus permanen %s", "Couldn't restore %s" => "Tidak dapat memulihkan %s", "perform restore operation" => "jalankan operasi pemulihan", -"Error" => "Galat", +"Error" => "kesalahan", "delete file permanently" => "hapus berkas secara permanen", -"Delete permanently" => "Hapus secara permanen", +"Delete permanently" => "hapus secara permanen", "Name" => "Nama", "Deleted" => "Dihapus", -"1 folder" => "1 folder", -"{count} folders" => "{count} folder", +"1 folder" => "1 map", +"{count} folders" => "{count} map", "1 file" => "1 berkas", "{count} files" => "{count} berkas", "Nothing in here. Your trash bin is empty!" => "Tempat sampah anda kosong!", diff --git a/apps/files_trashbin/l10n/nn_NO.php b/apps/files_trashbin/l10n/nn_NO.php index 8166a024e5..14345ddcc4 100644 --- a/apps/files_trashbin/l10n/nn_NO.php +++ b/apps/files_trashbin/l10n/nn_NO.php @@ -1,10 +1,5 @@ "Feil", -"Delete permanently" => "Slett for godt", "Name" => "Namn", -"1 folder" => "1 mappe", -"{count} folders" => "{count} mapper", -"1 file" => "1 fil", -"{count} files" => "{count} filer", "Delete" => "Slett" ); diff --git a/apps/files_trashbin/l10n/pl.php b/apps/files_trashbin/l10n/pl.php index 5c9f558f11..7fd1ab21ec 100644 --- a/apps/files_trashbin/l10n/pl.php +++ b/apps/files_trashbin/l10n/pl.php @@ -8,9 +8,9 @@ "Name" => "Nazwa", "Deleted" => "UsuniÄ™te", "1 folder" => "1 folder", -"{count} folders" => "Ilość folderów: {count}", +"{count} folders" => "{count} foldery", "1 file" => "1 plik", -"{count} files" => "Ilość plików: {count}", +"{count} files" => "{count} pliki", "Nothing in here. Your trash bin is empty!" => "Nic tu nie ma. Twój kosz jest pusty!", "Restore" => "Przywróć", "Delete" => "UsuÅ„", diff --git a/apps/files_trashbin/l10n/pt_PT.php b/apps/files_trashbin/l10n/pt_PT.php index ba85158b70..7dfe610466 100644 --- a/apps/files_trashbin/l10n/pt_PT.php +++ b/apps/files_trashbin/l10n/pt_PT.php @@ -13,6 +13,6 @@ "{count} files" => "{count} ficheiros", "Nothing in here. Your trash bin is empty!" => "Não hà ficheiros. O lixo está vazio!", "Restore" => "Restaurar", -"Delete" => "Eliminar", +"Delete" => "Apagar", "Deleted Files" => "Ficheiros Apagados" ); diff --git a/apps/files_trashbin/l10n/ro.php b/apps/files_trashbin/l10n/ro.php index 3af21b7e3f..c03ef600f3 100644 --- a/apps/files_trashbin/l10n/ro.php +++ b/apps/files_trashbin/l10n/ro.php @@ -1,6 +1,5 @@ "Eroare", -"Delete permanently" => "Stergere permanenta", "Name" => "Nume", "1 folder" => "1 folder", "{count} folders" => "{count} foldare", diff --git a/apps/files_trashbin/l10n/sk_SK.php b/apps/files_trashbin/l10n/sk_SK.php index 7cef36ef1c..7203f4c75f 100644 --- a/apps/files_trashbin/l10n/sk_SK.php +++ b/apps/files_trashbin/l10n/sk_SK.php @@ -5,7 +5,7 @@ "Error" => "Chyba", "delete file permanently" => "trvalo zmazaÅ¥ súbor", "Delete permanently" => "ZmazaÅ¥ trvalo", -"Name" => "Názov", +"Name" => "Meno", "Deleted" => "Zmazané", "1 folder" => "1 prieÄinok", "{count} folders" => "{count} prieÄinkov", diff --git a/apps/files_trashbin/lib/trash.php b/apps/files_trashbin/lib/trash.php index 88c71a75ab..f0b56eef01 100644 --- a/apps/files_trashbin/lib/trash.php +++ b/apps/files_trashbin/lib/trash.php @@ -39,15 +39,14 @@ class Trashbin { $view = new \OC\Files\View('/'. $user); if (!$view->is_dir('files_trashbin')) { $view->mkdir('files_trashbin'); - $view->mkdir('files_trashbin/files'); - $view->mkdir('files_trashbin/versions'); - $view->mkdir('files_trashbin/keyfiles'); - $view->mkdir('files_trashbin/share-keys'); + $view->mkdir("files_trashbin/files"); + $view->mkdir("files_trashbin/versions"); + $view->mkdir("files_trashbin/keyfiles"); } $path_parts = pathinfo($file_path); - $filename = $path_parts['basename']; + $deleted = $path_parts['basename']; $location = $path_parts['dirname']; $timestamp = time(); $mime = $view->getMimeType('files'.$file_path); @@ -63,24 +62,45 @@ class Trashbin { $trashbinSize = self::calculateSize(new \OC\Files\View('/'. $user.'/files_trashbin')); } - $sizeOfAddedFiles = self::copy_recursive($file_path, 'files_trashbin/files/'.$filename.'.d'.$timestamp, $view); - - if ( $view->file_exists('files_trashbin/files/'.$filename.'.d'.$timestamp) ) { + $sizeOfAddedFiles = self::copy_recursive($file_path, 'files_trashbin/files/'.$deleted.'.d'.$timestamp, $view); + + if ( $view->file_exists('files_trashbin/files/'.$deleted.'.d'.$timestamp) ) { $trashbinSize += $sizeOfAddedFiles; $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`type`,`mime`,`user`) VALUES (?,?,?,?,?,?)"); - $result = $query->execute(array($filename, $timestamp, $location, $type, $mime, $user)); + $result = $query->execute(array($deleted, $timestamp, $location, $type, $mime, $user)); if ( !$result ) { // if file couldn't be added to the database than also don't store it in the trash bin. - $view->deleteAll('files_trashbin/files/'.$filename.'.d'.$timestamp); + $view->deleteAll('files_trashbin/files/'.$deleted.'.d'.$timestamp); \OC_Log::write('files_trashbin', 'trash bin database couldn\'t be updated', \OC_log::ERROR); return; } \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', array('filePath' => \OC\Files\Filesystem::normalizePath($file_path), - 'trashPath' => \OC\Files\Filesystem::normalizePath($filename.'.d'.$timestamp))); - - $trashbinSize += self::retainVersions($view, $file_path, $filename, $timestamp); - $trashbinSize += self::retainEncryptionKeys($view, $file_path, $filename, $timestamp); - + 'trashPath' => \OC\Files\Filesystem::normalizePath($deleted.'.d'.$timestamp))); + + // Take care of file versions + if ( \OCP\App::isEnabled('files_versions') ) { + if ( $view->is_dir('files_versions/'.$file_path) ) { + $trashbinSize += self::calculateSize(new \OC\Files\View('/'. $user.'/files_versions/'.$file_path)); + $view->rename('files_versions/'.$file_path, 'files_trashbin/versions'. $deleted.'.d'.$timestamp); + } else if ( $versions = \OCA\Files_Versions\Storage::getVersions($user, $file_path) ) { + foreach ($versions as $v) { + $trashbinSize += $view->filesize('files_versions'.$v['path'].'.v'.$v['version']); + $view->rename('files_versions'.$v['path'].'.v'.$v['version'], 'files_trashbin/versions/'. $deleted.'.v'.$v['version'].'.d'.$timestamp); + } + } + } + + // Take care of encryption keys + $keyfile = \OC\Files\Filesystem::normalizePath('files_encryption/keyfiles/'.$file_path); + if ( \OCP\App::isEnabled('files_encryption') && $view->file_exists($keyfile.'.key') ) { + if ( $view->is_dir('files'.$file_path) ) { + $trashbinSize += self::calculateSize(new \OC\Files\View('/'.$user.'/'.$keyfile)); + $view->rename($keyfile, 'files_trashbin/keyfiles/'. $deleted.'.d'.$timestamp); + } else { + $trashbinSize += $view->filesize($keyfile.'.key'); + $view->rename($keyfile.'.key', 'files_trashbin/keyfiles/'. $deleted.'.key.d'.$timestamp); + } + } } else { \OC_Log::write('files_trashbin', 'Couldn\'t move '.$file_path.' to the trash bin', \OC_log::ERROR); } @@ -91,134 +111,15 @@ class Trashbin { } - /** - * Move file versions to trash so that they can be restored later - * - * @param \OC\Files\View $view - * @param $file_path path to original file - * @param $filename of deleted file - * @param $timestamp when the file was deleted - * - * @return size of stored versions - */ - private static function retainVersions($view, $file_path, $filename, $timestamp) { - $size = 0; - if (\OCP\App::isEnabled('files_versions')) { - - // disable proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - - $user = \OCP\User::getUser(); - if ($view->is_dir('files_versions/' . $file_path)) { - $size += self::calculateSize(new \OC\Files\View('/' . $user . '/files_versions/' . $file_path)); - $view->rename('files_versions/' . $file_path, 'files_trashbin/versions/' . $filename . '.d' . $timestamp); - } else if ($versions = \OCA\Files_Versions\Storage::getVersions($user, $file_path)) { - foreach ($versions as $v) { - $size += $view->filesize('files_versions' . $v['path'] . '.v' . $v['version']); - $view->rename('files_versions' . $v['path'] . '.v' . $v['version'], 'files_trashbin/versions/' . $filename . '.v' . $v['version'] . '.d' . $timestamp); - } - } - - // enable proxy - \OC_FileProxy::$enabled = $proxyStatus; - } - - return $size; - } - - /** - * Move encryption keys to trash so that they can be restored later - * - * @param \OC\Files\View $view - * @param $file_path path to original file - * @param $filename of deleted file - * @param $timestamp when the file was deleted - * - * @return size of encryption keys - */ - private static function retainEncryptionKeys($view, $file_path, $filename, $timestamp) { - $size = 0; - - if (\OCP\App::isEnabled('files_encryption')) { - - $user = \OCP\User::getUser(); - - // disable proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - - // retain key files - $keyfile = \OC\Files\Filesystem::normalizePath('files_encryption/keyfiles/' . $file_path); - - if ($view->is_dir($keyfile) || $view->file_exists($keyfile . '.key')) { - $user = \OCP\User::getUser(); - // move keyfiles - if ($view->is_dir($keyfile)) { - $size += self::calculateSize(new \OC\Files\View('/' . $user . '/' . $keyfile)); - $view->rename($keyfile, 'files_trashbin/keyfiles/' . $filename . '.d' . $timestamp); - } else { - $size += $view->filesize($keyfile . '.key'); - $view->rename($keyfile . '.key', 'files_trashbin/keyfiles/' . $filename . '.key.d' . $timestamp); - } - } - - // retain share keys - $sharekeys = \OC\Files\Filesystem::normalizePath('files_encryption/share-keys/' . $file_path); - - if ($view->is_dir($sharekeys)) { - $size += self::calculateSize(new \OC\Files\View('/' . $user . '/' . $sharekeys)); - $view->rename($sharekeys, 'files_trashbin/share-keys/' . $filename . '.d' . $timestamp); - } else { - // get local path to share-keys - $localShareKeysPath = $view->getLocalFile($sharekeys); - - // handle share-keys - $matches = glob(preg_quote($localShareKeysPath).'*.shareKey'); - foreach ($matches as $src) { - // get source file parts - $pathinfo = pathinfo($src); - - // we only want to keep the owners key so we can access the private key - $ownerShareKey = $filename . '.' . $user. '.shareKey'; - - // if we found the share-key for the owner, we need to move it to files_trashbin - if($pathinfo['basename'] == $ownerShareKey) { - - // calculate size - $size += $view->filesize($sharekeys. '.' . $user. '.shareKey'); - - // move file - $view->rename($sharekeys. '.' . $user. '.shareKey', 'files_trashbin/share-keys/' . $ownerShareKey . '.d' . $timestamp); - } else { - - // calculate size - $size += filesize($src); - - // don't keep other share-keys - unlink($src); - } - } - - } - - // enable proxy - \OC_FileProxy::$enabled = $proxyStatus; - } - return $size; - } /** * restore files from trash bin * @param $file path to the deleted file * @param $filename name of the file * @param $timestamp time when the file was deleted - * - * @return bool - */ + */ public static function restore($file, $filename, $timestamp) { - - $user = \OCP\User::getUser(); + $user = \OCP\User::getUser(); $view = new \OC\Files\View('/'.$user); $trashbinSize = self::getTrashbinSize($user); @@ -256,17 +157,8 @@ class Trashbin { // we need a extension in case a file/dir with the same name already exists $ext = self::getUniqueExtension($location, $filename, $view); $mtime = $view->filemtime($source); - - // disable proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - - // restore file - $restoreResult = $view->rename($source, $target.$ext); - - // handle the restore result - if( $restoreResult ) { - $view->touch($target.$ext, $mtime); + if( $view->rename($source, $target.$ext) ) { + $view->touch($target.$ext, $mtime); \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', array('filePath' => \OC\Files\Filesystem::normalizePath('/'.$location.'/'.$filename.$ext), 'trashPath' => \OC\Files\Filesystem::normalizePath($file))); @@ -275,183 +167,68 @@ class Trashbin { } else { $trashbinSize -= $view->filesize($target.$ext); } - - $trashbinSize -= self::restoreVersions($view, $file, $filename, $ext, $location, $timestamp); - $trashbinSize -= self::restoreEncryptionKeys($view, $file, $filename, $ext, $location, $timestamp); - + // if versioning app is enabled, copy versions from the trash bin back to the original location + if ( \OCP\App::isEnabled('files_versions') ) { + if ($timestamp ) { + $versionedFile = $filename; + } else { + $versionedFile = $file; + } + if ( $result[0]['type'] === 'dir' ) { + $trashbinSize -= self::calculateSize(new \OC\Files\View('/'.$user.'/'.'files_trashbin/versions/'. $file)); + $view->rename(\OC\Files\Filesystem::normalizePath('files_trashbin/versions/'. $file), \OC\Files\Filesystem::normalizePath('files_versions/'.$location.'/'.$filename.$ext)); + } else if ( $versions = self::getVersionsFromTrash($versionedFile, $timestamp) ) { + foreach ($versions as $v) { + if ($timestamp ) { + $trashbinSize -= $view->filesize('files_trashbin/versions/'.$versionedFile.'.v'.$v.'.d'.$timestamp); + $view->rename('files_trashbin/versions/'.$versionedFile.'.v'.$v.'.d'.$timestamp, 'files_versions/'.$location.'/'.$filename.$ext.'.v'.$v); + } else { + $trashbinSize -= $view->filesize('files_trashbin/versions/'.$versionedFile.'.v'.$v); + $view->rename('files_trashbin/versions/'.$versionedFile.'.v'.$v, 'files_versions/'.$location.'/'.$filename.$ext.'.v'.$v); + } + } + } + } + + // Take care of encryption keys TODO! Get '.key' in file between file name and delete date (also for permanent delete!) + $parts = pathinfo($file); + if ( $result[0]['type'] === 'dir' ) { + $keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/'.$parts['dirname'].'/'.$filename); + } else { + $keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/'.$parts['dirname'].'/'.$filename.'.key'); + } + if ($timestamp) { + $keyfile .= '.d'.$timestamp; + } + if ( \OCP\App::isEnabled('files_encryption') && $view->file_exists($keyfile) ) { + if ( $result[0]['type'] === 'dir' ) { + $trashbinSize -= self::calculateSize(new \OC\Files\View('/'.$user.'/'.$keyfile)); + $view->rename($keyfile, 'files_encryption/keyfiles/'. $location.'/'.$filename); + } else { + $trashbinSize -= $view->filesize($keyfile); + $view->rename($keyfile, 'files_encryption/keyfiles/'. $location.'/'.$filename.'.key'); + } + } + if ( $timestamp ) { $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=? AND `id`=? AND `timestamp`=?'); $query->execute(array($user,$filename,$timestamp)); } self::setTrashbinSize($user, $trashbinSize); - - // enable proxy - \OC_FileProxy::$enabled = $proxyStatus; - + return true; + } else { + \OC_Log::write('files_trashbin', 'Couldn\'t restore file from trash bin, '.$filename, \OC_log::ERROR); } - // enable proxy - \OC_FileProxy::$enabled = $proxyStatus; - return false; } - /** - * @brief restore versions from trash bin - * - * @param \OC\Files\View $view file view - * @param $file complete path to file - * @param $filename name of file - * @param $ext file extension in case a file with the same $filename already exists - * @param $location location if file - * @param $timestamp deleteion time - * - * @return size of restored versions - */ - private static function restoreVersions($view, $file, $filename, $ext, $location, $timestamp) { - $size = 0; - if (\OCP\App::isEnabled('files_versions')) { - // disable proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - - $user = \OCP\User::getUser(); - if ($timestamp) { - $versionedFile = $filename; - } else { - $versionedFile = $file; - } - - if ($view->is_dir('/files_trashbin/versions/'.$file)) { - $size += self::calculateSize(new \OC\Files\View('/' . $user . '/' . 'files_trashbin/versions/' . $file)); - $view->rename(\OC\Files\Filesystem::normalizePath('files_trashbin/versions/' . $file), \OC\Files\Filesystem::normalizePath('files_versions/' . $location . '/' . $filename . $ext)); - } else if ($versions = self::getVersionsFromTrash($versionedFile, $timestamp)) { - foreach ($versions as $v) { - if ($timestamp) { - $size += $view->filesize('files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp); - $view->rename('files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp, 'files_versions/' . $location . '/' . $filename . $ext . '.v' . $v); - } else { - $size += $view->filesize('files_trashbin/versions/' . $versionedFile . '.v' . $v); - $view->rename('files_trashbin/versions/' . $versionedFile . '.v' . $v, 'files_versions/' . $location . '/' . $filename . $ext . '.v' . $v); - } - } - } - - // enable proxy - \OC_FileProxy::$enabled = $proxyStatus; - } - return $size; - } - - - /** - * @brief restore encryption keys from trash bin - * - * @param \OC\Files\View $view - * @param $file complete path to file - * @param $filename name of file - * @param $ext file extension in case a file with the same $filename already exists - * @param $location location if file - * @param $timestamp deleteion time - * - * @return size of restored encrypted file - */ - private static function restoreEncryptionKeys($view, $file, $filename, $ext, $location, $timestamp) { - // Take care of encryption keys TODO! Get '.key' in file between file name and delete date (also for permanent delete!) - $size = 0; - if (\OCP\App::isEnabled('files_encryption')) { - $user = \OCP\User::getUser(); - - $path_parts = pathinfo($file); - $source_location = $path_parts['dirname']; - - if ($view->is_dir('/files_trashbin/keyfiles/'.$file)) { - if($source_location != '.') { - $keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/' . $source_location . '/' . $filename); - $sharekey = \OC\Files\Filesystem::normalizePath('files_trashbin/share-keys/' . $source_location . '/' . $filename); - } else { - $keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/' . $filename); - $sharekey = \OC\Files\Filesystem::normalizePath('files_trashbin/share-keys/' . $filename); - } - } else { - $keyfile = \OC\Files\Filesystem::normalizePath('files_trashbin/keyfiles/' . $source_location . '/' . $filename . '.key'); - } - - if ($timestamp) { - $keyfile .= '.d' . $timestamp; - } - - // disable proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - - if ($view->file_exists($keyfile)) { - // handle directory - if ($view->is_dir($keyfile)) { - - // handle keyfiles - $size += self::calculateSize(new \OC\Files\View('/' . $user . '/' . $keyfile)); - $view->rename($keyfile, 'files_encryption/keyfiles/' . $location . '/' . $filename . $ext); - - // handle share-keys - if ($timestamp) { - $sharekey .= '.d' . $timestamp; - } - $view->rename($sharekey, 'files_encryption/share-keys/' . $location . '/' . $filename . $ext); - - } else { - // handle keyfiles - $size += $view->filesize($keyfile); - $view->rename($keyfile, 'files_encryption/keyfiles/' . $location . '/' . $filename . $ext . '.key'); - - // handle share-keys - $ownerShareKey = \OC\Files\Filesystem::normalizePath('files_trashbin/share-keys/' . $source_location . '/' . $filename . '.' . $user. '.shareKey'); - if ($timestamp) { - $ownerShareKey .= '.d' . $timestamp; - } - - $size += $view->filesize($ownerShareKey); - - // move only owners key - $view->rename($ownerShareKey, 'files_encryption/share-keys/' . $location . '/' . $filename . $ext . '.' . $user. '.shareKey'); - - // try to re-share if file is shared - $filesystemView = new \OC_FilesystemView('/'); - $session = new \OCA\Encryption\Session($filesystemView); - $util = new \OCA\Encryption\Util($filesystemView, $user); - - // fix the file size - $absolutePath = \OC\Files\Filesystem::normalizePath('/' . $user . '/files/'. $location. '/' .$filename); - $util->fixFileSize($absolutePath); - - // get current sharing state - $sharingEnabled = \OCP\Share::isEnabled(); - - // get the final filename - $target = \OC\Files\Filesystem::normalizePath($location.'/'.$filename); - - // get users sharing this file - $usersSharing = $util->getSharingUsersArray($sharingEnabled, $target.$ext, $user); - - // Attempt to set shareKey - $util->setSharedFileKeyfiles($session, $usersSharing, $target.$ext); - } - } - - // enable proxy - \OC_FileProxy::$enabled = $proxyStatus; - } - return $size; - } - /** - * @brief delete file from trash bin permanently - * + * delete file from trash bin permanently * @param $filename path to the file * @param $timestamp of deletion time - * * @return size of deleted files */ public static function delete($filename, $timestamp=null) { diff --git a/apps/files_versions/l10n/et_EE.php b/apps/files_versions/l10n/et_EE.php index c8d2f7cfac..930cfbc33a 100644 --- a/apps/files_versions/l10n/et_EE.php +++ b/apps/files_versions/l10n/et_EE.php @@ -7,5 +7,5 @@ "No old versions available" => "Vanu versioone pole saadaval", "No path specified" => "Asukohta pole määratud", "Versions" => "Versioonid", -"Revert a file to a previous version by clicking on its revert button" => "Taasta fail varasemale versioonile klikkides nupule \"Taasta\"" +"Revert a file to a previous version by clicking on its revert button" => "Taasta fail varasemale versioonile klikkides \"Revert\" nupule" ); diff --git a/apps/files_versions/l10n/he.php b/apps/files_versions/l10n/he.php index ad2e261d53..9eb4df6485 100644 --- a/apps/files_versions/l10n/he.php +++ b/apps/files_versions/l10n/he.php @@ -1,3 +1,5 @@ "גרס×ות" +"History" => "היסטוריה", +"Files Versioning" => "שמירת הבדלי גרס×ות של קבצי×", +"Enable" => "הפעלה" ); diff --git a/apps/files_versions/l10n/ku_IQ.php b/apps/files_versions/l10n/ku_IQ.php index 9132caf75e..db5dbad49f 100644 --- a/apps/files_versions/l10n/ku_IQ.php +++ b/apps/files_versions/l10n/ku_IQ.php @@ -1,3 +1,5 @@ "وه‌شان" +"History" => "مێژوو", +"Files Versioning" => "وه‌شانی په‌ڕگه", +"Enable" => "چالاککردن" ); diff --git a/apps/files_versions/l10n/nb_NO.php b/apps/files_versions/l10n/nb_NO.php index df59dfe4c8..18c7250610 100644 --- a/apps/files_versions/l10n/nb_NO.php +++ b/apps/files_versions/l10n/nb_NO.php @@ -1,3 +1,5 @@ "Versjoner" +"History" => "Historie", +"Files Versioning" => "Fil versjonering", +"Enable" => "Aktiver" ); diff --git a/apps/files_versions/l10n/ro.php b/apps/files_versions/l10n/ro.php index cd9fc89dcc..7dfaee3672 100644 --- a/apps/files_versions/l10n/ro.php +++ b/apps/files_versions/l10n/ro.php @@ -1,11 +1,5 @@ "Nu a putut reveni: %s", -"success" => "success", -"File %s was reverted to version %s" => "Fisierul %s a revenit la versiunea %s", -"failure" => "eÈ™ec", -"File %s could not be reverted to version %s" => "Fisierele %s nu au putut reveni la versiunea %s", -"No old versions available" => "Versiunile vechi nu sunt disponibile", -"No path specified" => "Nici un dosar specificat", -"Versions" => "Versiuni", -"Revert a file to a previous version by clicking on its revert button" => "Readuceti un fiÈ™ier la o versiune anterioară, făcând clic pe butonul revenire" +"History" => "Istoric", +"Files Versioning" => "Versionare fiÈ™iere", +"Enable" => "Activare" ); diff --git a/apps/files_versions/l10n/si_LK.php b/apps/files_versions/l10n/si_LK.php index c7ee63d8ef..37debf869b 100644 --- a/apps/files_versions/l10n/si_LK.php +++ b/apps/files_versions/l10n/si_LK.php @@ -1,3 +1,5 @@ "අනුවà·à¶¯" +"History" => "ඉතිහà·à·ƒà¶º", +"Files Versioning" => "ගොනු අනුවà·à¶¯à¶ºà¶±à·Š", +"Enable" => "සක්â€à¶»à·’ය කරන්න" ); diff --git a/apps/files_versions/l10n/ta_LK.php b/apps/files_versions/l10n/ta_LK.php index 61a47e42f0..aca76dcc26 100644 --- a/apps/files_versions/l10n/ta_LK.php +++ b/apps/files_versions/l10n/ta_LK.php @@ -1,3 +1,5 @@ "பதிபà¯à®ªà¯à®•à®³à¯" +"History" => "வரலாறà¯", +"Files Versioning" => "கோபà¯à®ªà¯ பதிபà¯à®ªà¯à®•à®³à¯", +"Enable" => "இயலà¯à®®à¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®•" ); diff --git a/apps/files_versions/l10n/th_TH.php b/apps/files_versions/l10n/th_TH.php index 2998f74838..e1e996903a 100644 --- a/apps/files_versions/l10n/th_TH.php +++ b/apps/files_versions/l10n/th_TH.php @@ -1,3 +1,5 @@ "รุ่น" +"History" => "ประวัติ", +"Files Versioning" => "à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”เวอร์ชั่นของไฟล์", +"Enable" => "เปิดใช้งาน" ); diff --git a/apps/files_versions/l10n/vi.php b/apps/files_versions/l10n/vi.php index 33b045f2e3..f2499e7bf3 100644 --- a/apps/files_versions/l10n/vi.php +++ b/apps/files_versions/l10n/vi.php @@ -6,6 +6,5 @@ "File %s could not be reverted to version %s" => "File %s không thể khôi phục vá» phiên bản %s", "No old versions available" => "Không có phiên bản cÅ© nào", "No path specified" => "Không chỉ ra Ä‘Æ°á»ng dẫn rõ ràng", -"Versions" => "Phiên bản", "Revert a file to a previous version by clicking on its revert button" => "Khôi phục má»™t file vá» phiên bản trÆ°á»›c đó bằng cách click vào nút Khôi phục tÆ°Æ¡ng ứng" ); diff --git a/apps/user_ldap/l10n/ca.php b/apps/user_ldap/l10n/ca.php index 8f2799b6e6..abdecb164e 100644 --- a/apps/user_ldap/l10n/ca.php +++ b/apps/user_ldap/l10n/ca.php @@ -15,7 +15,7 @@ "Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "Avís: El mòdul PHP LDAP no està instal·lat, el dorsal no funcionarà. Demaneu a l'administrador del sistema que l'instal·li.", "Server configuration" => "Configuració del servidor", "Add Server Configuration" => "Afegeix la configuració del servidor", -"Host" => "Equip remot", +"Host" => "Màquina", "You can omit the protocol, except you require SSL. Then start with ldaps://" => "Podeu ometre el protocol, excepte si requeriu SSL. Llavors comenceu amb ldaps://", "Base DN" => "DN Base", "One Base DN per line" => "Una DN Base per línia", diff --git a/apps/user_ldap/l10n/fa.php b/apps/user_ldap/l10n/fa.php index 89fc40af4f..9a01a67703 100644 --- a/apps/user_ldap/l10n/fa.php +++ b/apps/user_ldap/l10n/fa.php @@ -10,7 +10,7 @@ "Server configuration" => "پیکربندی سرور", "Add Server Configuration" => "اÙزودن پیکربندی سرور", "Host" => "میزبانی", -"Password" => "گذرواژه", +"Password" => "رمز عبور", "Group Filter" => "Ùیلتر گروه", "Port" => "درگاه", "in bytes" => "در بایت", diff --git a/apps/user_ldap/l10n/gl.php b/apps/user_ldap/l10n/gl.php index 215d518e7a..deb6dbb555 100644 --- a/apps/user_ldap/l10n/gl.php +++ b/apps/user_ldap/l10n/gl.php @@ -3,7 +3,7 @@ "The configuration is valid and the connection could be established!" => "A configuración é correcta e pode estabelecerse a conexión.", "The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "A configuración é correcta, mais a ligazón non. Comprobe a configuración do servidor e as credenciais.", "The configuration is invalid. Please look in the ownCloud log for further details." => "A configuración non é correcta. Vexa o rexistro de ownCloud para máis detalles", -"Deletion failed" => "Produciuse un fallo ao eliminar", +"Deletion failed" => "Fallou o borrado", "Take over settings from recent server configuration?" => "Tomar os recentes axustes de configuración do servidor?", "Keep settings?" => "Manter os axustes?", "Cannot add server configuration" => "Non é posíbel engadir a configuración do servidor", diff --git a/apps/user_ldap/l10n/hi.php b/apps/user_ldap/l10n/hi.php index 45166eb0e3..60d4ea98e8 100644 --- a/apps/user_ldap/l10n/hi.php +++ b/apps/user_ldap/l10n/hi.php @@ -1,4 +1,3 @@ "पासवरà¥à¤¡", "Help" => "सहयोग" ); diff --git a/apps/user_ldap/l10n/hr.php b/apps/user_ldap/l10n/hr.php index 005a76d4bb..9150331506 100644 --- a/apps/user_ldap/l10n/hr.php +++ b/apps/user_ldap/l10n/hr.php @@ -1,4 +1,3 @@ "Lozinka", "Help" => "Pomoć" ); diff --git a/apps/user_ldap/l10n/ia.php b/apps/user_ldap/l10n/ia.php index 38374abda7..3586bf5a2e 100644 --- a/apps/user_ldap/l10n/ia.php +++ b/apps/user_ldap/l10n/ia.php @@ -1,4 +1,3 @@ "Contrasigno", "Help" => "Adjuta" ); diff --git a/apps/user_ldap/l10n/id.php b/apps/user_ldap/l10n/id.php index 5f76d6b99f..1f6d8fcffe 100644 --- a/apps/user_ldap/l10n/id.php +++ b/apps/user_ldap/l10n/id.php @@ -3,7 +3,7 @@ "The configuration is valid and the connection could be established!" => "Konfigurasi valid dan koneksi dapat dilakukan!", "The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "Konfigurasi valid, tetapi Bind gagal. Silakan cek pengaturan server dan keamanan.", "The configuration is invalid. Please look in the ownCloud log for further details." => "Konfigurasi salah. Silakan lihat log ownCloud untuk lengkapnya.", -"Deletion failed" => "Penghapusan gagal", +"Deletion failed" => "penghapusan gagal", "Take over settings from recent server configuration?" => "Ambil alih pengaturan dari konfigurasi server saat ini?", "Keep settings?" => "Biarkan pengaturan?", "Cannot add server configuration" => "Gagal menambah konfigurasi server", @@ -15,14 +15,14 @@ "Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "Peringatan: Modul LDAP PHP tidak terpasang, perangkat tidak akan bekerja. Silakan minta administrator sistem untuk memasangnya.", "Server configuration" => "Konfigurasi server", "Add Server Configuration" => "Tambah Konfigurasi Server", -"Host" => "Host", +"Host" => "host", "You can omit the protocol, except you require SSL. Then start with ldaps://" => "Protokol dapat tidak ditulis, kecuali anda menggunakan SSL. Lalu jalankan dengan ldaps://", "Base DN" => "Base DN", "One Base DN per line" => "Satu Base DN per baris", "You can specify Base DN for users and groups in the Advanced tab" => "Anda dapat menetapkan Base DN untuk pengguna dan grup dalam tab Lanjutan", "User DN" => "User DN", "The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty." => "DN dari klien pengguna yang dengannya tautan akan diterapkan, mis. uid=agen,dc=contoh,dc=com. Untuk akses anonim, biarkan DN dan kata sandi kosong.", -"Password" => "Sandi", +"Password" => "kata kunci", "For anonymous access, leave DN and Password empty." => "Untuk akses anonim, biarkan DN dan Kata sandi kosong.", "User Login Filter" => "gunakan saringan login", "Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action." => "Definisikan filter untuk diterapkan, saat login dilakukan. %%uid menggantikan username saat login.", @@ -71,5 +71,5 @@ "User Home Folder Naming Rule" => "Aturan Penamaan Folder Home Pengguna", "Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "Biarkan nama pengguna kosong (default). Atau tetapkan atribut LDAP/AD.", "Test Configuration" => "Uji Konfigurasi", -"Help" => "Bantuan" +"Help" => "bantuan" ); diff --git a/apps/user_ldap/l10n/ku_IQ.php b/apps/user_ldap/l10n/ku_IQ.php index f8f893834b..1ae808ddd9 100644 --- a/apps/user_ldap/l10n/ku_IQ.php +++ b/apps/user_ldap/l10n/ku_IQ.php @@ -1,4 +1,3 @@ "وشەی تێپەربو", "Help" => "یارمەتی" ); diff --git a/apps/user_ldap/l10n/ms_MY.php b/apps/user_ldap/l10n/ms_MY.php index 88ed18346c..17a6cbe2cb 100644 --- a/apps/user_ldap/l10n/ms_MY.php +++ b/apps/user_ldap/l10n/ms_MY.php @@ -1,5 +1,4 @@ "Pemadaman gagal", -"Password" => "Kata laluan", "Help" => "Bantuan" ); diff --git a/apps/user_ldap/l10n/nn_NO.php b/apps/user_ldap/l10n/nn_NO.php index 1adac1b102..54d1f158f6 100644 --- a/apps/user_ldap/l10n/nn_NO.php +++ b/apps/user_ldap/l10n/nn_NO.php @@ -1,4 +1,3 @@ "Passord", "Help" => "Hjelp" ); diff --git a/apps/user_ldap/l10n/oc.php b/apps/user_ldap/l10n/oc.php index 49b6c5970c..a128638172 100644 --- a/apps/user_ldap/l10n/oc.php +++ b/apps/user_ldap/l10n/oc.php @@ -1,5 +1,4 @@ "Fracàs d'escafatge", -"Password" => "Senhal", "Help" => "Ajuda" ); diff --git a/apps/user_ldap/l10n/pl.php b/apps/user_ldap/l10n/pl.php index a5b620e48b..776aa445e4 100644 --- a/apps/user_ldap/l10n/pl.php +++ b/apps/user_ldap/l10n/pl.php @@ -3,7 +3,7 @@ "The configuration is valid and the connection could be established!" => "Konfiguracja jest prawidÅ‚owa i można ustanowić poÅ‚Ä…czenie!", "The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "Konfiguracja jest prawidÅ‚owa, ale Bind nie. Sprawdź ustawienia serwera i poÅ›wiadczenia.", "The configuration is invalid. Please look in the ownCloud log for further details." => "Konfiguracja jest nieprawidÅ‚owa. ProszÄ™ przejrzeć logi dziennika ownCloud ", -"Deletion failed" => "UsuniÄ™cie nie powiodÅ‚o siÄ™", +"Deletion failed" => "Skasowanie nie powiodÅ‚o siÄ™", "Take over settings from recent server configuration?" => "Przejmij ustawienia z ostatnich konfiguracji serwera?", "Keep settings?" => "Zachować ustawienia?", "Cannot add server configuration" => "Nie można dodać konfiguracji serwera", diff --git a/apps/user_ldap/l10n/pt_PT.php b/apps/user_ldap/l10n/pt_PT.php index 02b03d5a75..3092d06143 100644 --- a/apps/user_ldap/l10n/pt_PT.php +++ b/apps/user_ldap/l10n/pt_PT.php @@ -22,7 +22,7 @@ "You can specify Base DN for users and groups in the Advanced tab" => "Pode especificar o ND Base para utilizadores e grupos no separador Avançado", "User DN" => "DN do utilizador", "The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty." => "O DN to cliente ", -"Password" => "Password", +"Password" => "Palavra-passe", "For anonymous access, leave DN and Password empty." => "Para acesso anónimo, deixe DN e a Palavra-passe vazios.", "User Login Filter" => "Filtro de login de utilizador", "Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action." => "Define o filtro a aplicar, para aquando de uma tentativa de login. %%uid substitui o nome de utilizador utilizado.", diff --git a/apps/user_ldap/l10n/sr@latin.php b/apps/user_ldap/l10n/sr@latin.php index 005a76d4bb..9150331506 100644 --- a/apps/user_ldap/l10n/sr@latin.php +++ b/apps/user_ldap/l10n/sr@latin.php @@ -1,4 +1,3 @@ "Lozinka", "Help" => "Pomoć" ); diff --git a/apps/user_ldap/l10n/tr.php b/apps/user_ldap/l10n/tr.php index e6d450301e..7bcabb0448 100644 --- a/apps/user_ldap/l10n/tr.php +++ b/apps/user_ldap/l10n/tr.php @@ -1,49 +1,28 @@ "Uyunlama mantikli ve baglama yerlestirmek edebilmi.", -"The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "Uyunlama gecerli, fakat Baglama yapamadi. Lutfen kontrol yapmak, eger bu iyi yerlertirdi. ", -"The configuration is invalid. Please look in the ownCloud log for further details." => "Uyunma mantikli degil. Lutfen log daha kontrol yapmak. ", "Deletion failed" => "Silme baÅŸarısız oldu", -"Take over settings from recent server configuration?" => "Parametri sonadan uyunlama cikarmak mi?", "Keep settings?" => "Ayarları kalsınmı?", -"Cannot add server configuration" => "Sunucu uyunlama birlemek edemen. ", "Connection test succeeded" => "BaÄŸlantı testi baÅŸarılı oldu", "Connection test failed" => "BaÄŸlantı testi baÅŸarısız oldu", -"Do you really want to delete the current Server Configuration?" => "Hakikatten, Sonuncu Funksyon durmak istiyor mi?", "Confirm Deletion" => "Silmeyi onayla", -"Warning: Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behaviour. Please ask your system administrator to disable one of them." => "Uyari Apps kullanici_Idap ve user_webdavauth uyunmayan. Bu belki sik degil. Lutfen sistem yonetici sormak on aktif yapmaya. ", -"Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "Ihbar Modulu PHP LDAP yuklemdi degil, backend calismacak. Lutfen sistem yonetici sormak yuklemek icin.", "Host" => "Sunucu", -"You can omit the protocol, except you require SSL. Then start with ldaps://" => "Protokol atlamak edesin, sadece SSL istiyorsaniz. O zaman, idapsile baslamak. ", "Base DN" => "Ana DN", -"One Base DN per line" => "Bir Tabani DN herbir dizi. ", -"You can specify Base DN for users and groups in the Advanced tab" => "Base DN kullanicileri ve kaynaklari icin tablosu Advanced tayin etmek ederiz. ", "User DN" => "Kullanıcı DN", -"The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty." => "DN musterinin, kimle baglamaya yapacagiz,meselâ uid=agent.dc mesela, dc=com Gecinme adisiz ici, DN ve Parola bos birakmak. ", "Password" => "Parola", "For anonymous access, leave DN and Password empty." => "Anonim eriÅŸim için DN ve Parola alanlarını boÅŸ bırakın.", "User Login Filter" => "Kullanıcı Oturum Filtresi", -"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action." => "Filter uyunlamak icin tayin ediyor, ne zaman giriÅŸmek isteminiz. % % uid adi kullanici girismeye karsi koymacak. ", "use %%uid placeholder, e.g. \"uid=%%uid\"" => "%%uid yer tutucusunu kullanın, örneÄŸin \"uid=%%uid\"", "User List Filter" => "Kullanıcı Liste Filtresi", -"Defines the filter to apply, when retrieving users." => "Filter uyunmak icin tayin ediyor, ne zaman adi kullanici geri aliyor. ", "without any placeholder, e.g. \"objectClass=person\"." => "bir yer tutucusu olmadan, örneÄŸin \"objectClass=person\"", "Group Filter" => "Grup Süzgeci", -"Defines the filter to apply, when retrieving groups." => "Filter uyunmak icin tayin ediyor, ne zaman grubalari tekrar aliyor. ", -"without any placeholder, e.g. \"objectClass=posixGroup\"." => "siz bir yer tutucu, mes. 'objectClass=posixGroup ('posixGrubu''. ", "Connection Settings" => "BaÄŸlantı ayarları", "Port" => "Port", "Disable Main Server" => "Ana sunucuyu devredışı birak", "Use TLS" => "TLS kullan", "Turn off SSL certificate validation." => "SSL sertifika doÄŸrulamasını kapat.", -"If connection only works with this option, import the LDAP server's SSL certificate in your ownCloud server." => "Bagladiginda, bunla secene sadece calisiyor, sunucu LDAP SSL sunucun ithal etemek, dneyme sizine sunucu ownClouden. ", "Not recommended, use for testing only." => "Önerilmez, sadece test için kullanın.", "in seconds. A change empties the cache." => "saniye cinsinden. Bir deÄŸiÅŸiklik önbelleÄŸi temizleyecektir.", -"User Display Name Field" => "Ekran Adi Kullanici, (Alan Adi Kullanici Ekrane)", "Base User Tree" => "Temel Kullanıcı AÄŸacı", -"Group Display Name Field" => "Grub Ekrane Alani Adi", -"The LDAP attribute to use to generate the groups`s ownCloud name." => "LDAP kullamayin grub adi ownCloud uremek icin. ", "Base Group Tree" => "Temel Grup AÄŸacı", -"One Group Base DN per line" => "Bir Grubu Tabani DN her dizgi. ", "Group-Member association" => "Grup-Ãœye iÅŸbirliÄŸi", "in bytes" => "byte cinsinden", "Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "Kullanıcı adı bölümünü boÅŸ bırakın (varsayılan). ", diff --git a/core/css/styles.css b/core/css/styles.css index 93f2cecbfe..4dfa3f64a3 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -220,8 +220,6 @@ label.infield { cursor:text !important; top:1.05em; left:.85em; } } #login #databaseField .infield { padding-left:0; } #login form input[type="checkbox"]+label { position:relative; margin:0; font-size:1em; text-shadow:#fff 0 1px 0; } -#login form .errors { background:#fed7d7; border:1px solid #f00; list-style-indent:inside; margin:0 0 2em; padding:1em; } -#login .success { background:#d7fed7; border:1px solid #0f0; width: 35%; margin: 30px auto; padding:1em; text-align: center;} /* Show password toggle */ #show, #dbpassword { position:absolute; right:1em; top:.8em; float:right; } @@ -344,8 +342,8 @@ li.update, li.error { width:640px; margin:4em auto; padding:1em 1em 1em 4em; bac .center { text-align:center; } #notification-container { position: fixed; top: 0px; width: 100%; text-align: center; z-index: 101; line-height: 1.2;} -#notification, #update-notification { z-index:101; background-color:#fc4; border:0; padding:0 .7em .3em; display:none; position: relative; top:0; -moz-border-radius-bottomleft:1em; -webkit-border-bottom-left-radius:1em; border-bottom-left-radius:1em; -moz-border-radius-bottomright:1em; -webkit-border-bottom-right-radius:1em; border-bottom-right-radius:1em; } -#notification span, #update-notification span { cursor:pointer; font-weight:bold; margin-left:1em; } +#notification { z-index:101; background-color:#fc4; border:0; padding:0 .7em .3em; display:none; position: relative; top:0; -moz-border-radius-bottomleft:1em; -webkit-border-bottom-left-radius:1em; border-bottom-left-radius:1em; -moz-border-radius-bottomright:1em; -webkit-border-bottom-right-radius:1em; border-bottom-right-radius:1em; } +#notification span { cursor:pointer; font-weight:bold; margin-left:1em; } tr .action:not(.permanent), .selectedActions a { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0; } tr:hover .action, tr .action.permanent, .selectedActions a { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; filter:alpha(opacity=50); opacity:.5; } diff --git a/core/js/jquery-showpassword.js b/core/js/jquery-showpassword.js index e1737643b4..0f4678327a 100644 --- a/core/js/jquery-showpassword.js +++ b/core/js/jquery-showpassword.js @@ -35,8 +35,7 @@ 'style' : $element.attr('style'), 'size' : $element.attr('size'), 'name' : $element.attr('name')+'-clone', - 'tabindex' : $element.attr('tabindex'), - 'autocomplete' : 'off' + 'tabindex' : $element.attr('tabindex') }); return $clone; @@ -103,16 +102,7 @@ $clone.bind('blur', function() { $input.trigger('focusout'); }); setState( $checkbox, $input, $clone ); - - // set type of password field clone (type=text) to password right on submit - // to prevent browser save the value of this field - $clone.closest('form').submit(function(e) { - // .prop has to be used, because .attr throws - // an error while changing a type of an input - // element - $clone.prop('type', 'password'); - }); - + if( callback.fn ){ callback.fn( callback.args ); } diff --git a/core/l10n/ar.php b/core/l10n/ar.php index 587e59695c..4d413715de 100644 --- a/core/l10n/ar.php +++ b/core/l10n/ar.php @@ -30,7 +30,7 @@ "October" => "تشرين الاول", "November" => "تشرين الثاني", "December" => "كانون الاول", -"Settings" => "إعدادات", +"Settings" => "تعديلات", "seconds ago" => "منذ ثواني", "1 minute ago" => "منذ دقيقة", "{minutes} minutes ago" => "{minutes} منذ دقائق", @@ -63,7 +63,7 @@ "Share with" => "شارك مع", "Share with link" => "شارك مع رابط", "Password protect" => "حماية كلمة السر", -"Password" => "كلمة المرور", +"Password" => "كلمة السر", "Email link to person" => "ارسل الرابط بالبريد الى صديق", "Send" => "أرسل", "Set expiration date" => "تعيين تاريخ إنتهاء الصلاحية", @@ -89,21 +89,23 @@ "ownCloud password reset" => "إعادة تعيين كلمة سر ownCloud", "Use the following link to reset your password: {link}" => "استخدم هذه الوصلة لاسترجاع كلمة السر: {link}", "You will receive a link to reset your password via Email." => "سو٠نرسل لك بريد يحتوي على وصلة لتجديد كلمة السر.", +"Reset email send." => "إعادة إرسال البريد الإلكتروني.", +"Request failed!" => "Ùشل الطلب", "Username" => "إسم المستخدم", "Request reset" => "طلب تعديل", "Your password was reset" => "لقد تم تعديل كلمة السر", "To login page" => "الى صÙحة الدخول", -"New password" => "كلمات سر جديدة", +"New password" => "كلمة سر جديدة", "Reset password" => "تعديل كلمة السر", -"Personal" => "شخصي", -"Users" => "المستخدمين", +"Personal" => "خصوصيات", +"Users" => "المستخدم", "Apps" => "التطبيقات", -"Admin" => "المدير", +"Admin" => "مستخدم رئيسي", "Help" => "المساعدة", "Access forbidden" => "التوصّل محظور", "Cloud not found" => "لم يتم إيجاد", "Edit categories" => "عدل الÙئات", -"Add" => "اضÙ", +"Add" => "أدخل", "Security Warning" => "تحذير أمان", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)", "Please update your PHP installation to use ownCloud securely." => "Please update your PHP installation to use ownCloud securely.", @@ -112,7 +114,7 @@ "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "مجلدات البيانات والملÙات الخاصة قد تكون قابلة للوصول اليها عن طريق شبكة الانترنت وذلك بسبب ان مل٠.htaccess لا يعمل بشكل صحيح.", "For information how to properly configure your server, please see the documentation." => "للحصول على معلومات عن كيÙية اعداد الخادم الخاص بك , يرجى زيارة الرابط التالي documentation.", "Create an admin account" => "أض٠مستخدم رئيسي ", -"Advanced" => "تعديلات متقدمه", +"Advanced" => "خيارات متقدمة", "Data folder" => "مجلد المعلومات", "Configure the database" => "أسس قاعدة البيانات", "will be used" => "سيتم استخدمه", @@ -122,7 +124,7 @@ "Database tablespace" => "مساحة جدول قاعدة البيانات", "Database host" => "خادم قاعدة البيانات", "Finish setup" => "انهاء التعديلات", -"web services under your control" => "خدمات الشبكة تحت سيطرتك", +"web services under your control" => "خدمات الوب تحت تصرÙÙƒ", "Log out" => "الخروج", "Automatic logon rejected!" => "تم رÙض تسجيل الدخول التلقائي!", "If you did not change your password recently, your account may be compromised!" => "قد يكون حسابك ÙÙŠ خطر إن لم تقم بإعادة تعيين كلمة السر حديثاً", diff --git a/core/l10n/bg_BG.php b/core/l10n/bg_BG.php index 74e28bf290..dadb570d93 100644 --- a/core/l10n/bg_BG.php +++ b/core/l10n/bg_BG.php @@ -1,24 +1,4 @@ "ÐÑма избрани категории за изтриване", -"Sunday" => "ÐеделÑ", -"Monday" => "Понеделник", -"Tuesday" => "Вторник", -"Wednesday" => "СрÑда", -"Thursday" => "Четвъртък", -"Friday" => "Петък", -"Saturday" => "Събота", -"January" => "Януари", -"February" => "Февруари", -"March" => "Март", -"April" => "Ðприл", -"May" => "Май", -"June" => "Юни", -"July" => "Юли", -"August" => "ÐвгуÑÑ‚", -"September" => "Септември", -"October" => "Октомври", -"November" => "Ðоември", -"December" => "Декември", "Settings" => "ÐаÑтройки", "seconds ago" => "преди Ñекунди", "1 minute ago" => "преди 1 минута", @@ -28,45 +8,16 @@ "last month" => "поÑледниÑÑ‚ меÑец", "last year" => "поÑледната година", "years ago" => "поÑледните години", -"Ok" => "Добре", "Cancel" => "Отказ", -"Yes" => "Да", -"No" => "Ðе", "Error" => "Грешка", "Share" => "СподелÑне", -"Share with" => "Споделено Ñ", "Password" => "Парола", -"create" => "Ñъздаване", -"You will receive a link to reset your password via Email." => "Ще получите връзка за нулиране на паролата Ви.", -"Username" => "Потребител", -"Request reset" => "Ðулиране на заÑвка", -"Your password was reset" => "Вашата парола е нулирана", "New password" => "Ðова парола", -"Reset password" => "Ðулиране на парола", "Personal" => "Лични", "Users" => "Потребители", "Apps" => "ПриложениÑ", "Admin" => "Ðдмин", "Help" => "Помощ", -"Access forbidden" => "ДоÑтъпът е забранен", -"Cloud not found" => "облакът не намерен", -"Edit categories" => "Редактиране на категориите", "Add" => "ДобавÑне", -"Create an admin account" => "Създаване на админ профил", -"Advanced" => "Разширено", -"Data folder" => "Ð”Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð·Ð° данни", -"Configure the database" => "Конфигуриране на базата", -"will be used" => "ще Ñе ползва", -"Database user" => "Потребител за базата", -"Database password" => "Парола за базата", -"Database name" => "Име на базата", -"Database host" => "ХоÑÑ‚ за базата", -"Finish setup" => "Завършване на наÑтройките", -"web services under your control" => "уеб уÑлуги под Ваш контрол", -"Log out" => "Изход", -"Lost your password?" => "Забравена парола?", -"remember" => "запомни", -"Log in" => "Вход", -"prev" => "пред.", -"next" => "Ñледващо" +"web services under your control" => "уеб уÑлуги под Ваш контрол" ); diff --git a/core/l10n/bn_BD.php b/core/l10n/bn_BD.php index 63a80edad3..1b18b6ae3e 100644 --- a/core/l10n/bn_BD.php +++ b/core/l10n/bn_BD.php @@ -8,13 +8,13 @@ "Object type not provided." => "অবজেকà§à¦Ÿà§‡à¦° ধরণটি পà§à¦°à¦¦à¦¾à¦¨ করা হয় নি।", "%s ID not provided." => "%s ID পà§à¦°à¦¦à¦¾à¦¨ করা হয় নি।", "Error adding %s to favorites." => "পà§à¦°à¦¿à§Ÿà¦¤à§‡ %s যোগ করতে সমসà§à¦¯à¦¾ দেখা দিয়েছে।", -"No categories selected for deletion." => "মà§à¦›à§‡ ফেলার জনà§à¦¯ কনো কà§à¦¯à¦¾à¦Ÿà§‡à¦—রি নিরà§à¦¬à¦¾à¦šà¦¨ করা হয় নি।", +"No categories selected for deletion." => "মà§à¦›à§‡ ফেলার জনà§à¦¯ কোন কà§à¦¯à¦¾à¦Ÿà§‡à¦—রি নিরà§à¦¬à¦¾à¦šà¦¨ করা হয় নি ।", "Error removing %s from favorites." => "পà§à¦°à¦¿à§Ÿ থেকে %s সরিয়ে ফেলতে সমসà§à¦¯à¦¾ দেখা দিয়েছে।", "Sunday" => "রবিবার", "Monday" => "সোমবার", "Tuesday" => "মঙà§à¦—লবার", "Wednesday" => "বà§à¦§à¦¬à¦¾à¦°", -"Thursday" => "বৃহসà§à¦ªà¦¤à¦¿à¦¬à¦¾à¦°", +"Thursday" => "বৃহষà§à¦ªà¦¤à¦¿à¦¬à¦¾à¦°", "Friday" => "শà§à¦•à§à¦°à¦¬à¦¾à¦°", "Saturday" => "শনিবার", "January" => "জানà§à§Ÿà¦¾à¦°à¦¿", @@ -31,14 +31,14 @@ "December" => "ডিসেমà§à¦¬à¦°", "Settings" => "নিয়ামকসমূহ", "seconds ago" => "সেকেনà§à¦¡ পূরà§à¦¬à§‡", -"1 minute ago" => "১ মিনিট পূরà§à¦¬à§‡", +"1 minute ago" => "1 মিনিট পূরà§à¦¬à§‡", "{minutes} minutes ago" => "{minutes} মিনিট পূরà§à¦¬à§‡", "1 hour ago" => "1 ঘনà§à¦Ÿà¦¾ পূরà§à¦¬à§‡", "{hours} hours ago" => "{hours} ঘনà§à¦Ÿà¦¾ পূরà§à¦¬à§‡", "today" => "আজ", "yesterday" => "গতকাল", "{days} days ago" => "{days} দিন পূরà§à¦¬à§‡", -"last month" => "গত মাস", +"last month" => "গতমাস", "{months} months ago" => "{months} মাস পূরà§à¦¬à§‡", "months ago" => "মাস পূরà§à¦¬à§‡", "last year" => "গত বছর", @@ -71,7 +71,7 @@ "No people found" => "কোন বà§à¦¯à¦•à§à¦¤à¦¿ খà§à¦à¦œà§‡ পাওয়া গেল না", "Resharing is not allowed" => "পূনঃরায় ভাগাভাগি অনà§à¦®à§‹à¦¦à¦¿à¦¤ নয়", "Shared in {item} with {user}" => "{user} à¦à¦° সাথে {item} ভাগাভাগি করা হয়েছে", -"Unshare" => "ভাগাভাগি বাতিল ", +"Unshare" => "ভাগাভাগি বাতিল কর", "can edit" => "সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ করতে পারবেন", "access control" => "অধিগমà§à¦¯à¦¤à¦¾ নিয়নà§à¦¤à§à¦°à¦£", "create" => "তৈরী করà§à¦¨", @@ -86,6 +86,8 @@ "ownCloud password reset" => "ownCloud কূটশবà§à¦¦ পূনঃনিরà§à¦§à¦¾à¦°à¦£", "Use the following link to reset your password: {link}" => "আপনার কূটশবà§à¦¦à¦Ÿà¦¿ পূনঃনিরà§à¦§à¦¾à¦°à¦£ করার জনà§à¦¯ নিমà§à¦¨à§‹à¦•à§à¦¤ লিংকটি বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨à¦ƒ {link}", "You will receive a link to reset your password via Email." => "কূটশবà§à¦¦ পূনঃনিরà§à¦§à¦¾à¦°à¦£à§‡à¦° জনà§à¦¯ à¦à¦•à¦Ÿà¦¿ টূনঃনিরà§à¦§à¦¾à¦°à¦£ লিংকটি আপনাকে ই-মেইলে পাঠানো হয়েছে ।", +"Reset email send." => "পূনঃনিরà§à¦§à¦¾à¦°à¦£ ই-মেইল পাঠানো হয়েছে।", +"Request failed!" => "অনà§à¦°à§‹à¦§ বà§à¦¯à¦°à§à¦¥ !", "Username" => "বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€", "Request reset" => "অনà§à¦°à§‹à¦§ পূনঃনিরà§à¦§à¦¾à¦°à¦£", "Your password was reset" => "আপনার কূটশবà§à¦¦à¦Ÿà¦¿ পূনঃনিরà§à¦§à¦¾à¦°à¦£ করা হয়েছে", @@ -94,7 +96,7 @@ "Reset password" => "কূটশবà§à¦¦ পূনঃনিরà§à¦§à¦¾à¦°à¦£ কর", "Personal" => "বà§à¦¯à¦•à§à¦¤à¦¿à¦—ত", "Users" => "বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€", -"Apps" => "অà§à¦¯à¦¾à¦ª", +"Apps" => "অà§à¦¯à¦¾à¦ªà¦¸", "Admin" => "পà§à¦°à¦¶à¦¾à¦¸à¦¨", "Help" => "সহায়িকা", "Access forbidden" => "অধিগমনের অনà§à¦®à¦¤à¦¿ নেই", @@ -113,7 +115,7 @@ "Database tablespace" => "ডাটাবেজ টেবলসà§à¦ªà§‡à¦¸", "Database host" => "ডাটাবেজ হোসà§à¦Ÿ", "Finish setup" => "সেটআপ সà§à¦¸à¦®à§à¦ªà¦¨à§à¦¨ কর", -"web services under your control" => "ওয়েব সারà§à¦­à¦¿à¦¸ আপনার হাতের মà§à¦ à§‹à§Ÿ", +"web services under your control" => "ওয়েব সারà§à¦­à¦¿à¦¸à§‡à¦° নিয়নà§à¦¤à§à¦°à¦£ আপনার হাতের মà§à¦ à§‹à§Ÿ", "Log out" => "পà§à¦°à¦¸à§à¦¥à¦¾à¦¨", "Lost your password?" => "কূটশবà§à¦¦ হারিয়েছেন?", "remember" => "মনে রাখ", diff --git a/core/l10n/ca.php b/core/l10n/ca.php index 818c5b20b9..91b51d1b31 100644 --- a/core/l10n/ca.php +++ b/core/l10n/ca.php @@ -30,7 +30,7 @@ "October" => "Octubre", "November" => "Novembre", "December" => "Desembre", -"Settings" => "Configuració", +"Settings" => "Arranjament", "seconds ago" => "segons enrere", "1 minute ago" => "fa 1 minut", "{minutes} minutes ago" => "fa {minutes} minuts", @@ -89,6 +89,8 @@ "ownCloud password reset" => "estableix de nou la contrasenya Owncloud", "Use the following link to reset your password: {link}" => "Useu l'enllaç següent per restablir la contrasenya: {link}", "You will receive a link to reset your password via Email." => "Rebreu un enllaç al correu electrònic per reiniciar la contrasenya.", +"Reset email send." => "S'ha enviat el correu reinicialització", +"Request failed!" => "El requeriment ha fallat!", "Username" => "Nom d'usuari", "Request reset" => "Sol·licita reinicialització", "Your password was reset" => "La vostra contrasenya s'ha reinicialitzat", @@ -98,7 +100,7 @@ "Personal" => "Personal", "Users" => "Usuaris", "Apps" => "Aplicacions", -"Admin" => "Administració", +"Admin" => "Administrador", "Help" => "Ajuda", "Access forbidden" => "Accés prohibit", "Cloud not found" => "No s'ha trobat el núvol", diff --git a/core/l10n/cs_CZ.php b/core/l10n/cs_CZ.php index 47206be618..15c89106e5 100644 --- a/core/l10n/cs_CZ.php +++ b/core/l10n/cs_CZ.php @@ -88,9 +88,9 @@ "The update was successful. Redirecting you to ownCloud now." => "Aktualizace byla úspěšná. PÅ™esmÄ›rovávám na ownCloud.", "ownCloud password reset" => "Obnovení hesla pro ownCloud", "Use the following link to reset your password: {link}" => "Heslo obnovíte použitím následujícího odkazu: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "Odkaz na obnovení hesla byl odeslán na vaši e-mailovou adresu.
Pokud jej v krátké době neobdržíte, zkontrolujte váš koš a složku spam.
Pokud jej nenaleznete, kontaktujte svého správce.", -"Request failed!
Did you make sure your email/username was right?" => "Požadavek selhal.
Ujistili jste se, že vaÅ¡e uživatelské jméno a e-mail jsou správnÄ›?", "You will receive a link to reset your password via Email." => "Bude Vám e-mailem zaslán odkaz pro obnovu hesla.", +"Reset email send." => "Obnovovací e-mail odeslán.", +"Request failed!" => "Požadavek selhal.", "Username" => "Uživatelské jméno", "Request reset" => "Vyžádat obnovu", "Your password was reset" => "VaÅ¡e heslo bylo obnoveno", @@ -124,7 +124,7 @@ "Database tablespace" => "Tabulkový prostor databáze", "Database host" => "Hostitel databáze", "Finish setup" => "DokonÄit nastavení", -"web services under your control" => "služby webu pod Vaší kontrolou", +"web services under your control" => "webové služby pod Vaší kontrolou", "Log out" => "Odhlásit se", "Automatic logon rejected!" => "Automatické pÅ™ihlášení odmítnuto.", "If you did not change your password recently, your account may be compromised!" => "V nedávné dobÄ› jste nezmÄ›nili své heslo, Váš úÄet může být kompromitován.", diff --git a/core/l10n/cy_GB.php b/core/l10n/cy_GB.php index d614797eb6..4d28ae29a9 100644 --- a/core/l10n/cy_GB.php +++ b/core/l10n/cy_GB.php @@ -89,6 +89,8 @@ "ownCloud password reset" => "ailosod cyfrinair ownCloud", "Use the following link to reset your password: {link}" => "Defnyddiwch y ddolen hon i ailosod eich cyfrinair: {link}", "You will receive a link to reset your password via Email." => "Byddwch yn derbyn dolen drwy e-bost i ailosod eich cyfrinair.", +"Reset email send." => "Ailosod anfon e-bost.", +"Request failed!" => "Methodd y cais!", "Username" => "Enw defnyddiwr", "Request reset" => "Gwneud cais i ailosod", "Your password was reset" => "Ailosodwyd eich cyfrinair", diff --git a/core/l10n/da.php b/core/l10n/da.php index 43b2f4f840..286f524b67 100644 --- a/core/l10n/da.php +++ b/core/l10n/da.php @@ -45,7 +45,7 @@ "last year" => "sidste Ã¥r", "years ago" => "Ã¥r siden", "Ok" => "OK", -"Cancel" => "Annuller", +"Cancel" => "Fortryd", "Choose" => "Vælg", "Yes" => "Ja", "No" => "Nej", @@ -89,13 +89,15 @@ "ownCloud password reset" => "Nulstil ownCloud kodeord", "Use the following link to reset your password: {link}" => "Anvend følgende link til at nulstille din adgangskode: {link}", "You will receive a link to reset your password via Email." => "Du vil modtage et link til at nulstille dit kodeord via email.", +"Reset email send." => "Reset-mail afsendt.", +"Request failed!" => "Anmodningen mislykkedes!", "Username" => "Brugernavn", "Request reset" => "Anmod om nulstilling", "Your password was reset" => "Dit kodeord blev nulstillet", "To login page" => "Til login-side", "New password" => "Nyt kodeord", "Reset password" => "Nulstil kodeord", -"Personal" => "Personligt", +"Personal" => "Personlig", "Users" => "Brugere", "Apps" => "Apps", "Admin" => "Admin", diff --git a/core/l10n/de.php b/core/l10n/de.php index c173e56c1f..3af653b9ac 100644 --- a/core/l10n/de.php +++ b/core/l10n/de.php @@ -88,9 +88,9 @@ "The update was successful. Redirecting you to ownCloud now." => "Das Update war erfolgreich. Sie werden nun zu ownCloud weitergeleitet.", "ownCloud password reset" => "ownCloud-Passwort zurücksetzen", "Use the following link to reset your password: {link}" => "Nutze den nachfolgenden Link, um Dein Passwort zurückzusetzen: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "Der Link zum Rücksetzen Deines Passwort ist an Deine E-Mail-Adresse geschickt worden.
Wenn Du ihn nicht innerhalb einer vernünftigen Zeit empfängst prüfe Deine Spam-Verzeichnisse.
Wenn er nicht dort ist frage Deinen lokalen Administrator.", -"Request failed!
Did you make sure your email/username was right?" => "Anfrage fehlgeschlagen!
Hast Du darauf geachtet, dass Deine E-Mail/Dein Benutzername korrekt war?", "You will receive a link to reset your password via Email." => "Du erhältst einen Link per E-Mail, um Dein Passwort zurückzusetzen.", +"Reset email send." => "Die E-Mail zum Zurücksetzen wurde versendet.", +"Request failed!" => "Die Anfrage schlug fehl!", "Username" => "Benutzername", "Request reset" => "Beantrage Zurücksetzung", "Your password was reset" => "Dein Passwort wurde zurückgesetzt.", @@ -99,8 +99,8 @@ "Reset password" => "Passwort zurücksetzen", "Personal" => "Persönlich", "Users" => "Benutzer", -"Apps" => "Apps", -"Admin" => "Administration", +"Apps" => "Anwendungen", +"Admin" => "Admin", "Help" => "Hilfe", "Access forbidden" => "Zugriff verboten", "Cloud not found" => "Cloud nicht gefunden", @@ -124,7 +124,7 @@ "Database tablespace" => "Datenbank-Tablespace", "Database host" => "Datenbank-Host", "Finish setup" => "Installation abschließen", -"web services under your control" => "Web-Services unter Deiner Kontrolle", +"web services under your control" => "Web-Services unter Ihrer Kontrolle", "Log out" => "Abmelden", "Automatic logon rejected!" => "Automatischer Login zurückgewiesen!", "If you did not change your password recently, your account may be compromised!" => "Wenn Du Dein Passwort nicht vor kurzem geändert hast, könnte Dein\nAccount kompromittiert sein!", diff --git a/core/l10n/de_DE.php b/core/l10n/de_DE.php index b69868e5e5..4065f2484f 100644 --- a/core/l10n/de_DE.php +++ b/core/l10n/de_DE.php @@ -43,7 +43,7 @@ "{months} months ago" => "Vor {months} Monaten", "months ago" => "Vor Monaten", "last year" => "Letztes Jahr", -"years ago" => "Vor Jahren", +"years ago" => "Vor Jahren", "Ok" => "OK", "Cancel" => "Abbrechen", "Choose" => "Auswählen", @@ -88,9 +88,9 @@ "The update was successful. Redirecting you to ownCloud now." => "Das Update war erfolgreich. Sie werden nun zu ownCloud weitergeleitet.", "ownCloud password reset" => "ownCloud-Passwort zurücksetzen", "Use the following link to reset your password: {link}" => "Nutzen Sie den nachfolgenden Link, um Ihr Passwort zurückzusetzen: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "Der Link zum Rücksetzen Ihres Passworts ist an Ihre E-Mail-Adresse gesendet worde.
Wenn Sie ihn nicht innerhalb einer sinnvollen Zeitspanne erhalten prüfen Sie bitte Ihre Spam-Verzeichnisse.
Wenn er nicht dort ist fragen Sie Ihren lokalen Administrator.", -"Request failed!
Did you make sure your email/username was right?" => "Anfrage fehlgeschlagen!
Haben Sie darauf geachtet, dass E-Mail-Adresse/Nutzername korrekt waren?", "You will receive a link to reset your password via Email." => "Sie erhalten einen Link per E-Mail, um Ihr Passwort zurückzusetzen.", +"Reset email send." => "Eine E-Mail zum Zurücksetzen des Passworts wurde gesendet.", +"Request failed!" => "Die Anfrage schlug fehl!", "Username" => "Benutzername", "Request reset" => "Zurücksetzung beantragen", "Your password was reset" => "Ihr Passwort wurde zurückgesetzt.", @@ -99,12 +99,12 @@ "Reset password" => "Passwort zurücksetzen", "Personal" => "Persönlich", "Users" => "Benutzer", -"Apps" => "Apps", -"Admin" => "Administrator", +"Apps" => "Anwendungen", +"Admin" => "Admin", "Help" => "Hilfe", "Access forbidden" => "Zugriff verboten", "Cloud not found" => "Cloud wurde nicht gefunden", -"Edit categories" => "Kategorien ändern", +"Edit categories" => "Kategorien bearbeiten", "Add" => "Hinzufügen", "Security Warning" => "Sicherheitshinweis", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "Ihre PHP Version ist durch die NULL Byte Attacke (CVE-2006-7243) angreifbar", diff --git a/core/l10n/el.php b/core/l10n/el.php index dbe0d0ee3d..4fc5b4aa86 100644 --- a/core/l10n/el.php +++ b/core/l10n/el.php @@ -88,10 +88,10 @@ "The update was successful. Redirecting you to ownCloud now." => "Η ενημέÏωση ήταν επιτυχής. Μετάβαση στο ownCloud.", "ownCloud password reset" => "ΕπαναφοÏά ÏƒÏ…Î½Î¸Î·Î¼Î±Ï„Î¹ÎºÎ¿Ï ownCloud", "Use the following link to reset your password: {link}" => "ΧÏησιμοποιήστε τον ακόλουθο σÏνδεσμο για να επανεκδόσετε τον κωδικό: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "Ο σÏνδεσμος για να επανακτήσετε τον κωδικό σας έχει σταλεί στο email
αν δεν το λάβετε μέσα σε οÏισμένο διάστημα, ελέγξετε τους φακελλους σας spam/junk
αν δεν είναι εκεί Ïωτήστε τον τοπικό σας διαχειÏιστή ", -"Request failed!
Did you make sure your email/username was right?" => "Η αίτηση απέτυχε! Βεβαιωθηκατε ότι το email σας / username ειναι σωστο? ", "You will receive a link to reset your password via Email." => "Θα λάβετε ένα σÏνδεσμο για να επαναφέÏετε τον κωδικό Ï€Ïόσβασής σας μέσω ηλεκτÏÎ¿Î½Î¹ÎºÎ¿Ï Ï„Î±Ï‡Ï…Î´Ïομείου.", -"Username" => "Όνομα χÏήστη", +"Reset email send." => "Η επαναφοÏά του email στάλθηκε.", +"Request failed!" => "Η αίτηση απέτυχε!", +"Username" => "Όνομα ΧÏήστη", "Request reset" => "ΕπαναφοÏά αίτησης", "Your password was reset" => "Ο κωδικός Ï€Ïόσβασής σας επαναφέÏθηκε", "To login page" => "Σελίδα εισόδου", @@ -124,7 +124,7 @@ "Database tablespace" => "Κενά Πινάκων Βάσης Δεδομένων", "Database host" => "Διακομιστής βάσης δεδομένων", "Finish setup" => "ΟλοκλήÏωση εγκατάστασης", -"web services under your control" => "υπηÏεσίες δικτÏου υπό τον έλεγχό σας", +"web services under your control" => "ΥπηÏεσίες web υπό τον έλεγχό σας", "Log out" => "ΑποσÏνδεση", "Automatic logon rejected!" => "ΑποÏÏίφθηκε η αυτόματη σÏνδεση!", "If you did not change your password recently, your account may be compromised!" => "Εάν δεν αλλάξατε το συνθηματικό σας Ï€Ïοσφάτως, ο λογαÏιασμός μποÏεί να έχει διαÏÏεÏσει!", diff --git a/core/l10n/eo.php b/core/l10n/eo.php index 1889de1ea2..5c8fe34031 100644 --- a/core/l10n/eo.php +++ b/core/l10n/eo.php @@ -85,6 +85,7 @@ "ownCloud password reset" => "La pasvorto de ownCloud restariÄis.", "Use the following link to reset your password: {link}" => "Uzu la jenan ligilon por restarigi vian pasvorton: {link}", "You will receive a link to reset your password via Email." => "Vi ricevos ligilon retpoÅte por rekomencigi vian pasvorton.", +"Request failed!" => "Peto malsukcesis!", "Username" => "Uzantonomo", "Request reset" => "Peti rekomencigon", "Your password was reset" => "Via pasvorto rekomencis", @@ -113,7 +114,7 @@ "Database tablespace" => "Datumbaza tabelospaco", "Database host" => "Datumbaza gastigo", "Finish setup" => "Fini la instalon", -"web services under your control" => "TTT-servoj regataj de vi", +"web services under your control" => "TTT-servoj sub via kontrolo", "Log out" => "Elsaluti", "If you did not change your password recently, your account may be compromised!" => "Se vi ne ÅanÄis vian pasvorton lastatempe, via konto eble kompromitas!", "Please change your password to secure your account again." => "Bonvolu ÅanÄi vian pasvorton por sekurigi vian konton ree.", diff --git a/core/l10n/es.php b/core/l10n/es.php index 8a3ab44e85..543563bed1 100644 --- a/core/l10n/es.php +++ b/core/l10n/es.php @@ -50,7 +50,7 @@ "Yes" => "Sí", "No" => "No", "The object type is not specified." => "El tipo de objeto no se ha especificado.", -"Error" => "Error", +"Error" => "Fallo", "The app name is not specified." => "El nombre de la app no se ha especificado.", "The required file {file} is not installed!" => "El fichero {file} requerido, no está instalado.", "Shared" => "Compartido", @@ -88,9 +88,9 @@ "The update was successful. Redirecting you to ownCloud now." => "La actualización se ha realizado correctamente. Redireccionando a ownCloud ahora.", "ownCloud password reset" => "Reiniciar contraseña de ownCloud", "Use the following link to reset your password: {link}" => "Utiliza el siguiente enlace para restablecer tu contraseña: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "El enlace para restablecer la contraseña ha sido enviada a su correo electrónico.
Si no lo recibe en un plazo razonable de tiempo, revise su spam / carpetas no deseados.
Si no está allí pregunte a su administrador local.", -"Request failed!
Did you make sure your email/username was right?" => "Petición ha fallado!
¿Usted asegúrese que su dirección de correo electrónico / nombre de usuario estaba justo?", "You will receive a link to reset your password via Email." => "Recibirás un enlace por correo electrónico para restablecer tu contraseña", +"Reset email send." => "Email de reconfiguración enviado.", +"Request failed!" => "Pedido fallado!", "Username" => "Nombre de usuario", "Request reset" => "Solicitar restablecimiento", "Your password was reset" => "Tu contraseña se ha restablecido", @@ -100,12 +100,12 @@ "Personal" => "Personal", "Users" => "Usuarios", "Apps" => "Aplicaciones", -"Admin" => "Administración", +"Admin" => "Administrador", "Help" => "Ayuda", "Access forbidden" => "Acceso denegado", "Cloud not found" => "No se ha encontrado la nube", "Edit categories" => "Editar categorías", -"Add" => "Agregar", +"Add" => "Añadir", "Security Warning" => "Advertencia de seguridad", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "La versión de PHP es vulnerable al ataque de Byte NULL (CVE-2006-7243)", "Please update your PHP installation to use ownCloud securely." => "Por favor, actualice su instalación de PHP para utilizar ownCloud en forma segura.", @@ -124,7 +124,7 @@ "Database tablespace" => "Espacio de tablas de la base de datos", "Database host" => "Host de la base de datos", "Finish setup" => "Completar la instalación", -"web services under your control" => "Servicios web bajo su control", +"web services under your control" => "servicios web bajo tu control", "Log out" => "Salir", "Automatic logon rejected!" => "¡Inicio de sesión automático rechazado!", "If you did not change your password recently, your account may be compromised!" => "Si usted no ha cambiado su contraseña recientemente, ¡puede que su cuenta esté comprometida!", diff --git a/core/l10n/es_AR.php b/core/l10n/es_AR.php index 8f77843708..748de3ddd1 100644 --- a/core/l10n/es_AR.php +++ b/core/l10n/es_AR.php @@ -9,7 +9,7 @@ "Object type not provided." => "Tipo de objeto no provisto. ", "%s ID not provided." => "%s ID no provista. ", "Error adding %s to favorites." => "Error al agregar %s a favoritos. ", -"No categories selected for deletion." => "No se seleccionaron categorías para borrar.", +"No categories selected for deletion." => "No hay categorías seleccionadas para borrar.", "Error removing %s from favorites." => "Error al remover %s de favoritos. ", "Sunday" => "Domingo", "Monday" => "Lunes", @@ -18,23 +18,23 @@ "Thursday" => "Jueves", "Friday" => "Viernes", "Saturday" => "Sábado", -"January" => "enero", -"February" => "febrero", -"March" => "marzo", -"April" => "abril", -"May" => "mayo", -"June" => "junio", -"July" => "julio", -"August" => "agosto", -"September" => "septiembre", -"October" => "octubre", -"November" => "noviembre", -"December" => "diciembre", -"Settings" => "Configuración", +"January" => "Enero", +"February" => "Febrero", +"March" => "Marzo", +"April" => "Abril", +"May" => "Mayo", +"June" => "Junio", +"July" => "Julio", +"August" => "Agosto", +"September" => "Septiembre", +"October" => "Octubre", +"November" => "Noviembre", +"December" => "Diciembre", +"Settings" => "Ajustes", "seconds ago" => "segundos atrás", "1 minute ago" => "hace 1 minuto", "{minutes} minutes ago" => "hace {minutes} minutos", -"1 hour ago" => "1 hora atrás", +"1 hour ago" => "Hace 1 hora", "{hours} hours ago" => "{hours} horas atrás", "today" => "hoy", "yesterday" => "ayer", @@ -72,7 +72,7 @@ "No people found" => "No se encontraron usuarios", "Resharing is not allowed" => "No se permite volver a compartir", "Shared in {item} with {user}" => "Compartido en {item} con {user}", -"Unshare" => "Dejar de compartir", +"Unshare" => "Remover compartir", "can edit" => "puede editar", "access control" => "control de acceso", "create" => "crear", @@ -89,16 +89,18 @@ "ownCloud password reset" => "Restablecer contraseña de ownCloud", "Use the following link to reset your password: {link}" => "Usá este enlace para restablecer tu contraseña: {link}", "You will receive a link to reset your password via Email." => "Vas a recibir un enlace por e-mail para restablecer tu contraseña", +"Reset email send." => "Reiniciar envío de email.", +"Request failed!" => "Error en el pedido!", "Username" => "Nombre de usuario", "Request reset" => "Solicitar restablecimiento", "Your password was reset" => "Tu contraseña fue restablecida", "To login page" => "A la página de inicio de sesión", -"New password" => "Nueva contraseña:", +"New password" => "Nueva contraseña", "Reset password" => "Restablecer contraseña", "Personal" => "Personal", "Users" => "Usuarios", "Apps" => "Aplicaciones", -"Admin" => "Administración", +"Admin" => "Administrador", "Help" => "Ayuda", "Access forbidden" => "Acceso denegado", "Cloud not found" => "No se encontró ownCloud", @@ -122,7 +124,7 @@ "Database tablespace" => "Espacio de tablas de la base de datos", "Database host" => "Host de la base de datos", "Finish setup" => "Completar la instalación", -"web services under your control" => "servicios web controlados por vos", +"web services under your control" => "servicios web sobre los que tenés control", "Log out" => "Cerrar la sesión", "Automatic logon rejected!" => "¡El inicio de sesión automático fue rechazado!", "If you did not change your password recently, your account may be compromised!" => "¡Si no cambiaste tu contraseña recientemente, puede ser que tu cuenta esté comprometida!", diff --git a/core/l10n/et_EE.php b/core/l10n/et_EE.php index aac3898fbb..b6b6d4c9d9 100644 --- a/core/l10n/et_EE.php +++ b/core/l10n/et_EE.php @@ -88,22 +88,23 @@ "The update was successful. Redirecting you to ownCloud now." => "Uuendus oli edukas. Kohe suunatakse Sind ownCloudi.", "ownCloud password reset" => "ownCloud parooli taastamine", "Use the following link to reset your password: {link}" => "Kasuta järgnevat linki oma parooli taastamiseks: {link}", -"Request failed!
Did you make sure your email/username was right?" => "Päring ebaõnnestus!
Oled sa veendunud, et e-post/kasutajanimi on õiged?", "You will receive a link to reset your password via Email." => "Sinu parooli taastamise link saadetakse sulle e-postile.", +"Reset email send." => "Taastamise e-kiri on saadetud.", +"Request failed!" => "Päring ebaõnnestus!", "Username" => "Kasutajanimi", "Request reset" => "Päringu taastamine", "Your password was reset" => "Sinu parool on taastatud", "To login page" => "Sisselogimise lehele", "New password" => "Uus parool", "Reset password" => "Nulli parool", -"Personal" => "Isiklik", +"Personal" => "isiklik", "Users" => "Kasutajad", -"Apps" => "Rakendused", +"Apps" => "Programmid", "Admin" => "Admin", "Help" => "Abiinfo", "Access forbidden" => "Ligipääs on keelatud", "Cloud not found" => "Pilve ei leitud", -"Edit categories" => "Muuda kategooriat", +"Edit categories" => "Muuda kategooriaid", "Add" => "Lisa", "Security Warning" => "Turvahoiatus", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "Sinu PHP versioon on haavatav NULL Baidi (CVE-2006-7243) rünnakuga.", @@ -113,7 +114,7 @@ "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Su andmete kataloog ja failid on tõenäoliselt internetist vabalt saadaval kuna .htaccess fail ei toimi.", "For information how to properly configure your server, please see the documentation." => "Serveri korrektseks seadistuseks palun tutvu dokumentatsiooniga.", "Create an admin account" => "Loo admini konto", -"Advanced" => "Täpsem", +"Advanced" => "Lisavalikud", "Data folder" => "Andmete kaust", "Configure the database" => "Seadista andmebaasi", "will be used" => "kasutatakse", @@ -123,7 +124,7 @@ "Database tablespace" => "Andmebaasi tabeliruum", "Database host" => "Andmebaasi host", "Finish setup" => "Lõpeta seadistamine", -"web services under your control" => "veebitenused sinu kontrolli all", +"web services under your control" => "veebiteenused sinu kontrolli all", "Log out" => "Logi välja", "Automatic logon rejected!" => "Automaatne sisselogimine lükati tagasi!", "If you did not change your password recently, your account may be compromised!" => "Kui sa ei muutnud oma parooli hiljut, siis võib su kasutajakonto olla ohustatud!", diff --git a/core/l10n/eu.php b/core/l10n/eu.php index 9c9d28133c..76e38a92d1 100644 --- a/core/l10n/eu.php +++ b/core/l10n/eu.php @@ -89,6 +89,8 @@ "ownCloud password reset" => "ownCloud-en pasahitza berrezarri", "Use the following link to reset your password: {link}" => "Eribili hurrengo lotura zure pasahitza berrezartzeko: {link}", "You will receive a link to reset your password via Email." => "Zure pashitza berrezartzeko lotura bat jasoko duzu Epostaren bidez.", +"Reset email send." => "Berrezartzeko eposta bidali da.", +"Request failed!" => "Eskariak huts egin du!", "Username" => "Erabiltzaile izena", "Request reset" => "Eskaera berrezarri da", "Your password was reset" => "Zure pasahitza berrezarri da", @@ -98,7 +100,7 @@ "Personal" => "Pertsonala", "Users" => "Erabiltzaileak", "Apps" => "Aplikazioak", -"Admin" => "Admin", +"Admin" => "Kudeatzailea", "Help" => "Laguntza", "Access forbidden" => "Sarrera debekatuta", "Cloud not found" => "Ez da hodeia aurkitu", diff --git a/core/l10n/fa.php b/core/l10n/fa.php index ff73e80448..e6f5aaac0c 100644 --- a/core/l10n/fa.php +++ b/core/l10n/fa.php @@ -54,7 +54,7 @@ "The app name is not specified." => "نام برنامه تعیین نشده است.", "The required file {file} is not installed!" => "پرونده { پرونده} درخواست شده نصب نشده است !", "Shared" => "اشتراک گذاشته شده", -"Share" => "اشتراک‌گذاری", +"Share" => "اشتراک‌گزاری", "Error while sharing" => "خطا درحال به اشتراک گذاشتن", "Error while unsharing" => "خطا درحال لغو اشتراک", "Error while changing permissions" => "خطا در حال تغییر مجوز", @@ -89,20 +89,22 @@ "ownCloud password reset" => "پسورد ابرهای شما تغییرکرد", "Use the following link to reset your password: {link}" => "از لینک زیر جهت دوباره سازی پسورد استÙاده کنید :\n{link}", "You will receive a link to reset your password via Email." => "شما یک نامه الکترونیکی حاوی یک لینک جهت بازسازی گذرواژه دریاÙت خواهید کرد.", -"Username" => "نام کاربری", +"Reset email send." => "تنظیم مجدد ایمیل را بÙرستید.", +"Request failed!" => "درخواست رد شده است !", +"Username" => "شناسه", "Request reset" => "درخواست دوباره سازی", "Your password was reset" => "گذرواژه شما تغییرکرد", "To login page" => "به صÙحه ورود", "New password" => "گذرواژه جدید", "Reset password" => "دوباره سازی گذرواژه", "Personal" => "شخصی", -"Users" => "کاربران", -"Apps" => " برنامه ها", +"Users" => "کاربر ها", +"Apps" => "برنامه", "Admin" => "مدیر", -"Help" => "راه‌نما", +"Help" => "Ú©Ù…Ú©", "Access forbidden" => "اجازه دسترسی به مناطق ممنوعه را ندارید", "Cloud not found" => "پیدا نشد", -"Edit categories" => "ویرایش گروه", +"Edit categories" => "ویرایش گروه ها", "Add" => "اÙزودن", "Security Warning" => "اخطار امنیتی", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "نسخه ÛŒ PHP شما در برابر حملات NULL Byte آسیب پذیر است.(CVE-2006-7243)", @@ -112,7 +114,7 @@ "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Ùایلها Ùˆ Ùهرست های داده های شما قابل از اینترنت قابل دسترسی هستند، چونکه Ùایل htacces. کار نمی کند.", "For information how to properly configure your server, please see the documentation." => "برای مطلع شدن از چگونگی تنظیم سرورتان،لطÙا این را ببینید.", "Create an admin account" => "لطÙا یک شناسه برای مدیر بسازید", -"Advanced" => "پیشرÙته", +"Advanced" => "حرÙÙ‡ ای", "Data folder" => "پوشه اطلاعاتی", "Configure the database" => "پایگاه داده برنامه ریزی شدند", "will be used" => "استÙاده خواهد شد", @@ -122,7 +124,7 @@ "Database tablespace" => "جدول پایگاه داده", "Database host" => "هاست پایگاه داده", "Finish setup" => "اتمام نصب", -"web services under your control" => "سرویس های تحت وب در کنترل شما", +"web services under your control" => "سرویس وب تحت کنترل شما", "Log out" => "خروج", "Automatic logon rejected!" => "ورود به سیستم اتوماتیک ردشد!", "If you did not change your password recently, your account may be compromised!" => "اگر شما اخیرا رمزعبور را تغییر نداده اید، حساب شما در معرض خطر Ù…ÛŒ باشد !", diff --git a/core/l10n/fi_FI.php b/core/l10n/fi_FI.php index 3f50e81484..ec79d03122 100644 --- a/core/l10n/fi_FI.php +++ b/core/l10n/fi_FI.php @@ -9,25 +9,25 @@ "Error adding %s to favorites." => "Virhe lisätessä kohdetta %s suosikkeihin.", "No categories selected for deletion." => "Luokkia ei valittu poistettavaksi.", "Error removing %s from favorites." => "Virhe poistaessa kohdetta %s suosikeista.", -"Sunday" => "sunnuntai", -"Monday" => "maanantai", -"Tuesday" => "tiistai", -"Wednesday" => "keskiviikko", -"Thursday" => "torstai", -"Friday" => "perjantai", -"Saturday" => "lauantai", -"January" => "tammikuu", -"February" => "helmikuu", -"March" => "maaliskuu", -"April" => "huhtikuu", -"May" => "toukokuu", -"June" => "kesäkuu", -"July" => "heinäkuu", -"August" => "elokuu", -"September" => "syyskuu", -"October" => "lokakuu", -"November" => "marraskuu", -"December" => "joulukuu", +"Sunday" => "Sunnuntai", +"Monday" => "Maanantai", +"Tuesday" => "Tiistai", +"Wednesday" => "Keskiviikko", +"Thursday" => "Torstai", +"Friday" => "Perjantai", +"Saturday" => "Lauantai", +"January" => "Tammikuu", +"February" => "Helmikuu", +"March" => "Maaliskuu", +"April" => "Huhtikuu", +"May" => "Toukokuu", +"June" => "Kesäkuu", +"July" => "Heinäkuu", +"August" => "Elokuu", +"September" => "Syyskuu", +"October" => "Lokakuu", +"November" => "Marraskuu", +"December" => "Joulukuu", "Settings" => "Asetukset", "seconds ago" => "sekuntia sitten", "1 minute ago" => "1 minuutti sitten", @@ -85,16 +85,18 @@ "ownCloud password reset" => "ownCloud-salasanan nollaus", "Use the following link to reset your password: {link}" => "Voit palauttaa salasanasi seuraavassa osoitteessa: {link}", "You will receive a link to reset your password via Email." => "Saat sähköpostitse linkin nollataksesi salasanan.", +"Reset email send." => "Salasanan nollausviesti lähetetty.", +"Request failed!" => "Pyyntö epäonnistui!", "Username" => "Käyttäjätunnus", "Request reset" => "Tilaus lähetetty", "Your password was reset" => "Salasanasi nollattiin", "To login page" => "Kirjautumissivulle", "New password" => "Uusi salasana", "Reset password" => "Palauta salasana", -"Personal" => "Henkilökohtainen", +"Personal" => "Henkilökohtaiset", "Users" => "Käyttäjät", "Apps" => "Sovellukset", -"Admin" => "Ylläpitäjä", +"Admin" => "Hallinta", "Help" => "Ohje", "Access forbidden" => "Pääsy estetty", "Cloud not found" => "Pilveä ei löydy", @@ -103,7 +105,6 @@ "Security Warning" => "Turvallisuusvaroitus", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "PHP-asennuksesi on haavoittuvainen NULL Byte -hyökkäykselle (CVE-2006-7243)", "Please update your PHP installation to use ownCloud securely." => "Päivitä PHP-asennuksesi käyttääksesi ownCloudia turvallisesti.", -"No secure random number generator is available, please enable the PHP OpenSSL extension." => "Turvallista satunnaislukugeneraattoria ei ole käytettävissä, ota käyttöön PHP:n OpenSSL-laajennus", "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Datakansiosi ja tiedostosi ovat mitä luultavimmin muiden saavutettavissa internetistä, koska .htaccess-tiedosto ei toimi.", "For information how to properly configure your server, please see the documentation." => "Katso palvelimen asetuksien määrittämiseen liittyvät ohjeet dokumentaatiosta.", "Create an admin account" => "Luo ylläpitäjän tunnus", diff --git a/core/l10n/fr.php b/core/l10n/fr.php index c8f60a678f..3b89d69b3b 100644 --- a/core/l10n/fr.php +++ b/core/l10n/fr.php @@ -9,7 +9,7 @@ "Object type not provided." => "Type d'objet non spécifié.", "%s ID not provided." => "L'identifiant de %s n'est pas spécifié.", "Error adding %s to favorites." => "Erreur lors de l'ajout de %s aux favoris.", -"No categories selected for deletion." => "Pas de catégorie sélectionnée pour la suppression.", +"No categories selected for deletion." => "Aucune catégorie sélectionnée pour suppression", "Error removing %s from favorites." => "Erreur lors de la suppression de %s des favoris.", "Sunday" => "Dimanche", "Monday" => "Lundi", @@ -88,23 +88,23 @@ "The update was successful. Redirecting you to ownCloud now." => "La mise à jour a réussi. Vous êtes redirigé maintenant vers ownCloud.", "ownCloud password reset" => "Réinitialisation de votre mot de passe Owncloud", "Use the following link to reset your password: {link}" => "Utilisez le lien suivant pour réinitialiser votre mot de passe : {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "Le lien permettant de réinitialiser votre mot de passe vous a été transmis.
Si vous ne le recevez pas dans un délai raisonnable, vérifier votre boîte de pourriels.
Au besoin, contactez votre administrateur local.", -"Request failed!
Did you make sure your email/username was right?" => "Requête en échec!
Avez-vous vérifié vos courriel/nom d'utilisateur?", "You will receive a link to reset your password via Email." => "Vous allez recevoir un e-mail contenant un lien pour réinitialiser votre mot de passe.", +"Reset email send." => "Mail de réinitialisation envoyé.", +"Request failed!" => "La requête a échoué !", "Username" => "Nom d'utilisateur", "Request reset" => "Demander la réinitialisation", "Your password was reset" => "Votre mot de passe a été réinitialisé", "To login page" => "Retour à la page d'authentification", "New password" => "Nouveau mot de passe", "Reset password" => "Réinitialiser le mot de passe", -"Personal" => "Personnel", +"Personal" => "Personnels", "Users" => "Utilisateurs", "Apps" => "Applications", "Admin" => "Administration", "Help" => "Aide", "Access forbidden" => "Accès interdit", "Cloud not found" => "Introuvable", -"Edit categories" => "Editer les catégories", +"Edit categories" => "Modifier les catégories", "Add" => "Ajouter", "Security Warning" => "Avertissement de sécurité", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "Votre version de PHP est vulnérable à l'attaque par caractère NULL (CVE-2006-7243)", diff --git a/core/l10n/gl.php b/core/l10n/gl.php index f6c36d6ac6..fd237a39c8 100644 --- a/core/l10n/gl.php +++ b/core/l10n/gl.php @@ -9,7 +9,7 @@ "Object type not provided." => "Non se forneceu o tipo de obxecto.", "%s ID not provided." => "Non se forneceu o ID %s.", "Error adding %s to favorites." => "Produciuse un erro ao engadir %s aos favoritos.", -"No categories selected for deletion." => "Non se seleccionaron categorías para eliminación.", +"No categories selected for deletion." => "Non hai categorías seleccionadas para eliminar.", "Error removing %s from favorites." => "Produciuse un erro ao eliminar %s dos favoritos.", "Sunday" => "Domingo", "Monday" => "Luns", @@ -30,11 +30,11 @@ "October" => "outubro", "November" => "novembro", "December" => "decembro", -"Settings" => "Axustes", +"Settings" => "Configuracións", "seconds ago" => "segundos atrás", "1 minute ago" => "hai 1 minuto", "{minutes} minutes ago" => "hai {minutes} minutos", -"1 hour ago" => "Vai 1 hora", +"1 hour ago" => "hai 1 hora", "{hours} hours ago" => "hai {hours} horas", "today" => "hoxe", "yesterday" => "onte", @@ -88,9 +88,9 @@ "The update was successful. Redirecting you to ownCloud now." => "A actualización realizouse correctamente. Redirixíndoo agora á ownCloud.", "ownCloud password reset" => "Restabelecer o contrasinal de ownCloud", "Use the following link to reset your password: {link}" => "Usa a seguinte ligazón para restabelecer o contrasinal: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "Envióuselle ao seu correo unha ligazón para restabelecer o seu contrasinal.
Se non o recibe nun prazo razoábel de tempo, revise o seu cartafol de correo lixo ou de non desexados.
Se non o atopa aí pregúntelle ao seu administrador local..", -"Request failed!
Did you make sure your email/username was right?" => "Non foi posíbel facer a petición!
Asegúrese de que o seu enderezo de correo ou nome de usuario é correcto.", "You will receive a link to reset your password via Email." => "Recibirá unha ligazón por correo para restabelecer o contrasinal", +"Reset email send." => "Restabelecer o envío por correo.", +"Request failed!" => "Non foi posíbel facer a petición", "Username" => "Nome de usuario", "Request reset" => "Petición de restabelecemento", "Your password was reset" => "O contrasinal foi restabelecido", @@ -100,11 +100,11 @@ "Personal" => "Persoal", "Users" => "Usuarios", "Apps" => "Aplicativos", -"Admin" => "Administración", +"Admin" => "Admin", "Help" => "Axuda", "Access forbidden" => "Acceso denegado", "Cloud not found" => "Nube non atopada", -"Edit categories" => "Editar as categorías", +"Edit categories" => "Editar categorías", "Add" => "Engadir", "Security Warning" => "Aviso de seguranza", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "A súa versión de PHP é vulnerábel a un ataque de byte nulo (CVE-2006-7243)", diff --git a/core/l10n/he.php b/core/l10n/he.php index f161c356ca..56f273e95d 100644 --- a/core/l10n/he.php +++ b/core/l10n/he.php @@ -63,7 +63,7 @@ "Share with" => "שיתוף ×¢×", "Share with link" => "שיתוף ×¢× ×§×™×©×•×¨", "Password protect" => "×”×’× ×” בססמה", -"Password" => "סיסמ×", +"Password" => "ססמה", "Email link to person" => "שליחת קישור בדו×״ל למשתמש", "Send" => "שליחה", "Set expiration date" => "הגדרת ת×ריך תפוגה", @@ -89,6 +89,8 @@ "ownCloud password reset" => "×יפוס הססמה של ownCloud", "Use the following link to reset your password: {link}" => "יש להשתמש בקישור ×”×‘× ×›×“×™ ל×פס ×ת הססמה שלך: {link}", "You will receive a link to reset your password via Email." => "יישלח לתיבת הדו×״ל שלך קישור ל×יפוס הססמה.", +"Reset email send." => "×יפוס שליחת דו×״ל.", +"Request failed!" => "הבקשה נכשלה!", "Username" => "×©× ×ž×©×ª×ž×©", "Request reset" => "בקשת ×יפוס", "Your password was reset" => "הססמה שלך ×ופסה", @@ -102,7 +104,7 @@ "Help" => "עזרה", "Access forbidden" => "הגישה נחסמה", "Cloud not found" => "ענן ×œ× × ×ž×¦×", -"Edit categories" => "ערוך קטגוריות", +"Edit categories" => "עריכת הקטגוריות", "Add" => "הוספה", "Security Warning" => "×זהרת ×בטחה", "No secure random number generator is available, please enable the PHP OpenSSL extension." => "×ין מחולל ×ž×¡×¤×¨×™× ×קר××™×™× ×ž×ובטח, × × ×œ×”×¤×¢×™×œ ×ת ההרחבה OpenSSL ב־PHP.", @@ -120,7 +122,7 @@ "Database tablespace" => "מרחב הכתובות של מסד הנתוני×", "Database host" => "שרת בסיס נתוני×", "Finish setup" => "×¡×™×•× ×”×ª×§× ×”", -"web services under your control" => "שירותי רשת תחת השליטה שלך", +"web services under your control" => "שירותי רשת בשליטתך", "Log out" => "התנתקות", "Automatic logon rejected!" => "בקשת הכניסה ×”×וטומטית נדחתה!", "If you did not change your password recently, your account may be compromised!" => "×× ×œ× ×©×™× ×™×ª ×ת ססמתך ל×חרונה, יתכן שחשבונך נפגע!", diff --git a/core/l10n/hr.php b/core/l10n/hr.php index e79e71d4b2..d32d8d4b22 100644 --- a/core/l10n/hr.php +++ b/core/l10n/hr.php @@ -1,6 +1,6 @@ "Nemate kategorija koje možete dodati?", -"No categories selected for deletion." => "Niti jedna kategorija nije odabrana za brisanje.", +"No categories selected for deletion." => "Nema odabranih kategorija za brisanje.", "Sunday" => "nedelja", "Monday" => "ponedeljak", "Tuesday" => "utorak", @@ -33,7 +33,7 @@ "Choose" => "Izaberi", "Yes" => "Da", "No" => "Ne", -"Error" => "GreÅ¡ka", +"Error" => "PogreÅ¡ka", "Share" => "Podijeli", "Error while sharing" => "GreÅ¡ka prilikom djeljenja", "Error while unsharing" => "GreÅ¡ka prilikom iskljuÄivanja djeljenja", @@ -76,7 +76,7 @@ "Edit categories" => "Uredi kategorije", "Add" => "Dodaj", "Create an admin account" => "Stvori administratorski raÄun", -"Advanced" => "Napredno", +"Advanced" => "Dodatno", "Data folder" => "Mapa baze podataka", "Configure the database" => "Konfiguriraj bazu podataka", "will be used" => "će se koristiti", diff --git a/core/l10n/hu_HU.php b/core/l10n/hu_HU.php index 013d68dff5..eb0a3d1a91 100644 --- a/core/l10n/hu_HU.php +++ b/core/l10n/hu_HU.php @@ -45,7 +45,7 @@ "last year" => "tavaly", "years ago" => "több éve", "Ok" => "Ok", -"Cancel" => "Mégsem", +"Cancel" => "Mégse", "Choose" => "Válasszon", "Yes" => "Igen", "No" => "Nem", @@ -89,16 +89,18 @@ "ownCloud password reset" => "ownCloud jelszó-visszaállítás", "Use the following link to reset your password: {link}" => "Használja ezt a linket a jelszó ismételt beállításához: {link}", "You will receive a link to reset your password via Email." => "Egy emailben fog értesítést kapni a jelszóbeállítás módjáról.", +"Reset email send." => "Elküldtük az emailt a jelszó ismételt beállításához.", +"Request failed!" => "Nem sikerült a kérést teljesíteni!", "Username" => "Felhasználónév", "Request reset" => "Visszaállítás igénylése", "Your password was reset" => "Jelszó megváltoztatva", "To login page" => "A bejelentkezÅ‘ ablakhoz", -"New password" => "Az új jelszó", +"New password" => "Új jelszó", "Reset password" => "Jelszó-visszaállítás", "Personal" => "Személyes", "Users" => "Felhasználók", "Apps" => "Alkalmazások", -"Admin" => "Adminsztráció", +"Admin" => "Adminisztráció", "Help" => "Súgó", "Access forbidden" => "A hozzáférés nem engedélyezett", "Cloud not found" => "A felhÅ‘ nem található", diff --git a/core/l10n/hy.php b/core/l10n/hy.php deleted file mode 100644 index de0c725c73..0000000000 --- a/core/l10n/hy.php +++ /dev/null @@ -1,21 +0,0 @@ - "Ô¿Õ«Ö€Õ¡Õ¯Õ«", -"Monday" => "ÔµÖ€Õ¯Õ¸Ö‚Õ·Õ¡Õ¢Õ©Õ«", -"Tuesday" => "ÔµÖ€Õ¥Ö„Õ·Õ¡Õ¢Õ©Õ«", -"Wednesday" => "Õ‰Õ¸Ö€Õ¥Ö„Õ·Õ¡Õ¢Õ©Õ«", -"Thursday" => "Õ€Õ«Õ¶Õ£Õ·Õ¡Õ¢Õ©Õ«", -"Friday" => "ÕˆÖ‚Ö€Õ¢Õ¡Õ©", -"Saturday" => "Õ‡Õ¡Õ¢Õ¡Õ©", -"January" => "Õ€Õ¸Ö‚Õ¶Õ¾Õ¡Ö€", -"February" => "Õ“Õ¥Õ¿Ö€Õ¾Õ¡Ö€", -"March" => "Õ„Õ¡Ö€Õ¿", -"April" => "Ô±ÕºÖ€Õ«Õ¬", -"May" => "Õ„Õ¡ÕµÕ«Õ½", -"June" => "Õ€Õ¸Ö‚Õ¶Õ«Õ½", -"July" => "Õ€Õ¸Ö‚Õ¬Õ«Õ½", -"August" => "Õ•Õ£Õ¸Õ½Õ¿Õ¸Õ½", -"September" => "ÕÕ¥ÕºÕ¿Õ¥Õ´Õ¢Õ¥Ö€", -"October" => "Õ€Õ¸Õ¯Õ¿Õ¥Õ´Õ¢Õ¥Ö€", -"November" => "Õ†Õ¸ÕµÕ¥Õ´Õ¢Õ¥Ö€", -"December" => "Ô´Õ¥Õ¯Õ¿Õ¥Õ´Õ¢Õ¥Ö€" -); diff --git a/core/l10n/id.php b/core/l10n/id.php index 984822af1e..9eeaba3454 100644 --- a/core/l10n/id.php +++ b/core/l10n/id.php @@ -45,7 +45,7 @@ "last year" => "tahun kemarin", "years ago" => "beberapa tahun lalu", "Ok" => "Oke", -"Cancel" => "Batal", +"Cancel" => "Batalkan", "Choose" => "Pilih", "Yes" => "Ya", "No" => "Tidak", @@ -89,7 +89,9 @@ "ownCloud password reset" => "Setel ulang sandi ownCloud", "Use the following link to reset your password: {link}" => "Gunakan tautan berikut untuk menyetel ulang sandi Anda: {link}", "You will receive a link to reset your password via Email." => "Anda akan menerima tautan penyetelan ulang sandi lewat Email.", -"Username" => "Nama pengguna", +"Reset email send." => "Email penyetelan ulang dikirim.", +"Request failed!" => "Permintaan gagal!", +"Username" => "Nama Pengguna", "Request reset" => "Ajukan penyetelan ulang", "Your password was reset" => "Sandi Anda telah disetel ulang", "To login page" => "Ke halaman masuk", @@ -103,7 +105,7 @@ "Access forbidden" => "Akses ditolak", "Cloud not found" => "Cloud tidak ditemukan", "Edit categories" => "Edit kategori", -"Add" => "Tambah", +"Add" => "Tambahkan", "Security Warning" => "Peringatan Keamanan", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "Versi PHP Anda rentan terhadap serangan NULL Byte (CVE-2006-7243)", "Please update your PHP installation to use ownCloud securely." => "Silakan perbarui instalasi PHP untuk dapat menggunakan ownCloud secara aman.", @@ -112,7 +114,7 @@ "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Kemungkinan direktori data dan berkas Anda dapat diakses dari internet karena berkas .htaccess tidak berfungsi.", "For information how to properly configure your server, please see the documentation." => "Untuk informasi lebih lanjut tentang pengaturan server yang benar, silakan lihat dokumentasi.", "Create an admin account" => "Buat sebuah akun admin", -"Advanced" => "Lanjutan", +"Advanced" => "Tingkat Lanjut", "Data folder" => "Folder data", "Configure the database" => "Konfigurasikan basis data", "will be used" => "akan digunakan", diff --git a/core/l10n/is.php b/core/l10n/is.php index d30d8bca11..c6b7a6df32 100644 --- a/core/l10n/is.php +++ b/core/l10n/is.php @@ -30,8 +30,8 @@ "November" => "Nóvember", "December" => "Desember", "Settings" => "Stillingar", -"seconds ago" => "sek.", -"1 minute ago" => "Fyrir 1 mínútu", +"seconds ago" => "sek síðan", +"1 minute ago" => "1 min síðan", "{minutes} minutes ago" => "{minutes} min síðan", "1 hour ago" => "Fyrir 1 klst.", "{hours} hours ago" => "fyrir {hours} klst.", @@ -42,7 +42,7 @@ "{months} months ago" => "fyrir {months} mánuðum", "months ago" => "mánuðir síðan", "last year" => "síðasta ári", -"years ago" => "einhverjum árum", +"years ago" => "árum síðan", "Ok" => "à lagi", "Cancel" => "Hætta við", "Choose" => "Veldu", @@ -85,21 +85,23 @@ "ownCloud password reset" => "endursetja ownCloud lykilorð", "Use the following link to reset your password: {link}" => "Notað eftirfarandi veftengil til að endursetja lykilorðið þitt: {link}", "You will receive a link to reset your password via Email." => "Þú munt fá veftengil í tölvupósti til að endursetja lykilorðið.", +"Reset email send." => "Beiðni um endursetningu send.", +"Request failed!" => "Beiðni mistókst!", "Username" => "Notendanafn", "Request reset" => "Endursetja lykilorð", "Your password was reset" => "Lykilorðið þitt hefur verið endursett.", "To login page" => "Fara á innskráningarsíðu", "New password" => "Nýtt lykilorð", "Reset password" => "Endursetja lykilorð", -"Personal" => "Um mig", +"Personal" => "Persónustillingar", "Users" => "Notendur", "Apps" => "Forrit", -"Admin" => "Stjórnun", +"Admin" => "Vefstjórn", "Help" => "Hjálp", "Access forbidden" => "Aðgangur bannaður", "Cloud not found" => "Ský finnst ekki", "Edit categories" => "Breyta flokkum", -"Add" => "Bæta við", +"Add" => "Bæta", "Security Warning" => "Öryggis aðvörun", "No secure random number generator is available, please enable the PHP OpenSSL extension." => "Enginn traustur slembitölugjafi í boði, vinsamlegast virkjaðu PHP OpenSSL viðbótina.", "Without a secure random number generator an attacker may be able to predict password reset tokens and take over your account." => "Ãn öruggs slembitölugjafa er mögulegt að sjá fyrir öryggis auðkenni til að endursetja lykilorð og komast inn á aðganginn þinn.", diff --git a/core/l10n/it.php b/core/l10n/it.php index d450f90b1d..d24c3330bf 100644 --- a/core/l10n/it.php +++ b/core/l10n/it.php @@ -77,8 +77,8 @@ "access control" => "controllo d'accesso", "create" => "creare", "update" => "aggiornare", -"delete" => "elimina", -"share" => "condividi", +"delete" => "eliminare", +"share" => "condividere", "Password protected" => "Protetta da password", "Error unsetting expiration date" => "Errore durante la rimozione della data di scadenza", "Error setting expiration date" => "Errore durante l'impostazione della data di scadenza", @@ -88,9 +88,9 @@ "The update was successful. Redirecting you to ownCloud now." => "L'aggiornamento è stato effettuato correttamente. Stai per essere reindirizzato a ownCloud.", "ownCloud password reset" => "Ripristino password di ownCloud", "Use the following link to reset your password: {link}" => "Usa il collegamento seguente per ripristinare la password: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "Il collegamento per ripristinare la password è stato inviato al tuo indirizzo di posta.
Se non lo ricevi in tempi ragionevoli, controlla le cartelle della posta indesiderata.
Se non dovesse essere nemmeno lì, contatta il tuo amministratore locale.", -"Request failed!
Did you make sure your email/username was right?" => "Richiesta non riuscita!
Sei sicuro che l'indirizzo di posta/nome utente fosse corretto?", "You will receive a link to reset your password via Email." => "Riceverai un collegamento per ripristinare la tua password via email", +"Reset email send." => "Email di ripristino inviata.", +"Request failed!" => "Richiesta non riuscita!", "Username" => "Nome utente", "Request reset" => "Richiesta di ripristino", "Your password was reset" => "La password è stata ripristinata", @@ -104,7 +104,7 @@ "Help" => "Aiuto", "Access forbidden" => "Accesso negato", "Cloud not found" => "Nuvola non trovata", -"Edit categories" => "Modifica categorie", +"Edit categories" => "Modifica le categorie", "Add" => "Aggiungi", "Security Warning" => "Avviso di sicurezza", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "La tua versione di PHP è vulnerabile all'attacco NULL Byte (CVE-2006-7243)", @@ -114,7 +114,7 @@ "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "La cartella dei dati e i file sono probabilmente accessibili da Internet poiché il file .htaccess non funziona.", "For information how to properly configure your server, please see the documentation." => "Per informazioni su come configurare correttamente il server, vedi la documentazione.", "Create an admin account" => "Crea un account amministratore", -"Advanced" => "Avanzat", +"Advanced" => "Avanzate", "Data folder" => "Cartella dati", "Configure the database" => "Configura il database", "will be used" => "sarà utilizzato", diff --git a/core/l10n/ja_JP.php b/core/l10n/ja_JP.php index 056c67e8da..200e494d8c 100644 --- a/core/l10n/ja_JP.php +++ b/core/l10n/ja_JP.php @@ -89,16 +89,18 @@ "ownCloud password reset" => "ownCloudã®ãƒ‘スワードをリセットã—ã¾ã™", "Use the following link to reset your password: {link}" => "パスワードをリセットã™ã‚‹ã«ã¯æ¬¡ã®ãƒªãƒ³ã‚¯ã‚’クリックã—ã¦ä¸‹ã•ã„: {link}", "You will receive a link to reset your password via Email." => "メールã§ãƒ‘スワードをリセットã™ã‚‹ãƒªãƒ³ã‚¯ãŒå±Šãã¾ã™ã€‚", -"Username" => "ユーザーå", +"Reset email send." => "リセットメールをé€ä¿¡ã—ã¾ã™ã€‚", +"Request failed!" => "リクエスト失敗ï¼", +"Username" => "ユーザå", "Request reset" => "リセットをè¦æ±‚ã—ã¾ã™ã€‚", "Your password was reset" => "ã‚ãªãŸã®ãƒ‘スワードã¯ãƒªã‚»ãƒƒãƒˆã•ã‚Œã¾ã—ãŸã€‚", "To login page" => "ログインページã¸æˆ»ã‚‹", "New password" => "æ–°ã—ã„パスワードを入力", "Reset password" => "パスワードをリセット", -"Personal" => "個人", +"Personal" => "個人設定", "Users" => "ユーザ", "Apps" => "アプリ", -"Admin" => "管ç†", +"Admin" => "管ç†è€…", "Help" => "ヘルプ", "Access forbidden" => "アクセスãŒç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™", "Cloud not found" => "見ã¤ã‹ã‚Šã¾ã›ã‚“", @@ -122,7 +124,7 @@ "Database tablespace" => "データベースã®è¡¨é ˜åŸŸ", "Database host" => "データベースã®ãƒ›ã‚¹ãƒˆå", "Finish setup" => "セットアップを完了ã—ã¾ã™", -"web services under your control" => "管ç†ä¸‹ã®ã‚¦ã‚§ãƒ–サービス", +"web services under your control" => "管ç†ä¸‹ã«ã‚るウェブサービス", "Log out" => "ログアウト", "Automatic logon rejected!" => "自動ログインã¯æ‹’å¦ã•ã‚Œã¾ã—ãŸï¼", "If you did not change your password recently, your account may be compromised!" => "最近パスワードを変更ã—ã¦ã„ãªã„å ´åˆã€ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯å±é™ºã«ã•ã‚‰ã•ã‚Œã¦ã„ã‚‹ã‹ã‚‚ã—ã‚Œã¾ã›ã‚“。", diff --git a/core/l10n/ka_GE.php b/core/l10n/ka_GE.php index fd2e512654..190a2f5eab 100644 --- a/core/l10n/ka_GE.php +++ b/core/l10n/ka_GE.php @@ -60,7 +60,7 @@ "Error while changing permissions" => "შეცდáƒáƒ›áƒ დáƒáƒ¨áƒ•áƒ”ბის ცვლილების დრáƒáƒ¡", "Shared with you and the group {group} by {owner}" => "გáƒáƒ–იáƒáƒ áƒ“რთქვენთვის დრჯგუფისთვის {group}, {owner}–ის მიერ", "Shared with you by {owner}" => "გáƒáƒ–იáƒáƒ áƒ“რთქვენთვის {owner}–ის მიერ", -"Share with" => "გáƒáƒáƒ–იáƒáƒ áƒ” შემდეგით:", +"Share with" => "გáƒáƒ£áƒ–იáƒáƒ áƒ”", "Share with link" => "გáƒáƒ£áƒ–იáƒáƒ áƒ” ლინკით", "Password protect" => "პáƒáƒ áƒáƒšáƒ˜áƒ— დáƒáƒªáƒ•áƒ", "Password" => "პáƒáƒ áƒáƒšáƒ˜", @@ -72,7 +72,7 @@ "No people found" => "მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბელი áƒáƒ  áƒáƒ áƒ˜áƒ¡ ნáƒáƒžáƒáƒ•áƒœáƒ˜", "Resharing is not allowed" => "მეáƒáƒ áƒ”ჯერ გáƒáƒ–იáƒáƒ áƒ”ბრáƒáƒ  áƒáƒ áƒ˜áƒ¡ დáƒáƒ¨áƒ•áƒ”ბული", "Shared in {item} with {user}" => "გáƒáƒ–იáƒáƒ áƒ“რ{item}–ში {user}–ის მიერ", -"Unshare" => "გáƒáƒ£áƒ–იáƒáƒ áƒ”ბáƒáƒ“ი", +"Unshare" => "გáƒáƒ–იáƒáƒ áƒ”ბის მáƒáƒ®áƒ¡áƒœáƒ", "can edit" => "შეგიძლირშეცვლáƒ", "access control" => "დáƒáƒ¨áƒ•áƒ”ბის კáƒáƒœáƒ¢áƒ áƒáƒšáƒ˜", "create" => "შექმნáƒ", @@ -89,16 +89,18 @@ "ownCloud password reset" => "ownCloud პáƒáƒ áƒáƒšáƒ˜áƒ¡ შეცვლáƒ", "Use the following link to reset your password: {link}" => "გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნე შემდეგი ლინკი პáƒáƒ áƒáƒšáƒ˜áƒ¡ შესáƒáƒªáƒ•áƒšáƒ”ლáƒáƒ“: {link}", "You will receive a link to reset your password via Email." => "თქვენ მáƒáƒ’ივáƒáƒ— პáƒáƒ áƒáƒšáƒ˜áƒ¡ შესáƒáƒªáƒ•áƒšáƒ”ლი ლინკი მეილზე", -"Username" => "მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბლის სáƒáƒ®áƒ”ლი", +"Reset email send." => "რესეტის მეილი გáƒáƒ˜áƒ’ზáƒáƒ•áƒœáƒ", +"Request failed!" => "მáƒáƒ—ხáƒáƒ•áƒœáƒ შეწყდáƒ!", +"Username" => "მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბელი", "Request reset" => "პáƒáƒ áƒáƒšáƒ˜áƒ¡ შეცვლის მáƒáƒ—ხáƒáƒ•áƒœáƒ", "Your password was reset" => "თქვენი პáƒáƒ áƒáƒšáƒ˜ შეცვლილიáƒ", "To login page" => "შესვლის გვერდზე", "New password" => "áƒáƒ®áƒáƒšáƒ˜ პáƒáƒ áƒáƒšáƒ˜", "Reset password" => "პáƒáƒ áƒáƒšáƒ˜áƒ¡ შეცვლáƒ", "Personal" => "პირáƒáƒ“ი", -"Users" => "მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბელი", +"Users" => "მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბლები", "Apps" => "áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ”ბი", -"Admin" => "áƒáƒ“მინისტრáƒáƒ¢áƒáƒ áƒ˜", +"Admin" => "áƒáƒ“მინი", "Help" => "დáƒáƒ®áƒ›áƒáƒ áƒ”ბáƒ", "Access forbidden" => "წვდáƒáƒ›áƒ áƒáƒ™áƒ áƒ«áƒáƒšáƒ£áƒšáƒ˜áƒ", "Cloud not found" => "ღრუბელი áƒáƒ  áƒáƒ áƒ¡áƒ”ბáƒáƒ‘ს", @@ -122,7 +124,7 @@ "Database tablespace" => "ბáƒáƒ–ის ცხრილის ზáƒáƒ›áƒ", "Database host" => "მáƒáƒœáƒáƒªáƒ”მთრბáƒáƒ–ის ჰáƒáƒ¡áƒ¢áƒ˜", "Finish setup" => "კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ˜áƒ¡ დáƒáƒ¡áƒ áƒ£áƒšáƒ”ბáƒ", -"web services under your control" => "web services under your control", +"web services under your control" => "თქვენი კáƒáƒœáƒ¢áƒ áƒáƒšáƒ˜áƒ¡ ქვეშ მყáƒáƒ¤áƒ˜ ვებ სერვისები", "Log out" => "გáƒáƒ›áƒáƒ¡áƒ•áƒšáƒ", "Automatic logon rejected!" => "áƒáƒ•áƒ¢áƒáƒ›áƒáƒ¢áƒ£áƒ áƒ˜ შესვლრუáƒáƒ áƒ§áƒáƒ¤áƒ˜áƒšáƒ˜áƒ!", "If you did not change your password recently, your account may be compromised!" => "თუ თქვენ áƒáƒ  შეცვლით პáƒáƒ áƒáƒšáƒ¡, თქვენი áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜ შეიძლებრიყáƒáƒ¡ დáƒáƒ¨áƒ•áƒ”ბáƒáƒ“ი სხვებისთვის", diff --git a/core/l10n/ko.php b/core/l10n/ko.php index 08713edaee..2a75ce9c4f 100644 --- a/core/l10n/ko.php +++ b/core/l10n/ko.php @@ -5,11 +5,10 @@ "User %s shared the folder \"%s\" with you. It is available for download here: %s" => "%s ë‹˜ì´ í´ë” \"%s\"ì„(를) 공유하였습니다. 여기ì—ì„œ 다운로드할 수 있습니다: %s", "Category type not provided." => "분류 형ì‹ì´ 제공ë˜ì§€ 않았습니다.", "No category to add?" => "추가할 분류가 없습니까?", -"This category already exists: %s" => "분류가 ì´ë¯¸ 존재합니다: %s", "Object type not provided." => "ê°ì²´ 형ì‹ì´ 제공ë˜ì§€ 않았습니다.", "%s ID not provided." => "%s IDê°€ 제공ë˜ì§€ 않았습니다.", "Error adding %s to favorites." => "ì±…ê°ˆí”¼ì— %sì„(를) 추가할 수 없었습니다.", -"No categories selected for deletion." => "삭제할 분류를 ì„ íƒí•˜ì§€ 않았습니다. ", +"No categories selected for deletion." => "삭제할 분류를 ì„ íƒí•˜ì§€ 않았습니다.", "Error removing %s from favorites." => "책갈피ì—ì„œ %sì„(를) 삭제할 수 없었습니다.", "Sunday" => "ì¼ìš”ì¼", "Monday" => "월요ì¼", @@ -75,7 +74,7 @@ "Unshare" => "공유 í•´ì œ", "can edit" => "편집 가능", "access control" => "ì ‘ê·¼ 제어", -"create" => "ìƒì„±", +"create" => "만들기", "update" => "ì—…ë°ì´íŠ¸", "delete" => "ì‚­ì œ", "share" => "공유", @@ -89,6 +88,8 @@ "ownCloud password reset" => "ownCloud 암호 재설정", "Use the following link to reset your password: {link}" => "ë‹¤ìŒ ë§í¬ë¥¼ 사용하여 암호를 재설정할 수 있습니다: {link}", "You will receive a link to reset your password via Email." => "ì´ë©”ì¼ë¡œ 암호 재설정 ë§í¬ë¥¼ 보냈습니다.", +"Reset email send." => "초기화 ì´ë©”ì¼ì„ 보냈습니다.", +"Request failed!" => "ìš”ì²­ì´ ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤!", "Username" => "ì‚¬ìš©ìž ì´ë¦„", "Request reset" => "요청 초기화", "Your password was reset" => "암호가 재설정ë˜ì—ˆìŠµë‹ˆë‹¤", @@ -102,15 +103,11 @@ "Help" => "ë„움ë§", "Access forbidden" => "ì ‘ê·¼ 금지ë¨", "Cloud not found" => "í´ë¼ìš°ë“œë¥¼ ì°¾ì„ ìˆ˜ 없습니다", -"Edit categories" => "분류 수정", +"Edit categories" => "분류 편집", "Add" => "추가", "Security Warning" => "보안 경고", -"Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "사용 ì¤‘ì¸ PHP ë²„ì „ì´ NULL ë°”ì´íŠ¸ ê³µê²©ì— ì·¨ì•½í•©ë‹ˆë‹¤ (CVE-2006-7243)", -"Please update your PHP installation to use ownCloud securely." => "ownCloudì˜ ë³´ì•ˆì„ ìœ„í•˜ì—¬ PHP ë²„ì „ì„ ì—…ë°ì´íŠ¸í•˜ì‹­ì‹œì˜¤.", "No secure random number generator is available, please enable the PHP OpenSSL extension." => "안전한 난수 ìƒì„±ê¸°ë¥¼ 사용할 수 없습니다. PHPì˜ OpenSSL í™•ìž¥ì„ í™œì„±í™”í•´ 주십시오.", "Without a secure random number generator an attacker may be able to predict password reset tokens and take over your account." => "안전한 난수 ìƒì„±ê¸°ë¥¼ 사용하지 않으면 공격ìžê°€ 암호 초기화 토í°ì„ 추측하여 ê³„ì •ì„ íƒˆì·¨í•  수 있습니다.", -"Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => ".htaccess 파ì¼ì´ 처리ë˜ì§€ ì•Šì•„ì„œ ë°ì´í„° 디렉터리와 파ì¼ì„ ì¸í„°ë„·ì—ì„œ 접근할 수 ì—†ì„ ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤.", -"For information how to properly configure your server, please see the documentation." => "서버를 올바르게 설정하는 ë°©ë²•ì„ ì•Œì•„ë³´ë ¤ë©´ 문서를 참고하십시오..", "Create an admin account" => "ê´€ë¦¬ìž ê³„ì • 만들기", "Advanced" => "고급", "Data folder" => "ë°ì´í„° í´ë”", @@ -130,7 +127,6 @@ "Lost your password?" => "암호를 잊으셨습니까?", "remember" => "기억하기", "Log in" => "로그ì¸", -"Alternative Logins" => "대체 ", "prev" => "ì´ì „", "next" => "다ìŒ", "Updating ownCloud to version %s, this may take a while." => "ownCloud를 버전 %s(으)ë¡œ ì—…ë°ì´íŠ¸í•©ë‹ˆë‹¤. ìž ì‹œ 기다려 주십시오." diff --git a/core/l10n/lb.php b/core/l10n/lb.php index f2277445f9..79258b8e97 100644 --- a/core/l10n/lb.php +++ b/core/l10n/lb.php @@ -57,7 +57,7 @@ "Access forbidden" => "Access net erlaabt", "Cloud not found" => "Cloud net fonnt", "Edit categories" => "Kategorien editéieren", -"Add" => "Dobäisetzen", +"Add" => "Bäisetzen", "Security Warning" => "Sécherheets Warnung", "Create an admin account" => "En Admin Account uleeën", "Advanced" => "Avancéiert", diff --git a/core/l10n/lt_LT.php b/core/l10n/lt_LT.php index 05ae35cc3d..0f55c341e5 100644 --- a/core/l10n/lt_LT.php +++ b/core/l10n/lt_LT.php @@ -53,7 +53,7 @@ "No people found" => "Žmonių nerasta", "Resharing is not allowed" => "Dalijinasis iÅ¡naujo negalimas", "Shared in {item} with {user}" => "Pasidalino {item} su {user}", -"Unshare" => "Nebesidalinti", +"Unshare" => "Nesidalinti", "can edit" => "gali redaguoti", "access control" => "priÄ—jimo kontrolÄ—", "create" => "sukurti", diff --git a/core/l10n/lv.php b/core/l10n/lv.php index 18af82e4e3..76188662fb 100644 --- a/core/l10n/lv.php +++ b/core/l10n/lv.php @@ -9,7 +9,7 @@ "Object type not provided." => "Objekta tips nav norÄdÄ«ts.", "%s ID not provided." => "%s ID nav norÄdÄ«ts.", "Error adding %s to favorites." => "Kļūda, pievienojot %s izlasei.", -"No categories selected for deletion." => "Neviena kategorija nav izvÄ“lÄ“ta dzÄ“Å¡anai.", +"No categories selected for deletion." => "Neviena kategorija nav izvÄ“lÄ“ta dzÄ“Å¡anai", "Error removing %s from favorites." => "Kļūda, izņemot %s no izlases.", "Sunday" => "SvÄ“tdiena", "Monday" => "Pirmdiena", @@ -72,7 +72,7 @@ "No people found" => "Nav atrastu cilvÄ“ku", "Resharing is not allowed" => "AtkÄrtota dalÄ«Å¡anÄs nav atļauta", "Shared in {item} with {user}" => "DalÄ«jÄs ar {item} ar {user}", -"Unshare" => "PÄrtraukt dalÄ«Å¡anos", +"Unshare" => "Beigt dalÄ«ties", "can edit" => "var rediģēt", "access control" => "piekļuves vadÄ«ba", "create" => "izveidot", @@ -89,6 +89,8 @@ "ownCloud password reset" => "ownCloud paroles maiņa", "Use the following link to reset your password: {link}" => "Izmantojiet Å¡o saiti, lai mainÄ«tu paroli: {link}", "You will receive a link to reset your password via Email." => "JÅ«s savÄ epastÄ saņemsiet interneta saiti, caur kuru varÄ“siet atjaunot paroli.", +"Reset email send." => "AtstatÄ«t e-pasta sÅ«tÄ«Å¡anu.", +"Request failed!" => "PieprasÄ«jums neizdevÄs!", "Username" => "LietotÄjvÄrds", "Request reset" => "PieprasÄ«t paroles maiņu", "Your password was reset" => "JÅ«su parole tika nomainÄ«ta", @@ -98,7 +100,7 @@ "Personal" => "PersonÄ«gi", "Users" => "LietotÄji", "Apps" => "Lietotnes", -"Admin" => "Administratori", +"Admin" => "Administrators", "Help" => "PalÄ«dzÄ«ba", "Access forbidden" => "Pieeja ir liegta", "Cloud not found" => "MÄkonis netika atrasts", diff --git a/core/l10n/mk.php b/core/l10n/mk.php index a6c06e4780..9743d8b299 100644 --- a/core/l10n/mk.php +++ b/core/l10n/mk.php @@ -29,7 +29,7 @@ "October" => "Октомври", "November" => "Ðоември", "December" => "Декември", -"Settings" => "ПодеÑувања", +"Settings" => "ПоÑтавки", "seconds ago" => "пред Ñекунди", "1 minute ago" => "пред 1 минута", "{minutes} minutes ago" => "пред {minutes} минути", @@ -85,6 +85,8 @@ "ownCloud password reset" => "реÑетирање на лозинка за ownCloud", "Use the following link to reset your password: {link}" => "КориÑтете ја Ñледната врÑка да ја реÑетирате Вашата лозинка: {link}", "You will receive a link to reset your password via Email." => "Ќе добиете врÑка по е-пошта за да може да ја реÑетирате Вашата лозинка.", +"Reset email send." => "Порката за реÑетирање на лозинка пратена.", +"Request failed!" => "Барањето не уÑпеа!", "Username" => "КориÑничко име", "Request reset" => "Побарајте реÑетирање", "Your password was reset" => "Вашата лозинка беше реÑетирана", @@ -93,7 +95,7 @@ "Reset password" => "РеÑетирај лозинка", "Personal" => "Лично", "Users" => "КориÑници", -"Apps" => "Ðппликации", +"Apps" => "Ðпликации", "Admin" => "Ðдмин", "Help" => "Помош", "Access forbidden" => "Забранет приÑтап", diff --git a/core/l10n/ms_MY.php b/core/l10n/ms_MY.php index 70581ff769..d8a2cf8836 100644 --- a/core/l10n/ms_MY.php +++ b/core/l10n/ms_MY.php @@ -1,6 +1,6 @@ "Tiada kategori untuk di tambah?", -"No categories selected for deletion." => "Tiada kategori dipilih untuk dibuang.", +"No categories selected for deletion." => "tiada kategori dipilih untuk penghapusan", "Sunday" => "Ahad", "Monday" => "Isnin", "Tuesday" => "Selasa", @@ -44,7 +44,7 @@ "Help" => "Bantuan", "Access forbidden" => "Larangan akses", "Cloud not found" => "Awan tidak dijumpai", -"Edit categories" => "Ubah kategori", +"Edit categories" => "Edit kategori", "Add" => "Tambah", "Security Warning" => "Amaran keselamatan", "Create an admin account" => "buat akaun admin", diff --git a/core/l10n/nb_NO.php b/core/l10n/nb_NO.php index 6efb31a7de..4e1ee45eec 100644 --- a/core/l10n/nb_NO.php +++ b/core/l10n/nb_NO.php @@ -92,7 +92,7 @@ "Database tablespace" => "Database tabellomrÃ¥de", "Database host" => "Databasevert", "Finish setup" => "Fullfør oppsetting", -"web services under your control" => "web tjenester du kontrollerer", +"web services under your control" => "nettjenester under din kontroll", "Log out" => "Logg ut", "Automatic logon rejected!" => "Automatisk pÃ¥logging avvist!", "If you did not change your password recently, your account may be compromised!" => "Hvis du ikke har endret passordet ditt nylig kan kontoen din være kompromitert", diff --git a/core/l10n/nl.php b/core/l10n/nl.php index 83d1e82dc3..5e050c33be 100644 --- a/core/l10n/nl.php +++ b/core/l10n/nl.php @@ -45,7 +45,7 @@ "last year" => "vorig jaar", "years ago" => "jaar geleden", "Ok" => "Ok", -"Cancel" => "Annuleer", +"Cancel" => "Annuleren", "Choose" => "Kies", "Yes" => "Ja", "No" => "Nee", @@ -75,7 +75,7 @@ "Unshare" => "Stop met delen", "can edit" => "kan wijzigen", "access control" => "toegangscontrole", -"create" => "creëer", +"create" => "maak", "update" => "bijwerken", "delete" => "verwijderen", "share" => "deel", @@ -88,14 +88,14 @@ "The update was successful. Redirecting you to ownCloud now." => "De update is geslaagd. U wordt teruggeleid naar uw eigen ownCloud.", "ownCloud password reset" => "ownCloud wachtwoord herstellen", "Use the following link to reset your password: {link}" => "Gebruik de volgende link om je wachtwoord te resetten: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "De link voor het resetten van uw wachtwoord is verzonden naar uw e-mailadres.
Als u dat bericht niet snel ontvangen hebt, controleer dan uw spambakje.
Als het daar ook niet is, vraag dan uw beheerder om te helpen.", -"Request failed!
Did you make sure your email/username was right?" => "Aanvraag mislukt!
Weet u zeker dat uw gebruikersnaam en/of wachtwoord goed waren?", "You will receive a link to reset your password via Email." => "U ontvangt een link om uw wachtwoord opnieuw in te stellen via e-mail.", +"Reset email send." => "Reset e-mail verstuurd.", +"Request failed!" => "Verzoek mislukt!", "Username" => "Gebruikersnaam", "Request reset" => "Resetaanvraag", "Your password was reset" => "Je wachtwoord is gewijzigd", "To login page" => "Naar de login-pagina", -"New password" => "Nieuw", +"New password" => "Nieuw wachtwoord", "Reset password" => "Reset wachtwoord", "Personal" => "Persoonlijk", "Users" => "Gebruikers", @@ -104,7 +104,7 @@ "Help" => "Help", "Access forbidden" => "Toegang verboden", "Cloud not found" => "Cloud niet gevonden", -"Edit categories" => "Wijzig categorieën", +"Edit categories" => "Wijzigen categorieën", "Add" => "Toevoegen", "Security Warning" => "Beveiligingswaarschuwing", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "Uw PHP versie is kwetsbaar voor de NULL byte aanval (CVE-2006-7243)", diff --git a/core/l10n/nn_NO.php b/core/l10n/nn_NO.php index f62897ed27..61b2baffbf 100644 --- a/core/l10n/nn_NO.php +++ b/core/l10n/nn_NO.php @@ -1,16 +1,4 @@ "Brukaren %s delte ei fil med deg", -"User %s shared a folder with you" => "Brukaren %s delte ei mappe med deg", -"User %s shared the file \"%s\" with you. It is available for download here: %s" => "Brukaren %s delte fila «%s» med deg. Du kan lasta ho ned her: %s", -"User %s shared the folder \"%s\" with you. It is available for download here: %s" => "Brukaren %s delte mappa «%s» med deg. Du kan lasta ho ned her: %s", -"Category type not provided." => "Ingen kategoritype.", -"No category to add?" => "Ingen kategori å leggja til?", -"This category already exists: %s" => "Denne kategorien finst alt: %s", -"Object type not provided." => "Ingen objekttype.", -"%s ID not provided." => "Ingen %s-ID.", -"Error adding %s to favorites." => "Klarte ikkje å leggja til %s i favorittar.", -"No categories selected for deletion." => "Ingen kategoriar valt for sletting.", -"Error removing %s from favorites." => "Klarte ikkje å fjerna %s frå favorittar.", "Sunday" => "Søndag", "Monday" => "Måndag", "Tuesday" => "Tysdag", @@ -31,88 +19,24 @@ "November" => "November", "December" => "Desember", "Settings" => "Innstillingar", -"seconds ago" => "sekund sidan", -"1 minute ago" => "1 minutt sidan", -"{minutes} minutes ago" => "{minutes} minutt sidan", -"1 hour ago" => "1 time sidan", -"{hours} hours ago" => "{hours} timar sidan", -"today" => "i dag", -"yesterday" => "i går", -"{days} days ago" => "{days} dagar sidan", -"last month" => "førre månad", -"{months} months ago" => "{months) månader sidan", -"months ago" => "månader sidan", -"last year" => "i fjor", -"years ago" => "år sidan", -"Ok" => "Greitt", -"Cancel" => "Avbryt", -"Choose" => "Vel", -"Yes" => "Ja", -"No" => "Nei", -"The object type is not specified." => "Objekttypen er ikkje spesifisert.", +"Cancel" => "Kanseller", "Error" => "Feil", -"The app name is not specified." => "App-namnet er ikkje spesifisert.", -"The required file {file} is not installed!" => "Den kravde fila {file} er ikkje installert!", -"Shared" => "Delt", -"Share" => "Del", -"Error while sharing" => "Feil ved deling", -"Error while unsharing" => "Feil ved udeling", -"Error while changing permissions" => "Feil ved endring av tillatingar", -"Shared with you and the group {group} by {owner}" => "Delt med deg og gruppa {group} av {owner}", -"Shared with you by {owner}" => "Delt med deg av {owner}", -"Share with" => "Del med", -"Share with link" => "Del med lenkje", -"Password protect" => "Passordvern", "Password" => "Passord", -"Email link to person" => "Send lenkja over e-post", -"Send" => "Send", -"Set expiration date" => "Set utlaupsdato", -"Expiration date" => "Utlaupsdato", -"Share via email:" => "Del over e-post:", -"No people found" => "Fann ingen personar", -"Resharing is not allowed" => "Vidaredeling er ikkje tillate", -"Shared in {item} with {user}" => "Delt i {item} med {brukar}", -"Unshare" => "Udel", -"can edit" => "kan endra", -"access control" => "tilgangskontroll", -"create" => "lag", -"update" => "oppdater", -"delete" => "slett", -"share" => "del", -"Password protected" => "Passordverna", -"Error unsetting expiration date" => "Klarte ikkje å fjerna utlaupsdato", -"Error setting expiration date" => "Klarte ikkje å setja utlaupsdato", -"Sending ..." => "Sender …", -"Email sent" => "E-post sendt", -"The update was unsuccessful. Please report this issue to the ownCloud community." => "Oppdateringa feila. Ver venleg og rapporter feilen til ownCloud-fellesskapet.", -"The update was successful. Redirecting you to ownCloud now." => "Oppdateringa er fullført. Sender deg vidare til ownCloud no.", -"ownCloud password reset" => "Nullstilling av ownCloud-passord", -"Use the following link to reset your password: {link}" => "Klikk følgjande lenkje til å nullstilla passordet ditt: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "Lenkja til å nullstilla passordet med er sendt til e-posten din.
Sjå i spam-/søppelmappa di viss du ikkje ser e-posten innan rimeleg tid.
Spør din lokale administrator viss han ikkje er der heller.", -"Request failed!
Did you make sure your email/username was right?" => "Førespurnaden feila!
Er du viss på at du skreiv inn rett e-post/brukarnamn?", -"You will receive a link to reset your password via Email." => "Du vil få ein e-post med ei lenkje for å nullstilla passordet.", +"Use the following link to reset your password: {link}" => "Bruk føljane link til å tilbakestille passordet ditt: {link}", +"You will receive a link to reset your password via Email." => "Du vil få ei lenkje for å nullstilla passordet via epost.", "Username" => "Brukarnamn", "Request reset" => "Be om nullstilling", "Your password was reset" => "Passordet ditt er nullstilt", -"To login page" => "Til innloggingssida", +"To login page" => "Til innloggings sida", "New password" => "Nytt passord", "Reset password" => "Nullstill passord", "Personal" => "Personleg", "Users" => "Brukarar", "Apps" => "Applikasjonar", -"Admin" => "Admin", +"Admin" => "Administrer", "Help" => "Hjelp", -"Access forbidden" => "Tilgang forbudt", "Cloud not found" => "Fann ikkje skyen", -"Edit categories" => "Endra kategoriar", "Add" => "Legg til", -"Security Warning" => "Tryggleiksåtvaring", -"Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "PHP-utgåva di er sårbar for NULL-byteåtaket (CVE-2006-7243)", -"Please update your PHP installation to use ownCloud securely." => "Ver venleg og oppdater PHP-installasjonen din så han køyrer ownCloud på ein trygg måte.", -"No secure random number generator is available, please enable the PHP OpenSSL extension." => "Ingen tilgjengeleg tilfeldig nummer-generator, ver venleg og aktiver OpenSSL-utvidinga i PHP.", -"Without a secure random number generator an attacker may be able to predict password reset tokens and take over your account." => "Utan ein trygg tilfeldig nummer-generator er det enklare for ein åtakar å gjetta seg fram til passordnullstillingskodar og dimed ta over kontoen din.", -"Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Datamappa og filene dine er sannsynlegvis tilgjengelege frå Internett sidan .htaccess-fila ikkje fungerer.", -"For information how to properly configure your server, please see the documentation." => "Ver venleg og les dokumentasjonen for å læra korleis du set opp tenaren din på rett måte.", "Create an admin account" => "Lag ein admin-konto", "Advanced" => "Avansert", "Data folder" => "Datamappe", @@ -121,19 +45,13 @@ "Database user" => "Databasebrukar", "Database password" => "Databasepassord", "Database name" => "Databasenamn", -"Database tablespace" => "Tabellnamnrom for database", "Database host" => "Databasetenar", "Finish setup" => "Fullfør oppsettet", -"web services under your control" => "Vevtenester under din kontroll", +"web services under your control" => "Vev tjenester under din kontroll", "Log out" => "Logg ut", -"Automatic logon rejected!" => "Automatisk innlogging avvist!", -"If you did not change your password recently, your account may be compromised!" => "Viss du ikkje endra passordet ditt nyleg, så kan kontoen din vera kompromittert!", -"Please change your password to secure your account again." => "Ver venleg og endra passordet for å gjera kontoen din trygg igjen.", "Lost your password?" => "Gløymt passordet?", "remember" => "hugs", "Log in" => "Logg inn", -"Alternative Logins" => "Alternative innloggingar", "prev" => "førre", -"next" => "neste", -"Updating ownCloud to version %s, this may take a while." => "Oppdaterer ownCloud til utgåve %s, dette kan ta ei stund." +"next" => "neste" ); diff --git a/core/l10n/oc.php b/core/l10n/oc.php index a384b0315b..ec432d495a 100644 --- a/core/l10n/oc.php +++ b/core/l10n/oc.php @@ -8,16 +8,16 @@ "Thursday" => "Dijòus", "Friday" => "Divendres", "Saturday" => "Dissabte", -"January" => "genièr", -"February" => "febrièr", -"March" => "març", -"April" => "abril", -"May" => "mai", -"June" => "junh", -"July" => "julhet", -"August" => "agost", -"September" => "septembre", -"October" => "octobre", +"January" => "Genièr", +"February" => "Febrièr", +"March" => "Març", +"April" => "Abril", +"May" => "Mai", +"June" => "Junh", +"July" => "Julhet", +"August" => "Agost", +"September" => "Septembre", +"October" => "Octobre", "November" => "Novembre", "December" => "Decembre", "Settings" => "Configuracion", @@ -30,7 +30,7 @@ "last year" => "an passat", "years ago" => "ans a", "Ok" => "D'accòrdi", -"Cancel" => "Annula", +"Cancel" => "Anulla", "Choose" => "Causís", "Yes" => "Òc", "No" => "Non", @@ -48,7 +48,7 @@ "Share via email:" => "Parteja tras corrièl :", "No people found" => "Deguns trobat", "Resharing is not allowed" => "Tornar partejar es pas permis", -"Unshare" => "Pas partejador", +"Unshare" => "Non parteje", "can edit" => "pòt modificar", "access control" => "Contraròtle d'acces", "create" => "crea", @@ -61,11 +61,11 @@ "ownCloud password reset" => "senhal d'ownCloud tornat botar", "Use the following link to reset your password: {link}" => "Utiliza lo ligam seguent per tornar botar lo senhal : {link}", "You will receive a link to reset your password via Email." => "Reçaupràs un ligam per tornar botar ton senhal via corrièl.", -"Username" => "Non d'usancièr", +"Username" => "Nom d'usancièr", "Request reset" => "Tornar botar requesit", "Your password was reset" => "Ton senhal es estat tornat botar", "To login page" => "Pagina cap al login", -"New password" => "Senhal novèl", +"New password" => "Senhal nòu", "Reset password" => "Senhal tornat botar", "Personal" => "Personal", "Users" => "Usancièrs", diff --git a/core/l10n/pl.php b/core/l10n/pl.php index 22cc24cd51..2821bf77ee 100644 --- a/core/l10n/pl.php +++ b/core/l10n/pl.php @@ -89,6 +89,8 @@ "ownCloud password reset" => "restart hasła ownCloud", "Use the following link to reset your password: {link}" => "Użyj tego odnośnika by zresetować hasło: {link}", "You will receive a link to reset your password via Email." => "Odnośnik służący do resetowania hasła zostanie wysłany na adres e-mail.", +"Reset email send." => "Wysłano e-mail resetujący.", +"Request failed!" => "Żądanie nieudane!", "Username" => "Nazwa użytkownika", "Request reset" => "Żądanie resetowania", "Your password was reset" => "Zresetowano hasło", @@ -122,7 +124,7 @@ "Database tablespace" => "Obszar tabel bazy danych", "Database host" => "Komputer bazy danych", "Finish setup" => "Zakończ konfigurowanie", -"web services under your control" => "Kontrolowane serwisy", +"web services under your control" => "usługi internetowe pod kontrolą", "Log out" => "Wyloguj", "Automatic logon rejected!" => "Automatyczne logowanie odrzucone!", "If you did not change your password recently, your account may be compromised!" => "Jeśli hasło było dawno niezmieniane, twoje konto może być zagrożone!", diff --git a/core/l10n/pt_BR.php b/core/l10n/pt_BR.php index ee1ac44d02..e5acd4da8f 100644 --- a/core/l10n/pt_BR.php +++ b/core/l10n/pt_BR.php @@ -9,7 +9,7 @@ "Object type not provided." => "tipo de objeto não fornecido.", "%s ID not provided." => "%s ID não fornecido(s).", "Error adding %s to favorites." => "Erro ao adicionar %s aos favoritos.", -"No categories selected for deletion." => "Nenhuma categoria selecionada para remoção.", +"No categories selected for deletion." => "Nenhuma categoria selecionada para excluir.", "Error removing %s from favorites." => "Erro ao remover %s dos favoritos.", "Sunday" => "Domingo", "Monday" => "Segunda-feira", @@ -30,7 +30,7 @@ "October" => "outubro", "November" => "novembro", "December" => "dezembro", -"Settings" => "Ajustes", +"Settings" => "Configurações", "seconds ago" => "segundos atrás", "1 minute ago" => "1 minuto atrás", "{minutes} minutes ago" => "{minutes} minutos atrás", @@ -88,10 +88,10 @@ "The update was successful. Redirecting you to ownCloud now." => "A atualização teve êxito. Você será redirecionado ao ownCloud agora.", "ownCloud password reset" => "Redefinir senha ownCloud", "Use the following link to reset your password: {link}" => "Use o seguinte link para redefinir sua senha: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "O link para redefinir sua senha foi enviada para o seu e-mail.
Se você não recebê-lo dentro de um período razoável de tempo, verifique o spam/lixo.
Se ele não estiver lá perguntar ao seu administrador local.", -"Request failed!
Did you make sure your email/username was right?" => "O pedido falhou!
Certifique-se que seu e-mail/username estavam corretos?", "You will receive a link to reset your password via Email." => "Você receberá um link para redefinir sua senha por e-mail.", -"Username" => "Nome de usuário", +"Reset email send." => "Email de redefinição de senha enviado.", +"Request failed!" => "A requisição falhou!", +"Username" => "Nome de Usuário", "Request reset" => "Pedir redefinição", "Your password was reset" => "Sua senha foi redefinida", "To login page" => "Para a página de login", @@ -99,7 +99,7 @@ "Reset password" => "Redefinir senha", "Personal" => "Pessoal", "Users" => "Usuários", -"Apps" => "Aplicações", +"Apps" => "Apps", "Admin" => "Admin", "Help" => "Ajuda", "Access forbidden" => "Acesso proibido", diff --git a/core/l10n/pt_PT.php b/core/l10n/pt_PT.php index 0b2af90d1d..67d43e372a 100644 --- a/core/l10n/pt_PT.php +++ b/core/l10n/pt_PT.php @@ -9,7 +9,7 @@ "Object type not provided." => "Tipo de objecto não fornecido", "%s ID not provided." => "ID %s não fornecido", "Error adding %s to favorites." => "Erro a adicionar %s aos favoritos", -"No categories selected for deletion." => "Nenhuma categoria seleccionada para eliminar.", +"No categories selected for deletion." => "Nenhuma categoria seleccionada para apagar", "Error removing %s from favorites." => "Erro a remover %s dos favoritos.", "Sunday" => "Domingo", "Monday" => "Segunda", @@ -30,11 +30,11 @@ "October" => "Outubro", "November" => "Novembro", "December" => "Dezembro", -"Settings" => "Configurações", +"Settings" => "Definições", "seconds ago" => "Minutos atrás", "1 minute ago" => "Há 1 minuto", "{minutes} minutes ago" => "{minutes} minutos atrás", -"1 hour ago" => "Há 1 horas", +"1 hour ago" => "Há 1 hora", "{hours} hours ago" => "Há {hours} horas atrás", "today" => "hoje", "yesterday" => "ontem", @@ -63,7 +63,7 @@ "Share with" => "Partilhar com", "Share with link" => "Partilhar com link", "Password protect" => "Proteger com palavra-passe", -"Password" => "Password", +"Password" => "Palavra chave", "Email link to person" => "Enviar o link por e-mail", "Send" => "Enviar", "Set expiration date" => "Especificar data de expiração", @@ -89,11 +89,13 @@ "ownCloud password reset" => "Reposição da password ownCloud", "Use the following link to reset your password: {link}" => "Use o seguinte endereço para repor a sua password: {link}", "You will receive a link to reset your password via Email." => "Vai receber um endereço para repor a sua password", -"Username" => "Nome de utilizador", +"Reset email send." => "E-mail de reinicialização enviado.", +"Request failed!" => "O pedido falhou!", +"Username" => "Utilizador", "Request reset" => "Pedir reposição", "Your password was reset" => "A sua password foi reposta", "To login page" => "Para a página de entrada", -"New password" => "Nova palavra-chave", +"New password" => "Nova password", "Reset password" => "Repor password", "Personal" => "Pessoal", "Users" => "Utilizadores", diff --git a/core/l10n/ro.php b/core/l10n/ro.php index 36ee8ab4b6..51c1523d7e 100644 --- a/core/l10n/ro.php +++ b/core/l10n/ro.php @@ -5,7 +5,6 @@ "User %s shared the folder \"%s\" with you. It is available for download here: %s" => "Utilizatorul %s a partajat dosarul \"%s\" cu tine. Îl poți descărca de aici: %s ", "Category type not provided." => "Tipul de categorie nu este prevazut", "No category to add?" => "Nici o categorie de adăugat?", -"This category already exists: %s" => "Această categorie deja există: %s", "Object type not provided." => "Tipul obiectului nu este prevazut", "%s ID not provided." => "ID-ul %s nu a fost introdus", "Error adding %s to favorites." => "Eroare la adăugarea %s la favorite", @@ -30,7 +29,7 @@ "October" => "Octombrie", "November" => "Noiembrie", "December" => "Decembrie", -"Settings" => "Setări", +"Settings" => "Configurări", "seconds ago" => "secunde în urmă", "1 minute ago" => "1 minut în urmă", "{minutes} minutes ago" => "{minutes} minute in urma", @@ -53,7 +52,6 @@ "Error" => "Eroare", "The app name is not specified." => "Numele aplicației nu a fost specificat", "The required file {file} is not installed!" => "Fișierul obligatoriu {file} nu este instalat!", -"Shared" => "Partajat", "Share" => "Partajează", "Error while sharing" => "Eroare la partajare", "Error while unsharing" => "Eroare la anularea partajării", @@ -63,7 +61,7 @@ "Share with" => "Partajat cu", "Share with link" => "Partajare cu legătură", "Password protect" => "Protejare cu parolă", -"Password" => "Parolă", +"Password" => "Parola", "Email link to person" => "Expediază legătura prin poșta electronică", "Send" => "Expediază", "Set expiration date" => "Specifică data expirării", @@ -84,14 +82,12 @@ "Error setting expiration date" => "Eroare la specificarea datei de expirare", "Sending ..." => "Se expediază...", "Email sent" => "Mesajul a fost expediat", -"The update was unsuccessful. Please report this issue to the ownCloud community." => "Modernizarea a eșuat! Te rugam sa raportezi problema aici..", -"The update was successful. Redirecting you to ownCloud now." => "Modernizare reusita! Vei fii redirectionat!", "ownCloud password reset" => "Resetarea parolei ownCloud ", "Use the following link to reset your password: {link}" => "Folosește următorul link pentru a reseta parola: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "Linkul pentru resetarea parolei tale a fost trimis pe email.
Daca nu ai primit email-ul intr-un timp rezonabil, verifica folderul spam/junk.
Daca nu sunt acolo intreaba administratorul local.", -"Request failed!
Did you make sure your email/username was right?" => "Cerere esuata!
Esti sigur ca email-ul/numele de utilizator sunt corecte?", "You will receive a link to reset your password via Email." => "Vei primi un mesaj prin care vei putea reseta parola via email", -"Username" => "Nume utilizator", +"Reset email send." => "Resetarea emailu-lui trimisa.", +"Request failed!" => "Solicitarea nu a reusit", +"Username" => "Utilizator", "Request reset" => "Cerere trimisă", "Your password was reset" => "Parola a fost resetată", "To login page" => "Spre pagina de autentificare", @@ -100,19 +96,15 @@ "Personal" => "Personal", "Users" => "Utilizatori", "Apps" => "AplicaÈ›ii", -"Admin" => "Admin", +"Admin" => "Administrator", "Help" => "Ajutor", "Access forbidden" => "Acces interzis", "Cloud not found" => "Nu s-a găsit", -"Edit categories" => "Editează categorii", +"Edit categories" => "Editează categoriile", "Add" => "Adaugă", "Security Warning" => "Avertisment de securitate", -"Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "Versiunea dvs. PHP este vulnerabil la acest atac un octet null (CVE-2006-7243)", -"Please update your PHP installation to use ownCloud securely." => "Vă rugăm să actualizaÈ›i instalarea dvs. PHP pentru a utiliza ownCloud in siguranță.", "No secure random number generator is available, please enable the PHP OpenSSL extension." => "Generatorul de numere pentru securitate nu este disponibil, va rog activati extensia PHP OpenSSL", "Without a secure random number generator an attacker may be able to predict password reset tokens and take over your account." => "Fara generatorul pentru numere de securitate , un atacator poate afla parola si reseta contul tau", -"Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Directorul de date È™i fiÈ™iere sunt, probabil, accesibile de pe Internet, deoarece .htaccess nu funcÈ›ionează.", -"For information how to properly configure your server, please see the documentation." => "Pentru informatii despre configurarea corecta a serverului accesati pagina Documentare.", "Create an admin account" => "Crează un cont de administrator", "Advanced" => "Avansat", "Data folder" => "Director date", @@ -132,7 +124,6 @@ "Lost your password?" => "Ai uitat parola?", "remember" => "aminteÈ™te", "Log in" => "Autentificare", -"Alternative Logins" => "Conectări alternative", "prev" => "precedentul", "next" => "următorul", "Updating ownCloud to version %s, this may take a while." => "Actualizăm ownCloud la versiunea %s, aceasta poate dura câteva momente." diff --git a/core/l10n/ru.php b/core/l10n/ru.php index 54a0b94ec9..0625a5d11d 100644 --- a/core/l10n/ru.php +++ b/core/l10n/ru.php @@ -30,7 +30,7 @@ "October" => "ОктÑбрь", "November" => "ÐоÑбрь", "December" => "Декабрь", -"Settings" => "КонфигурациÑ", +"Settings" => "ÐаÑтройки", "seconds ago" => "неÑколько Ñекунд назад", "1 minute ago" => "1 минуту назад", "{minutes} minutes ago" => "{minutes} минут назад", @@ -45,7 +45,7 @@ "last year" => "в прошлом году", "years ago" => "неÑколько лет назад", "Ok" => "Ок", -"Cancel" => "Отменить", +"Cancel" => "Отмена", "Choose" => "Выбрать", "Yes" => "Да", "No" => "Ðет", @@ -88,9 +88,9 @@ "The update was successful. Redirecting you to ownCloud now." => "Обновление прошло уÑпешно. ПеренаправлÑемÑÑ Ð² Ваш ownCloud...", "ownCloud password reset" => "Ð¡Ð±Ñ€Ð¾Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ ", "Use the following link to reset your password: {link}" => "ИÑпользуйте Ñледующую ÑÑылку чтобы ÑброÑить пароль: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "СÑылка Ð´Ð»Ñ ÑброÑа Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð±Ñ‹Ð»Ð° отправлена ​​по Ñлектронной почте.
ЕÑли вы не получите его в пределах одной двух минут, проверьте папку Ñпам.
ЕÑли Ñто не возможно, обратитеÑÑŒ к Вашему админиÑтратору.", -"Request failed!
Did you make sure your email/username was right?" => "Что-то не так. Ð’Ñ‹ уверены что Email / Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ñ‹ верно?", "You will receive a link to reset your password via Email." => "Ðа ваш Ð°Ð´Ñ€ÐµÑ Email выÑлана ÑÑылка Ð´Ð»Ñ ÑброÑа паролÑ.", +"Reset email send." => "Отправка пиÑьма Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸ÐµÐ¹ Ð´Ð»Ñ ÑброÑа.", +"Request failed!" => "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ðµ удалÑÑ!", "Username" => "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ", "Request reset" => "ЗапроÑить ÑброÑ", "Your password was reset" => "Ваш пароль был Ñброшен", @@ -100,11 +100,11 @@ "Personal" => "Личное", "Users" => "Пользователи", "Apps" => "ПриложениÑ", -"Admin" => "Admin", +"Admin" => "ÐдминиÑтратор", "Help" => "Помощь", "Access forbidden" => "ДоÑтуп запрещён", "Cloud not found" => "Облако не найдено", -"Edit categories" => "Редактировать категрии", +"Edit categories" => "Редактировать категории", "Add" => "Добавить", "Security Warning" => "Предупреждение безопаÑноÑти", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "Ваша верÑÐ¸Ñ PHP уÑзвима к атаке NULL Byte (CVE-2006-7243)", @@ -124,7 +124,7 @@ "Database tablespace" => "Табличое проÑтранÑтво базы данных", "Database host" => "ХоÑÑ‚ базы данных", "Finish setup" => "Завершить уÑтановку", -"web services under your control" => "веб-ÑервиÑÑ‹ под вашим управлением", +"web services under your control" => "Сетевые Ñлужбы под твоим контролем", "Log out" => "Выйти", "Automatic logon rejected!" => "ÐвтоматичеÑкий вход в ÑиÑтему отключен!", "If you did not change your password recently, your account may be compromised!" => "ЕÑли Ð’Ñ‹ недавно не менÑли Ñвой пароль, то Ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ может быть Ñкомпрометирована!", diff --git a/core/l10n/ru_RU.php b/core/l10n/ru_RU.php index 8fb568aee7..1afb9e20c9 100644 --- a/core/l10n/ru_RU.php +++ b/core/l10n/ru_RU.php @@ -1,3 +1,137 @@ "ÐаÑтройки" +"User %s shared a file with you" => "Пользователь %s открыл Вам доÑтуп к файлу", +"User %s shared a folder with you" => "Пользователь %s открыл Вам доÑтуп к папке", +"User %s shared the file \"%s\" with you. It is available for download here: %s" => "Пользователь %s открыл Вам доÑтуп к файлу \"%s\". Он доÑтупен Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ здеÑÑŒ: %s", +"User %s shared the folder \"%s\" with you. It is available for download here: %s" => "Пользователь %s открыл Вам доÑтуп к папке \"%s\". Она доÑтупена Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ здеÑÑŒ: %s", +"Category type not provided." => "Тип категории не предоÑтавлен.", +"No category to add?" => "Ðет категории Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ?", +"This category already exists: %s" => "Эта ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ð¸Ñ ÑƒÐ¶Ðµ ÑущеÑтвует: %s", +"Object type not provided." => "Тип объекта не предоÑтавлен.", +"%s ID not provided." => "%s ID не предоÑтавлен.", +"Error adding %s to favorites." => "Ошибка Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ %s в избранное.", +"No categories selected for deletion." => "Ðет категорий, выбранных Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ.", +"Error removing %s from favorites." => "Ошибка ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ %s из избранного.", +"Sunday" => "ВоÑкреÑенье", +"Monday" => "Понедельник", +"Tuesday" => "Вторник", +"Wednesday" => "Среда", +"Thursday" => "Четверг", +"Friday" => "ПÑтница", +"Saturday" => "Суббота", +"January" => "Январь", +"February" => "Февраль", +"March" => "Март", +"April" => "Ðпрель", +"May" => "Май", +"June" => "Июнь", +"July" => "Июль", +"August" => "ÐвгуÑÑ‚", +"September" => "СентÑбрь", +"October" => "ОктÑбрь", +"November" => "ÐоÑбрь", +"December" => "Декабрь", +"Settings" => "ÐаÑтройки", +"seconds ago" => "Ñекунд назад", +"1 minute ago" => " 1 минуту назад", +"{minutes} minutes ago" => "{минуты} минут назад", +"1 hour ago" => "1 Ñ‡Ð°Ñ Ð½Ð°Ð·Ð°Ð´", +"{hours} hours ago" => "{чаÑÑ‹} чаÑов назад", +"today" => "ÑегоднÑ", +"yesterday" => "вчера", +"{days} days ago" => "{дни} дней назад", +"last month" => "в прошлом меÑÑце", +"{months} months ago" => "{меÑÑцы} меÑÑцев назад", +"months ago" => "меÑÑц назад", +"last year" => "в прошлом году", +"years ago" => "лет назад", +"Ok" => "Да", +"Cancel" => "Отмена", +"Choose" => "Выбрать", +"Yes" => "Да", +"No" => "Ðет", +"The object type is not specified." => "Тип объекта не указан.", +"Error" => "Ошибка", +"The app name is not specified." => "Ð˜Ð¼Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½Ðµ указано.", +"The required file {file} is not installed!" => "Требуемый файл {файл} не уÑтановлен!", +"Shared" => "Опубликовано", +"Share" => "Сделать общим", +"Error while sharing" => "Ошибка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±Ñ‰ÐµÐ³Ð¾ доÑтупа", +"Error while unsharing" => "Ошибка Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ‰ÐµÐ³Ð¾ доÑтупа", +"Error while changing permissions" => "Ошибка при изменении прав доÑтупа", +"Shared with you and the group {group} by {owner}" => "Опубликовано Ð´Ð»Ñ Ð’Ð°Ñ Ð¸ группы {группа} {ÑобÑтвенник}", +"Shared with you by {owner}" => "Опубликовано Ð´Ð»Ñ Ð’Ð°Ñ {ÑобÑтвенник}", +"Share with" => "Сделать общим Ñ", +"Share with link" => "Опубликовать Ñ ÑÑылкой", +"Password protect" => "Защитить паролем", +"Password" => "Пароль", +"Email link to person" => "СÑылка на Ð°Ð´Ñ€ÐµÑ Ñлектронной почты", +"Send" => "Отправить", +"Set expiration date" => "УÑтановить Ñрок дейÑтвиÑ", +"Expiration date" => "Дата иÑÑ‚ÐµÑ‡ÐµÐ½Ð¸Ñ Ñрока дейÑтвиÑ", +"Share via email:" => "Сделать общедоÑтупным поÑредÑтвом email:", +"No people found" => "Ðе найдено людей", +"Resharing is not allowed" => "РекурÑивный общий доÑтуп не разрешен", +"Shared in {item} with {user}" => "СовмеÑтное иÑпользование в {объект} Ñ {пользователь}", +"Unshare" => "Отключить общий доÑтуп", +"can edit" => "возможно редактирование", +"access control" => "контроль доÑтупа", +"create" => "Ñоздать", +"update" => "обновить", +"delete" => "удалить", +"share" => "Ñделать общим", +"Password protected" => "Пароль защищен", +"Error unsetting expiration date" => "Ошибка при отключении даты иÑÑ‚ÐµÑ‡ÐµÐ½Ð¸Ñ Ñрока дейÑтвиÑ", +"Error setting expiration date" => "Ошибка при уÑтановке даты иÑÑ‚ÐµÑ‡ÐµÐ½Ð¸Ñ Ñрока дейÑтвиÑ", +"Sending ..." => "Отправка ...", +"Email sent" => "ПиÑьмо отправлено", +"The update was unsuccessful. Please report this issue to the ownCloud community." => "Обновление прошло неудачно. ПожалуйÑта, Ñообщите об Ñтом результате в ownCloud community.", +"The update was successful. Redirecting you to ownCloud now." => "Обновление прошло уÑпешно. Ðемедленное перенаправление Ð’Ð°Ñ Ð½Ð° ownCloud.", +"ownCloud password reset" => "Переназначение паролÑ", +"Use the following link to reset your password: {link}" => "ВоÑпользуйтеÑÑŒ Ñледующей ÑÑылкой Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ: {link}", +"You will receive a link to reset your password via Email." => "Ð’Ñ‹ получите ÑÑылку Ð´Ð»Ñ Ð²Ð¾ÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð¿Ð¾ Ñлектронной почте.", +"Reset email send." => "Ð¡Ð±Ñ€Ð¾Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸ email.", +"Request failed!" => "Ðе удалоÑÑŒ выполнить запроÑ!", +"Username" => "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ", +"Request reset" => "Ð¡Ð±Ñ€Ð¾Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа", +"Your password was reset" => "Ваш пароль был переуÑтановлен", +"To login page" => "Ðа Ñтраницу входа", +"New password" => "Ðовый пароль", +"Reset password" => "Переназначение паролÑ", +"Personal" => "ПерÑональный", +"Users" => "Пользователи", +"Apps" => "ПриложениÑ", +"Admin" => "ÐдминиÑтратор", +"Help" => "Помощь", +"Access forbidden" => "ДоÑтуп запрещен", +"Cloud not found" => "Облако не найдено", +"Edit categories" => "Редактирование категорий", +"Add" => "Добавить", +"Security Warning" => "Предупреждение ÑиÑтемы безопаÑноÑти", +"No secure random number generator is available, please enable the PHP OpenSSL extension." => "Ðет доÑтупного защищенного генератора Ñлучайных чиÑел, пожалуйÑта, включите раÑширение PHP OpenSSL.", +"Without a secure random number generator an attacker may be able to predict password reset tokens and take over your account." => "Без защищенного генератора Ñлучайных чиÑел злоумышленник может Ñпрогнозировать пароль, ÑброÑить учетные данные и завладеть Вашим аккаунтом.", +"Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Ваша папка Ñ Ð´Ð°Ð½Ð½Ñ‹Ð¼Ð¸ и файлы возможно доÑтупны из интернета потому что файл .htaccess не работает.", +"For information how to properly configure your server, please see the documentation." => "Ð”Ð»Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¸ как правильно наÑтроить Ваш Ñервер, пожалйÑта заглÑните в документацию.", +"Create an admin account" => "Создать admin account", +"Advanced" => "РаÑширенный", +"Data folder" => "Папка данных", +"Configure the database" => "ÐаÑтроить базу данных", +"will be used" => "будет иÑпользоватьÑÑ", +"Database user" => "Пользователь базы данных", +"Database password" => "Пароль базы данных", +"Database name" => "Ð˜Ð¼Ñ Ð±Ð°Ð·Ñ‹ данных", +"Database tablespace" => "Ð¢Ð°Ð±Ð»Ð¸Ñ‡Ð½Ð°Ñ Ð¾Ð±Ð»Ð°ÑÑ‚ÑŒ базы данных", +"Database host" => "Сервер базы данных", +"Finish setup" => "Завершение наÑтройки", +"web services under your control" => "веб-ÑервиÑÑ‹ под Вашим контролем", +"Log out" => "Выйти", +"Automatic logon rejected!" => "ÐвтоматичеÑкий вход в ÑиÑтему отклонен!", +"If you did not change your password recently, your account may be compromised!" => "ЕÑли Ð’Ñ‹ недавно не менÑли пароль, Ваш аккаунт может быть подвергнут опаÑноÑти!", +"Please change your password to secure your account again." => "ПожалуйÑта, измените пароль, чтобы защитить ваш аккаунт еще раз.", +"Lost your password?" => "Забыли пароль?", +"remember" => "запомнить", +"Log in" => "Войти", +"Alternative Logins" => "Ðльтернативные Имена", +"prev" => "предыдущий", +"next" => "Ñледующий", +"Updating ownCloud to version %s, this may take a while." => "Обновление ownCloud до верÑии %s, Ñто может занÑÑ‚ÑŒ некоторое времÑ." ); diff --git a/core/l10n/si_LK.php b/core/l10n/si_LK.php index c1e8ba37ed..dc9801139a 100644 --- a/core/l10n/si_LK.php +++ b/core/l10n/si_LK.php @@ -16,10 +16,10 @@ "July" => "ජූලි", "August" => "අගà·à·ƒà·Šà¶­à·”", "September" => "à·ƒà·à¶´à·Šà¶­à·à¶¸à·Šà¶¶à¶»à·Š", -"October" => "ඔක්තà·à¶¶à¶»", +"October" => "ඔක්තà·à¶¶à¶»à·Š", "November" => "නොවà·à¶¸à·Šà¶¶à¶»à·Š", "December" => "දෙසà·à¶¸à·Šà¶¶à¶»à·Š", -"Settings" => "සිටුවම්", +"Settings" => "à·ƒà·à¶šà·ƒà·”ම්", "seconds ago" => "තත්පරයන්ට පෙර", "1 minute ago" => "1 මිනිත්තුවකට පෙර", "today" => "අද", @@ -32,13 +32,13 @@ "Cancel" => "එපà·", "Choose" => "තà·à¶»à¶±à·Šà¶±", "Yes" => "ඔව්", -"No" => "එපà·", +"No" => "නà·à·„à·", "Error" => "දà·à·‚යක්", "Share" => "බෙද෠හද෠ගන්න", "Share with" => "බෙදà·à¶œà¶±à·Šà¶±", "Share with link" => "යොමුවක් මඟින් බෙදà·à¶œà¶±à·Šà¶±", "Password protect" => "මුර පදයකින් ආරක්à·à·à¶šà¶»à¶±à·Šà¶±", -"Password" => "මුර පදය", +"Password" => "මුර පදය ", "Set expiration date" => "කල් ඉකුත් විමේ දිනය දමන්න", "Expiration date" => "කල් ඉකුත් විමේ දිනය", "Share via email:" => "විද්â€à¶ºà·”ත් තà·à¶´à·‘ල මඟින් බෙදà·à¶œà¶±à·Šà¶±: ", @@ -54,10 +54,11 @@ "Error setting expiration date" => "කල් ඉකුත් දිනය ස්ථà·à¶´à¶±à¶º කිරීමේ දà·à·‚යක්", "ownCloud password reset" => "ownCloud මුරපදය ප්â€à¶»à¶­à·Šâ€à¶ºà·à¶»à¶¸à·Šà¶· කරන්න", "You will receive a link to reset your password via Email." => "ඔබගේ මුරපදය ප්â€à¶»à¶­à·Šâ€à¶ºà·à¶»à¶¸à·Šà¶· කිරීම සඳහ෠යොමුව විද්â€à¶ºà·”ත් තà·à¶´à·‘ලෙන් ලà·à¶¶à·™à¶±à·” ඇත", +"Request failed!" => "ඉල්ලීම අසà·à¶»à·Šà¶®à¶šà¶ºà·’!", "Username" => "පරිà·à·“ලක නම", "Your password was reset" => "ඔබේ මුරපදය ප්â€à¶»à¶­à·Šâ€à¶ºà·à¶»à¶¸à·Šà¶· කරන ලදී", "To login page" => "පිවිසුම් පිටුවට", -"New password" => "නව මුරපදය", +"New password" => "නව මුර පදයක්", "Reset password" => "මුරපදය ප්â€à¶»à¶­à·Šâ€à¶ºà·à¶»à¶¸à·Šà¶· කරන්න", "Personal" => "පෞද්ගලික", "Users" => "පරිà·à·“ලකයන්", @@ -67,7 +68,7 @@ "Access forbidden" => "ඇතුල් වීම තහනම්", "Cloud not found" => "සොය෠ගත නොහà·à¶š", "Edit categories" => "ප්â€à¶»à¶·à·šà¶¯à¶ºà¶±à·Š සංස්කරණය", -"Add" => "එකතු කරන්න", +"Add" => "එක් කරන්න", "Security Warning" => "ආරක්ෂක නිවේදනයක්", "Without a secure random number generator an attacker may be able to predict password reset tokens and take over your account." => "ආරක්ෂිත අහඹු සංඛ්â€à¶ºà· උත්පà·à¶¯à¶šà¶ºà¶šà·Š නොමà·à¶­à·’ නම් ඔබගේ ගිණුමට පහරදෙන අයකුට එහි මුරපද යළි පිහිටුවීමට අවà·à·Šâ€à¶º ටà·à¶šà¶± පහසුවෙන් සොයà·à¶œà·™à¶± ඔබගේ ගිණුම පà·à·„à·à¶»à¶œà¶­ à·„à·à¶š.", "Advanced" => "දියුණු/උසස්", diff --git a/core/l10n/sk_SK.php b/core/l10n/sk_SK.php index d9f124b2b4..b52c8b03c4 100644 --- a/core/l10n/sk_SK.php +++ b/core/l10n/sk_SK.php @@ -34,7 +34,7 @@ "seconds ago" => "pred sekundami", "1 minute ago" => "pred minútou", "{minutes} minutes ago" => "pred {minutes} minútami", -"1 hour ago" => "Pred 1 hodinou", +"1 hour ago" => "Pred 1 hodinou.", "{hours} hours ago" => "Pred {hours} hodinami.", "today" => "dnes", "yesterday" => "vÄera", @@ -88,10 +88,10 @@ "The update was successful. Redirecting you to ownCloud now." => "Aktualizácia bola úspeÅ¡ná. Presmerovávam na prihlasovaciu stránku.", "ownCloud password reset" => "Obnovenie hesla pre ownCloud", "Use the following link to reset your password: {link}" => "Použite nasledujúci odkaz pre obnovenie vášho hesla: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "Odkaz na obnovenie hesla bol odoslaný na Vašu emailovú adresu.
Ak ho v krátkej dobe neobdržíte, skontrolujte si Váš kôš a prieÄinok spam.
Ak ho ani tam nenájdete, kontaktujte svojho administrátora.", -"Request failed!
Did you make sure your email/username was right?" => "Požiadavka zlyhala.
Uistili ste sa, že VaÅ¡e používateľské meno a email sú správne?", "You will receive a link to reset your password via Email." => "Odkaz pre obnovenie hesla obdržíte e-mailom.", -"Username" => "Meno používateľa", +"Reset email send." => "Obnovovací email bol odoslaný.", +"Request failed!" => "Požiadavka zlyhala!", +"Username" => "Prihlasovacie meno", "Request reset" => "PožiadaÅ¥ o obnovenie", "Your password was reset" => "VaÅ¡e heslo bolo obnovené", "To login page" => "Na prihlasovaciu stránku", @@ -100,11 +100,11 @@ "Personal" => "Osobné", "Users" => "Používatelia", "Apps" => "Aplikácie", -"Admin" => "Administrátor", +"Admin" => "Administrácia", "Help" => "Pomoc", "Access forbidden" => "Prístup odmietnutý", "Cloud not found" => "Nenájdené", -"Edit categories" => "UpraviÅ¥ kategórie", +"Edit categories" => "Úprava kategórií", "Add" => "PridaÅ¥", "Security Warning" => "BezpeÄnostné varovanie", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "Verzia Vášho PHP je napadnuteľná pomocou techniky \"NULL Byte\" (CVE-2006-7243)", @@ -124,7 +124,7 @@ "Database tablespace" => "Tabuľkový priestor databázy", "Database host" => "Server databázy", "Finish setup" => "DokonÄiÅ¥ inÅ¡taláciu", -"web services under your control" => "webové služby pod VaÅ¡ou kontrolou", +"web services under your control" => "webové služby pod vaÅ¡ou kontrolou", "Log out" => "OdhlásiÅ¥", "Automatic logon rejected!" => "Automatické prihlásenie bolo zamietnuté!", "If you did not change your password recently, your account may be compromised!" => "V nedávnej dobe ste nezmenili svoje heslo, Váš úÄet môže byÅ¥ kompromitovaný.", diff --git a/core/l10n/sl.php b/core/l10n/sl.php index db5583c610..b3cd5c353c 100644 --- a/core/l10n/sl.php +++ b/core/l10n/sl.php @@ -34,7 +34,7 @@ "seconds ago" => "pred nekaj sekundami", "1 minute ago" => "pred minuto", "{minutes} minutes ago" => "pred {minutes} minutami", -"1 hour ago" => "Pred 1 uro", +"1 hour ago" => "pred 1 uro", "{hours} hours ago" => "pred {hours} urami", "today" => "danes", "yesterday" => "vÄeraj", @@ -72,7 +72,7 @@ "No people found" => "Ni najdenih uporabnikov", "Resharing is not allowed" => "Nadaljnja souporaba ni dovoljena", "Shared in {item} with {user}" => "V souporabi v {item} z {user}", -"Unshare" => "PrekliÄi souporabo", +"Unshare" => "Odstrani souporabo", "can edit" => "lahko ureja", "access control" => "nadzor dostopa", "create" => "ustvari", @@ -88,10 +88,10 @@ "The update was successful. Redirecting you to ownCloud now." => "Posodobitev je uspeÅ¡no konÄana. Stran bo preusmerjena na oblak ownCloud.", "ownCloud password reset" => "Ponastavitev gesla za oblak ownCloud", "Use the following link to reset your password: {link}" => "Za ponastavitev gesla uporabite povezavo: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "Povezava za ponastavitev gesla je bila poslana na elektronski naslov.
V kolikor sporoÄila ne prejmete v doglednem Äasu, preverite tudi mape vsiljene poÅ¡te.
ÄŒe ne bo niti tam, stopite v stik s skrbnikom.", -"Request failed!
Did you make sure your email/username was right?" => "Zahteva je spodletela!
Ali sta elektronski naslov oziroma uporabniÅ¡ko ime navedena pravilno?", "You will receive a link to reset your password via Email." => "Na elektronski naslov boste prejeli povezavo za ponovno nastavitev gesla.", -"Username" => "UporabniÅ¡ko ime", +"Reset email send." => "SporoÄilo z navodili za ponastavitev gesla je poslana na vaÅ¡ elektronski naslov.", +"Request failed!" => "Zahteva je spodletela!", +"Username" => "UporabniÅ¡ko Ime", "Request reset" => "Zahtevaj ponovno nastavitev", "Your password was reset" => "Geslo je ponovno nastavljeno", "To login page" => "Na prijavno stran", diff --git a/core/l10n/sq.php b/core/l10n/sq.php index 8769a833e1..6881d0105c 100644 --- a/core/l10n/sq.php +++ b/core/l10n/sq.php @@ -30,7 +30,7 @@ "October" => "Tetor", "November" => "Nëntor", "December" => "Dhjetor", -"Settings" => "Parametra", +"Settings" => "Parametrat", "seconds ago" => "sekonda më parë", "1 minute ago" => "1 minutë më parë", "{minutes} minutes ago" => "{minutes} minuta më parë", @@ -88,9 +88,9 @@ "The update was successful. Redirecting you to ownCloud now." => "Azhurnimi u krye. Tani do t'ju kaloj tek ownCloud-i.", "ownCloud password reset" => "Rivendosja e kodit të ownCloud-it", "Use the following link to reset your password: {link}" => "Përdorni lidhjen në vijim për të rivendosur kodin: {link}", -"The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator ." => "Lidhja për rivendosjen e kodit tuaj u dërgua tek email-i juaj.
Nëqoftëse nuk e merrni brenda një kohe të arsyeshme, kontrolloni dosjet e postës së padëshirueshme (spam).
Nëqoftëse nuk është as aty, pyesni administratorin tuaj lokal.", -"Request failed!
Did you make sure your email/username was right?" => "Kërkesa dështoi!
A u siguruat që email-i/përdoruesi juaj ishte i saktë?", "You will receive a link to reset your password via Email." => "Do t'iu vijë një email që përmban një lidhje për ta rivendosur kodin.", +"Reset email send." => "Emaili i rivendosjes u dërgua.", +"Request failed!" => "Kërkesa dështoi!", "Username" => "Përdoruesi", "Request reset" => "Bëj kërkesë për rivendosjen", "Your password was reset" => "Kodi yt u rivendos", diff --git a/core/l10n/sr.php b/core/l10n/sr.php index 2329dc49b1..b71d8cdd94 100644 --- a/core/l10n/sr.php +++ b/core/l10n/sr.php @@ -27,7 +27,7 @@ "October" => "Октобар", "November" => "Ðовембар", "December" => "Децембар", -"Settings" => "ПоÑтавке", +"Settings" => "Подешавања", "seconds ago" => "пре неколико Ñекунди", "1 minute ago" => "пре 1 минут", "{minutes} minutes ago" => "пре {minutes} минута", @@ -50,7 +50,7 @@ "Error" => "Грешка", "The app name is not specified." => "Име програма није унето.", "The required file {file} is not installed!" => "Потребна датотека {file} није инÑталирана.", -"Share" => "Дели", +"Share" => "Дељење", "Error while sharing" => "Грешка у дељењу", "Error while unsharing" => "Грешка код иÑкључења дељења", "Error while changing permissions" => "Грешка код промене дозвола", @@ -67,7 +67,7 @@ "No people found" => "ОÑобе ниÑу пронађене.", "Resharing is not allowed" => "Поновно дељење није дозвољено", "Shared in {item} with {user}" => "Подељено унутар {item} Ñа {user}", -"Unshare" => "Укини дељење", +"Unshare" => "Ðе дели", "can edit" => "може да мења", "access control" => "права приÑтупа", "create" => "направи", @@ -82,16 +82,18 @@ "ownCloud password reset" => "Поништавање лозинке за ownCloud", "Use the following link to reset your password: {link}" => "Овом везом реÑетујте Ñвоју лозинку: {link}", "You will receive a link to reset your password via Email." => "Добићете везу за реÑетовање лозинке путем е-поште.", +"Reset email send." => "Захтев је поÑлат поштом.", +"Request failed!" => "Захтев одбијен!", "Username" => "КориÑничко име", "Request reset" => "Захтевај реÑетовање", "Your password was reset" => "Ваша лозинка је реÑетована", "To login page" => "Ðа Ñтраницу за пријаву", "New password" => "Ðова лозинка", "Reset password" => "РеÑетуј лозинку", -"Personal" => "Лично", +"Personal" => "Лична", "Users" => "КориÑници", -"Apps" => "Ðпликације", -"Admin" => "ÐдминиÑтратор", +"Apps" => "Програми", +"Admin" => "ÐдниниÑтрација", "Help" => "Помоћ", "Access forbidden" => "Забрањен приÑтуп", "Cloud not found" => "Облак није нађен", diff --git a/core/l10n/sr@latin.php b/core/l10n/sr@latin.php index 238843aa17..ec3eab34e2 100644 --- a/core/l10n/sr@latin.php +++ b/core/l10n/sr@latin.php @@ -27,7 +27,7 @@ "Your password was reset" => "VaÅ¡a lozinka je resetovana", "New password" => "Nova lozinka", "Reset password" => "Resetuj lozinku", -"Personal" => "LiÄno", +"Personal" => "LiÄna", "Users" => "Korisnici", "Apps" => "Programi", "Admin" => "Adninistracija", diff --git a/core/l10n/sv.php b/core/l10n/sv.php index 26bcebdf6c..553afea5f7 100644 --- a/core/l10n/sv.php +++ b/core/l10n/sv.php @@ -89,6 +89,8 @@ "ownCloud password reset" => "ownCloud lösenordsÃ¥terställning", "Use the following link to reset your password: {link}" => "Använd följande länk för att Ã¥terställa lösenordet: {link}", "You will receive a link to reset your password via Email." => "Du fÃ¥r en länk att Ã¥terställa ditt lösenord via e-post.", +"Reset email send." => "Ã…terställ skickad e-post.", +"Request failed!" => "Begäran misslyckades!", "Username" => "Användarnamn", "Request reset" => "Begär Ã¥terställning", "Your password was reset" => "Ditt lösenord har Ã¥terställts", @@ -102,7 +104,7 @@ "Help" => "Hjälp", "Access forbidden" => "Ã…tkomst förbjuden", "Cloud not found" => "Hittade inget moln", -"Edit categories" => "Editera kategorier", +"Edit categories" => "Redigera kategorier", "Add" => "Lägg till", "Security Warning" => "Säkerhetsvarning", "Your PHP version is vulnerable to the NULL Byte attack (CVE-2006-7243)" => "Din version av PHP är sÃ¥rbar för NULL byte attack (CVE-2006-7243)", @@ -112,7 +114,7 @@ "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Din datakatalog och filer är förmodligen tillgängliga frÃ¥n Internet, eftersom .htaccess-filen inte fungerar.", "For information how to properly configure your server, please see the documentation." => "För information hur man korrekt konfigurera servern, var god se documentation.", "Create an admin account" => "Skapa ett administratörskonto", -"Advanced" => "Avancerad", +"Advanced" => "Avancerat", "Data folder" => "Datamapp", "Configure the database" => "Konfigurera databasen", "will be used" => "kommer att användas", diff --git a/core/l10n/ta_LK.php b/core/l10n/ta_LK.php index b01f8df945..b45f38627a 100644 --- a/core/l10n/ta_LK.php +++ b/core/l10n/ta_LK.php @@ -64,10 +64,10 @@ "No people found" => "நபரà¯à®•à®³à¯ யாரà¯à®®à¯ இலà¯à®²à¯ˆ", "Resharing is not allowed" => "மீளà¯à®ªà®•à®¿à®°à¯à®µà®¤à®±à¯à®•à¯ அனà¯à®®à®¤à®¿ இலà¯à®²à¯ˆ ", "Shared in {item} with {user}" => "{பயனாளரà¯} உடன௠{உரà¯à®ªà¯à®ªà®Ÿà®¿} பகிரபà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯", -"Unshare" => "பகிரபà¯à®ªà®Ÿà®¾à®¤à®¤à¯", +"Unshare" => "பகிரமà¯à®Ÿà®¿à®¯à®¾à®¤à¯", "can edit" => "தொகà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à¯à®®à¯", "access control" => "கடà¯à®Ÿà¯à®ªà¯à®ªà®¾à®Ÿà®¾à®© அணà¯à®•à®²à¯", -"create" => "உரà¯à®µà®µà®¾à®•à¯à®•à®²à¯", +"create" => "படைதà¯à®¤à®²à¯", "update" => "இறà¯à®±à¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯", "delete" => "நீகà¯à®•à¯à®•", "share" => "பகிரà¯à®¤à®²à¯", @@ -77,6 +77,8 @@ "ownCloud password reset" => "ownCloud இன௠கடவà¯à®šà¯à®šà¯Šà®²à¯ மீளமைபà¯à®ªà¯", "Use the following link to reset your password: {link}" => "உஙà¯à®•à®³à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மீளமைகà¯à®• பினà¯à®µà®°à¯à®®à¯ இணைபà¯à®ªà¯ˆ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà¯à®®à¯ : {இணைபà¯à®ªà¯}", "You will receive a link to reset your password via Email." => "நீஙà¯à®•à®³à¯ மினà¯à®©à®žà¯à®šà®²à¯ மூலம௠உஙà¯à®•à®³à¯à®Ÿà¯ˆà®¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மீளமைபà¯à®ªà®¤à®±à¯à®•à®¾à®© இணைபà¯à®ªà¯ˆ பெறà¯à®µà¯€à®°à¯à®•à®³à¯. ", +"Reset email send." => "மினà¯à®©à¯à®žà¯à®šà®²à¯ அனà¯à®ªà¯à®ªà¯à®¤à®²à¯ˆ மீளமைகà¯à®•à¯à®•", +"Request failed!" => "வேணà¯à®Ÿà¯à®•à¯‹à®³à¯ தோலà¯à®µà®¿à®¯à¯à®±à¯à®±à®¤à¯!", "Username" => "பயனாளர௠பெயரà¯", "Request reset" => "கோரிகà¯à®•à¯ˆ மீளமைபà¯à®ªà¯", "Your password was reset" => "உஙà¯à®•à®³à¯à®Ÿà¯ˆà®¯ கடவà¯à®šà¯à®šà¯Šà®²à¯ மீளமைகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯", @@ -84,9 +86,9 @@ "New password" => "பà¯à®¤à®¿à®¯ கடவà¯à®šà¯à®šà¯Šà®²à¯", "Reset password" => "மீளமைதà¯à®¤ கடவà¯à®šà¯à®šà¯Šà®²à¯", "Personal" => "தனிபà¯à®ªà®Ÿà¯à®Ÿ", -"Users" => "பயனாளரà¯", -"Apps" => "செயலிகளà¯", -"Admin" => "நிரà¯à®µà®¾à®•à®®à¯", +"Users" => "பயனாளரà¯à®•à®³à¯", +"Apps" => "பயனà¯à®ªà®¾à®Ÿà¯à®•à®³à¯", +"Admin" => "நிரà¯à®µà®¾à®•à®¿", "Help" => "உதவி", "Access forbidden" => "அணà¯à®• தடை", "Cloud not found" => "Cloud காணபà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ", @@ -96,7 +98,7 @@ "No secure random number generator is available, please enable the PHP OpenSSL extension." => "கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà¯à®Ÿ எணà¯à®£à®¿à®•à¯à®•à¯ˆ பாதà¯à®•à®¾à®ªà¯à®ªà®¾à®© பà¯à®±à®ªà¯à®ªà®¾à®•à¯à®•à®¿ / உணà¯à®Ÿà®¾à®•à¯à®•à®¿à®•à®³à¯ இலà¯à®²à¯ˆ, தயவà¯à®šà¯†à®¯à¯à®¤à¯ PHP OpenSSL நீடà¯à®šà®¿à®¯à¯ˆ இயலà¯à®®à¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®•. ", "Without a secure random number generator an attacker may be able to predict password reset tokens and take over your account." => "பாதà¯à®•à®¾à®ªà¯à®ªà®¾à®© சீரறà¯à®± எணà¯à®£à®¿à®•à¯à®•à¯ˆà®¯à®¾à®© பà¯à®±à®ªà¯à®ªà®¾à®•à¯à®•à®¿ இலà¯à®²à¯ˆà®¯à¯†à®©à®¿à®©à¯, தாகà¯à®•à¯à®©à®°à®¾à®²à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯ மீளமைபà¯à®ªà¯ அடையாளவிலà¯à®²à¯ˆà®•à®³à¯ à®®à¯à®©à¯à®®à¯Šà®´à®¿à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà¯ உஙà¯à®•à®³à¯à®Ÿà¯ˆà®¯ கணகà¯à®•à¯ˆ கைபà¯à®ªà®±à¯à®±à®²à®¾à®®à¯.", "Create an admin account" => " நிரà¯à®µà®¾à®• கணகà¯à®•à¯Šà®©à¯à®±à¯ˆ உரà¯à®µà®¾à®•à¯à®•à¯à®•", -"Advanced" => "உயரà¯à®¨à¯à®¤", +"Advanced" => "மேமà¯à®ªà®Ÿà¯à®Ÿ", "Data folder" => "தரவ௠கோபà¯à®ªà¯à®±à¯ˆ", "Configure the database" => "தரவà¯à®¤à¯à®¤à®³à®¤à¯à®¤à¯ˆ தகவமைகà¯à®•", "will be used" => "பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®®à¯", @@ -106,7 +108,7 @@ "Database tablespace" => "தரவà¯à®¤à¯à®¤à®³ அடà¯à®Ÿà®µà®£à¯ˆ", "Database host" => "தரவà¯à®¤à¯à®¤à®³ ஓமà¯à®ªà¯à®©à®°à¯", "Finish setup" => "அமைபà¯à®ªà¯ˆ à®®à¯à®Ÿà®¿à®•à¯à®•", -"web services under your control" => "வலைய சேவைகள௠உஙà¯à®•à®³à¯à®Ÿà¯ˆà®¯ கடà¯à®Ÿà¯à®ªà¯à®ªà®¾à®Ÿà¯à®Ÿà®¿à®©à¯ கீழ௠உளà¯à®³à®¤à¯", +"web services under your control" => "உஙà¯à®•à®³à¯ கடà¯à®Ÿà¯à®ªà¯à®ªà®¾à®Ÿà¯à®Ÿà®¿à®©à¯ கீழ௠இணைய சேவைகளà¯", "Log out" => "விடà¯à®ªà®¤à®¿à®•à¯ˆ செயà¯à®•", "Automatic logon rejected!" => "தனà¯à®©à®¿à®šà¯à®šà¯ˆà®¯à®¾à®© பà¯à®•à¯à®ªà®¤à®¿à®•à¯ˆ நிராகரிபà¯à®ªà®Ÿà¯à®Ÿà®¤à¯!", "If you did not change your password recently, your account may be compromised!" => "உஙà¯à®•à®³à¯à®Ÿà¯ˆà®¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ அணà¯à®®à¯ˆà®¯à®¿à®²à¯ மாறà¯à®±à®µà®¿à®²à¯à®²à¯ˆà®¯à®¿à®©à¯, உஙà¯à®•à®³à¯à®Ÿà¯ˆà®¯ கணகà¯à®•à¯ சமரசமாகிவிடà¯à®®à¯!", diff --git a/core/l10n/th_TH.php b/core/l10n/th_TH.php index 1114726434..47d4b87b17 100644 --- a/core/l10n/th_TH.php +++ b/core/l10n/th_TH.php @@ -49,7 +49,7 @@ "Yes" => "ตà¸à¸¥à¸‡", "No" => "ไม่ตà¸à¸¥à¸‡", "The object type is not specified." => "ชนิดของวัตถุยังไม่ได้รับà¸à¸²à¸£à¸£à¸°à¸šà¸¸", -"Error" => "ข้อผิดพลาด", +"Error" => "พบข้อผิดพลาด", "The app name is not specified." => "ชื่อของà¹à¸­à¸›à¸¢à¸±à¸‡à¹„ม่ได้รับà¸à¸²à¸£à¸£à¸°à¸šà¸¸à¸Šà¸·à¹ˆà¸­", "The required file {file} is not installed!" => "ไฟล์ {file} ซึ่งเป็นไฟล์ที่จำเป็นต้องได้รับà¸à¸²à¸£à¸•à¸´à¸”ตั้งไว้à¸à¹ˆà¸­à¸™ ยังไม่ได้ถูà¸à¸•à¸´à¸”ตั้ง", "Shared" => "à¹à¸Šà¸£à¹Œà¹à¸¥à¹‰à¸§", @@ -88,6 +88,8 @@ "ownCloud password reset" => "รีเซ็ตรหัสผ่าน ownCloud", "Use the following link to reset your password: {link}" => "ใช้ลิงค์ต่อไปนี้เพื่อเปลี่ยนรหัสผ่านของคุณใหม่: {link}", "You will receive a link to reset your password via Email." => "คุณจะได้รับลิงค์เพื่อà¸à¸³à¸«à¸™à¸”รหัสผ่านใหม่ทางอีเมล์", +"Reset email send." => "รีเซ็ตค่าà¸à¸²à¸£à¸ªà¹ˆà¸‡à¸­à¸µà¹€à¸¡à¸¥", +"Request failed!" => "คำร้องขอล้มเหลว!", "Username" => "ชื่อผู้ใช้งาน", "Request reset" => "ขอเปลี่ยนรหัสใหม่", "Your password was reset" => "รหัสผ่านของคุณถูà¸à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹€à¸£à¸µà¸¢à¸šà¸£à¹‰à¸­à¸¢à¹à¸¥à¹‰à¸§", @@ -96,8 +98,8 @@ "Reset password" => "เปลี่ยนรหัสผ่าน", "Personal" => "ส่วนตัว", "Users" => "ผู้ใช้งาน", -"Apps" => "à¹à¸­à¸›à¸¯", -"Admin" => "ผู้ดูà¹à¸¥", +"Apps" => "Apps", +"Admin" => "ผู้ดูà¹à¸¥à¸£à¸°à¸šà¸š", "Help" => "ช่วยเหลือ", "Access forbidden" => "à¸à¸²à¸£à¹€à¸‚้าถึงถูà¸à¸«à¸§à¸‡à¸«à¹‰à¸²à¸¡", "Cloud not found" => "ไม่พบ Cloud", @@ -117,7 +119,7 @@ "Database tablespace" => "พื้นที่ตารางในà¸à¸²à¸™à¸‚้อมูล", "Database host" => "Database host", "Finish setup" => "ติดตั้งเรียบร้อยà¹à¸¥à¹‰à¸§", -"web services under your control" => "เว็บเซอร์วิสที่คุณควบคุมà¸à¸²à¸£à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¹„ด้", +"web services under your control" => "web services under your control", "Log out" => "ออà¸à¸ˆà¸²à¸à¸£à¸°à¸šà¸š", "Automatic logon rejected!" => "à¸à¸²à¸£à¹€à¸‚้าสู่ระบบอัตโนมัติถูà¸à¸›à¸à¸´à¹€à¸ªà¸˜à¹à¸¥à¹‰à¸§", "If you did not change your password recently, your account may be compromised!" => "หาà¸à¸„ุณยังไม่ได้เปลี่ยนรหัสผ่านของคุณเมื่อเร็วๆนี้, บัà¸à¸Šà¸µà¸‚องคุณอาจถูà¸à¸šà¸¸à¸à¸£à¸¸à¸à¹‚ดยผู้อื่น", diff --git a/core/l10n/tr.php b/core/l10n/tr.php index 4b858e82e4..d6b25b4093 100644 --- a/core/l10n/tr.php +++ b/core/l10n/tr.php @@ -89,7 +89,9 @@ "ownCloud password reset" => "ownCloud parola sıfırlama", "Use the following link to reset your password: {link}" => "Bu baÄŸlantıyı kullanarak parolanızı sıfırlayın: {link}", "You will receive a link to reset your password via Email." => "Parolanızı sıfırlamak için bir baÄŸlantı Eposta olarak gönderilecek.", -"Username" => "Kullanıcı Adı", +"Reset email send." => "Sıfırlama epostası gönderildi.", +"Request failed!" => "Ä°stek reddedildi!", +"Username" => "Kullanıcı adı", "Request reset" => "Sıfırlama iste", "Your password was reset" => "Parolanız sıfırlandı", "To login page" => "GiriÅŸ sayfasına git", @@ -122,7 +124,7 @@ "Database tablespace" => "Veritabanı tablo alanı", "Database host" => "Veritabanı sunucusu", "Finish setup" => "Kurulumu tamamla", -"web services under your control" => "Bilgileriniz güvenli ve ÅŸifreli", +"web services under your control" => "kontrolünüzdeki web servisleri", "Log out" => "Çıkış yap", "Automatic logon rejected!" => "Otomatik oturum açma reddedildi!", "If you did not change your password recently, your account may be compromised!" => "Yakın zamanda parolanızı deÄŸiÅŸtirmedi iseniz hesabınız riske girebilir.", diff --git a/core/l10n/uk.php b/core/l10n/uk.php index a9e4117a61..1e86ed7d36 100644 --- a/core/l10n/uk.php +++ b/core/l10n/uk.php @@ -72,7 +72,7 @@ "No people found" => "Жодної людини не знайдено", "Resharing is not allowed" => "Пере-Ð¿ÑƒÐ±Ð»Ñ–ÐºÐ°Ñ†Ñ–Ñ Ð½Ðµ дозволÑєтьÑÑ", "Shared in {item} with {user}" => "Опубліковано {item} Ð´Ð»Ñ {user}", -"Unshare" => "Закрити доÑтуп", +"Unshare" => "Заборонити доÑтуп", "can edit" => "може редагувати", "access control" => "контроль доÑтупу", "create" => "Ñтворити", @@ -89,6 +89,8 @@ "ownCloud password reset" => "ÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ ownCloud", "Use the following link to reset your password: {link}" => "ВикориÑтовуйте наÑтупне поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ: {link}", "You will receive a link to reset your password via Email." => "Ви отримаєте поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ паролю на Ел. пошту.", +"Reset email send." => "ЛиÑÑ‚ ÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¾.", +"Request failed!" => "Ðевдалий запит!", "Username" => "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача", "Request reset" => "Запит ÑкиданнÑ", "Your password was reset" => "Ваш пароль був Ñкинутий", @@ -98,7 +100,7 @@ "Personal" => "ОÑобиÑте", "Users" => "КориÑтувачі", "Apps" => "Додатки", -"Admin" => "Ðдмін", +"Admin" => "ÐдмініÑтратор", "Help" => "Допомога", "Access forbidden" => "ДоÑтуп заборонено", "Cloud not found" => "Cloud не знайдено", @@ -122,7 +124,7 @@ "Database tablespace" => "Ð¢Ð°Ð±Ð»Ð¸Ñ†Ñ Ð±Ð°Ð·Ð¸ даних", "Database host" => "ХоÑÑ‚ бази даних", "Finish setup" => "Завершити налаштуваннÑ", -"web services under your control" => "підконтрольні Вам веб-ÑервіÑи", +"web services under your control" => "веб-ÑÐµÑ€Ð²Ñ–Ñ Ð¿Ñ–Ð´ вашим контролем", "Log out" => "Вихід", "Automatic logon rejected!" => "Ðвтоматичний вхід в ÑиÑтему відхилений!", "If you did not change your password recently, your account may be compromised!" => "Якщо Ви не мінÑли пароль оÑтаннім чаÑом, Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¼Ð¾Ð¶Ðµ бути Ñкомпрометованим!", diff --git a/core/l10n/vi.php b/core/l10n/vi.php index 0b45fa6931..709a874308 100644 --- a/core/l10n/vi.php +++ b/core/l10n/vi.php @@ -9,7 +9,7 @@ "Object type not provided." => "Loại đối tượng không được cung cấp.", "%s ID not provided." => "%s ID không được cung cấp.", "Error adding %s to favorites." => "Lá»—i thêm %s vào mục yêu thích.", -"No categories selected for deletion." => "Bạn chÆ°a chá»n mục để xóa", +"No categories selected for deletion." => "Không có thể loại nào được chá»n để xóa.", "Error removing %s from favorites." => "Lá»—i xóa %s từ mục yêu thích.", "Sunday" => "Chủ nhật", "Monday" => "Thứ 2", @@ -72,7 +72,7 @@ "No people found" => "Không tìm thấy ngÆ°á»i nào", "Resharing is not allowed" => "Chia sẻ lại không được cho phép", "Shared in {item} with {user}" => "Äã được chia sẽ trong {item} vá»›i {user}", -"Unshare" => "Bá» chia sẻ", +"Unshare" => "Gỡ bá» chia sẻ", "can edit" => "có thể chỉnh sá»­a", "access control" => "quản lý truy cập", "create" => "tạo", @@ -89,20 +89,22 @@ "ownCloud password reset" => "Khôi phục mật khẩu Owncloud ", "Use the following link to reset your password: {link}" => "Dùng Ä‘Æ°á»ng dẫn sau để khôi phục lại mật khẩu : {link}", "You will receive a link to reset your password via Email." => "Vui lòng kiểm tra Email để khôi phục lại mật khẩu.", -"Username" => "Tên đăng nhập", +"Reset email send." => "Thiết lập lại email gởi.", +"Request failed!" => "Yêu cầu của bạn không thành công !", +"Username" => "Tên ngÆ°á»i dùng", "Request reset" => "Yêu cầu thiết lập lại ", "Your password was reset" => "Mật khẩu của bạn đã được khôi phục", "To login page" => "Trang đăng nhập", "New password" => "Mật khẩu má»›i", "Reset password" => "Khôi phục mật khẩu", "Personal" => "Cá nhân", -"Users" => "NgÆ°á»i dùng", +"Users" => "NgÆ°á»i sá»­ dụng", "Apps" => "Ứng dụng", "Admin" => "Quản trị", "Help" => "Giúp đỡ", "Access forbidden" => "Truy cập bị cấm", "Cloud not found" => "Không tìm thấy Clound", -"Edit categories" => "Sá»­a chuyên mục", +"Edit categories" => "Sá»­a thể loại", "Add" => "Thêm", "Security Warning" => "Cảnh bảo bảo mật", "No secure random number generator is available, please enable the PHP OpenSSL extension." => "Không an toàn ! chức năng random number generator đã có sẵn ,vui lòng bật PHP OpenSSL extension.", @@ -120,7 +122,7 @@ "Database tablespace" => "CÆ¡ sở dữ liệu tablespace", "Database host" => "Database host", "Finish setup" => "Cài đặt hoàn tất", -"web services under your control" => "dịch vụ web dÆ°á»›i sá»± kiểm soát của bạn", +"web services under your control" => "các dịch vụ web dÆ°á»›i sá»± kiểm soát của bạn", "Log out" => "Äăng xuất", "Automatic logon rejected!" => "Tá»± Ä‘á»™ng đăng nhập đã bị từ chối !", "If you did not change your password recently, your account may be compromised!" => "Nếu bạn không thay đổi mật khẩu gần đây của bạn, tài khoản của bạn có thể gặp nguy hiểm!", diff --git a/core/l10n/zh_CN.GB2312.php b/core/l10n/zh_CN.GB2312.php index 7e98d69b64..9fbfac2eec 100644 --- a/core/l10n/zh_CN.GB2312.php +++ b/core/l10n/zh_CN.GB2312.php @@ -7,7 +7,7 @@ "No category to add?" => "没有分类添加了?", "This category already exists: %s" => "此分类已存在:%s", "Object type not provided." => "未选择对象类型。", -"No categories selected for deletion." => "没有选中è¦åˆ é™¤çš„分类。", +"No categories selected for deletion." => "没有选者è¦åˆ é™¤çš„分类.", "Sunday" => "星期天", "Monday" => "星期一", "Tuesday" => "星期二", @@ -47,7 +47,7 @@ "Yes" => "是", "No" => "å¦", "The object type is not specified." => "未指定对象类型。", -"Error" => "出错", +"Error" => "错误", "The app name is not specified." => "未指定应用å称。", "The required file {file} is not installed!" => "未安装所需è¦çš„文件 {file} ï¼", "Shared" => "已分享", @@ -86,16 +86,18 @@ "ownCloud password reset" => "ç§æœ‰äº‘密ç é‡ç½®", "Use the following link to reset your password: {link}" => "使用下é¢çš„链接æ¥é‡ç½®ä½ çš„密ç :{link}", "You will receive a link to reset your password via Email." => "你将会收到一个é‡ç½®å¯†ç çš„链接", +"Reset email send." => "é‡ç½®é‚®ä»¶å·²å‘é€ã€‚", +"Request failed!" => "请求失败ï¼", "Username" => "用户å", "Request reset" => "è¦æ±‚é‡ç½®", "Your password was reset" => "你的密ç å·²ç»è¢«é‡ç½®äº†", "To login page" => "转至登陆页é¢", "New password" => "新密ç ", "Reset password" => "é‡ç½®å¯†ç ", -"Personal" => "ç§äºº", +"Personal" => "个人的", "Users" => "用户", -"Apps" => "程åº", -"Admin" => "管ç†å‘˜", +"Apps" => "应用程åº", +"Admin" => "管ç†", "Help" => "帮助", "Access forbidden" => "ç¦æ­¢è®¿é—®", "Cloud not found" => "云 没有被找到", @@ -118,7 +120,7 @@ "Database tablespace" => "æ•°æ®åº“表格空间", "Database host" => "æ•°æ®åº“主机", "Finish setup" => "完æˆå®‰è£…", -"web services under your control" => "您控制的网络æœåŠ¡", +"web services under your control" => "你控制下的网络æœåŠ¡", "Log out" => "注销", "Automatic logon rejected!" => "自动登录被拒ç»ï¼", "If you did not change your password recently, your account may be compromised!" => "如果您最近没有修改您的密ç ï¼Œé‚£æ‚¨çš„å¸å·å¯èƒ½è¢«æ”»å‡»äº†ï¼", diff --git a/core/l10n/zh_CN.php b/core/l10n/zh_CN.php index 49cd1e2ebf..926d4691ed 100644 --- a/core/l10n/zh_CN.php +++ b/core/l10n/zh_CN.php @@ -54,13 +54,13 @@ "The app name is not specified." => "未指定Appå称。", "The required file {file} is not installed!" => "所需文件{file}未安装ï¼", "Shared" => "已共享", -"Share" => "分享", +"Share" => "共享", "Error while sharing" => "共享时出错", "Error while unsharing" => "å–消共享时出错", "Error while changing permissions" => "修改æƒé™æ—¶å‡ºé”™", "Shared with you and the group {group} by {owner}" => "{owner}共享给您åŠ{group}组", "Shared with you by {owner}" => " {owner}与您共享", -"Share with" => "分享之", +"Share with" => "共享", "Share with link" => "共享链接", "Password protect" => "密ç ä¿æŠ¤", "Password" => "密ç ", @@ -89,6 +89,8 @@ "ownCloud password reset" => "é‡ç½® ownCloud 密ç ", "Use the following link to reset your password: {link}" => "使用以下链接é‡ç½®æ‚¨çš„密ç ï¼š{link}", "You will receive a link to reset your password via Email." => "您将会收到包å«å¯ä»¥é‡ç½®å¯†ç é“¾æŽ¥çš„邮件。", +"Reset email send." => "é‡ç½®é‚®ä»¶å·²å‘é€ã€‚", +"Request failed!" => "请求失败ï¼", "Username" => "用户å", "Request reset" => "请求é‡ç½®", "Your password was reset" => "您的密ç å·²é‡ç½®", @@ -98,12 +100,12 @@ "Personal" => "个人", "Users" => "用户", "Apps" => "应用", -"Admin" => "管ç†", +"Admin" => "管ç†å‘˜", "Help" => "帮助", "Access forbidden" => "访问ç¦æ­¢", "Cloud not found" => "未找到云", "Edit categories" => "编辑分类", -"Add" => "增加", +"Add" => "添加", "Security Warning" => "安全警告", "No secure random number generator is available, please enable the PHP OpenSSL extension." => "éšæœºæ•°ç”Ÿæˆå™¨æ— æ•ˆï¼Œè¯·å¯ç”¨PHPçš„OpenSSL扩展", "Without a secure random number generator an attacker may be able to predict password reset tokens and take over your account." => "没有安全éšæœºç ç”Ÿæˆå™¨ï¼Œæ”»å‡»è€…å¯èƒ½ä¼šçŒœæµ‹å¯†ç é‡ç½®ä¿¡æ¯ä»Žè€Œçªƒå–您的账户", @@ -120,7 +122,7 @@ "Database tablespace" => "æ•°æ®åº“表空间", "Database host" => "æ•°æ®åº“主机", "Finish setup" => "安装完æˆ", -"web services under your control" => "您控制的webæœåŠ¡", +"web services under your control" => "由您掌控的网络æœåŠ¡", "Log out" => "注销", "Automatic logon rejected!" => "自动登录被拒ç»ï¼", "If you did not change your password recently, your account may be compromised!" => "如果您没有最近修改您的密ç ï¼Œæ‚¨çš„å¸æˆ·å¯èƒ½ä¼šå—到影å“ï¼", diff --git a/core/l10n/zh_HK.php b/core/l10n/zh_HK.php index c4f4009517..178ab88e5e 100644 --- a/core/l10n/zh_HK.php +++ b/core/l10n/zh_HK.php @@ -55,6 +55,8 @@ "The update was successful. Redirecting you to ownCloud now." => "æ›´æ–°æˆåŠŸ, æ­£", "Use the following link to reset your password: {link}" => "請用以下連çµé‡è¨­ä½ çš„密碼: {link}", "You will receive a link to reset your password via Email." => "你將收到一å°é›»éƒµ", +"Reset email send." => "é‡è¨­å¯†ç¢¼éƒµä»¶å·²å‚³", +"Request failed!" => "請求失敗", "Username" => "用戶å稱", "Request reset" => "é‡è¨­", "Your password was reset" => "你的密碼已被é‡è¨­", diff --git a/core/l10n/zh_TW.php b/core/l10n/zh_TW.php index cfc3a9fe33..3199688be3 100644 --- a/core/l10n/zh_TW.php +++ b/core/l10n/zh_TW.php @@ -34,7 +34,7 @@ "seconds ago" => "幾秒å‰", "1 minute ago" => "1 分é˜å‰", "{minutes} minutes ago" => "{minutes} 分é˜å‰", -"1 hour ago" => "1 å°æ™‚之å‰", +"1 hour ago" => "1 個å°æ™‚å‰", "{hours} hours ago" => "{hours} å°æ™‚å‰", "today" => "今天", "yesterday" => "昨天", @@ -89,6 +89,8 @@ "ownCloud password reset" => "ownCloud 密碼é‡è¨­", "Use the following link to reset your password: {link}" => "請至以下連çµé‡è¨­æ‚¨çš„密碼: {link}", "You will receive a link to reset your password via Email." => "é‡è¨­å¯†ç¢¼çš„連çµå°‡æœƒå¯„到你的電å­éƒµä»¶ä¿¡ç®±ã€‚", +"Reset email send." => "é‡è¨­éƒµä»¶å·²é€å‡ºã€‚", +"Request failed!" => "請求失敗ï¼", "Username" => "使用者å稱", "Request reset" => "請求é‡è¨­", "Your password was reset" => "您的密碼已é‡è¨­", @@ -98,8 +100,8 @@ "Personal" => "個人", "Users" => "使用者", "Apps" => "應用程å¼", -"Admin" => "管ç†", -"Help" => "說明", +"Admin" => "管ç†è€…", +"Help" => "幫助", "Access forbidden" => "å­˜å–被拒", "Cloud not found" => "未發ç¾é›²ç«¯", "Edit categories" => "編輯分類", diff --git a/core/lostpassword/templates/lostpassword.php b/core/lostpassword/templates/lostpassword.php index c19c6893f1..dc9f0bc8ad 100644 --- a/core/lostpassword/templates/lostpassword.php +++ b/core/lostpassword/templates/lostpassword.php @@ -1,24 +1,17 @@ - -

- t('The link to reset your password has been sent to your email.
If you do not receive it within a reasonable amount of time, check your spam/junk folders.
If it is not there ask your local administrator .')); - ?> -

- -
-
+ +
+ t('You will receive a link to reset your password via Email.'); ?> + + t('Reset email send.'); ?> + -

- t('Request failed!
Did you make sure your email/username was right?')); ?> -

+ t('Request failed!'); ?> - t('You will receive a link to reset your password via Email.')); ?>

+ - -

- -
- - + + +
+ diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php index 4dc4a2c759..cfe0a55194 100644 --- a/core/templates/layout.user.php +++ b/core/templates/layout.user.php @@ -32,9 +32,6 @@