Merge branch 'master' into user
This commit is contained in:
commit
542bcf9156
|
@ -46,6 +46,7 @@
|
|||
"{count} folders" => "{count} pastas",
|
||||
"1 file" => "1 ficheiro",
|
||||
"{count} files" => "{count} ficheiros",
|
||||
"Invalid folder name. Usage of 'Shared' is reserved by ownCloud" => "Nome da pasta inválido. Palavra 'Shared' é reservado pela ownCloud",
|
||||
"Unable to rename file" => "Não foi possível renomear o ficheiro",
|
||||
"Upload" => "Carregar",
|
||||
"File handling" => "Manuseamento de ficheiros",
|
||||
|
|
|
@ -13,31 +13,47 @@ use OCA\Encryption;
|
|||
\OCP\JSON::checkAppEnabled('files_encryption');
|
||||
\OCP\JSON::callCheck();
|
||||
|
||||
$l=OC_L10N::get('files_encryption');
|
||||
$l = OC_L10N::get('files_encryption');
|
||||
|
||||
$return = false;
|
||||
|
||||
// Enable recoveryAdmin
|
||||
|
||||
$recoveryKeyId = OC_Appconfig::getValue('files_encryption', 'recoveryKeyId');
|
||||
|
||||
if (isset($_POST['adminEnableRecovery']) && $_POST['adminEnableRecovery'] == 1){
|
||||
if (isset($_POST['adminEnableRecovery']) && $_POST['adminEnableRecovery'] === '1') {
|
||||
|
||||
$return = \OCA\Encryption\Helper::adminEnableRecovery($recoveryKeyId, $_POST['recoveryPassword']);
|
||||
$action = "enable";
|
||||
|
||||
// Return success or failure
|
||||
if ($return) {
|
||||
\OCP\JSON::success(array('data' => array('message' => $l->t('Recovery key successfully enabled'))));
|
||||
} else {
|
||||
\OCP\JSON::error(array(
|
||||
'data' => array(
|
||||
'message' => $l->t(
|
||||
'Could not enable recovery key. Please check your recovery key password!')
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
// Disable recoveryAdmin
|
||||
} elseif (
|
||||
isset($_POST['adminEnableRecovery'])
|
||||
&& 0 == $_POST['adminEnableRecovery']
|
||||
&& '0' === $_POST['adminEnableRecovery']
|
||||
) {
|
||||
$return = \OCA\Encryption\Helper::adminDisableRecovery($_POST['recoveryPassword']);
|
||||
$action = "disable";
|
||||
|
||||
// Return success or failure
|
||||
if ($return) {
|
||||
\OCP\JSON::success(array('data' => array('message' => $l->t('Recovery key successfully disabled'))));
|
||||
} else {
|
||||
\OCP\JSON::error(array(
|
||||
'data' => array(
|
||||
'message' => $l->t(
|
||||
'Could not disable recovery key. Please check your recovery key password!')
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Return success or failure
|
||||
if ($return) {
|
||||
\OCP\JSON::success(array("data" => array( "message" => $l->t('Recovery key successfully ' . $action.'d'))));
|
||||
} else {
|
||||
\OCP\JSON::error(array("data" => array( "message" => $l->t('Could not '.$action.' recovery key. Please check your recovery key password!'))));
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* See the COPYING-README file.
|
||||
*
|
||||
* @brief Script to change recovery key password
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
use OCA\Encryption;
|
||||
|
@ -15,7 +15,7 @@ use OCA\Encryption;
|
|||
\OCP\JSON::checkAppEnabled('files_encryption');
|
||||
\OCP\JSON::callCheck();
|
||||
|
||||
$l=OC_L10N::get('core');
|
||||
$l = OC_L10N::get('core');
|
||||
|
||||
$return = false;
|
||||
|
||||
|
@ -28,7 +28,7 @@ $result = $util->checkRecoveryPassword($oldPassword);
|
|||
|
||||
if ($result) {
|
||||
$keyId = $util->getRecoveryKeyId();
|
||||
$keyPath = '/owncloud_private_key/' . $keyId . ".private.key";
|
||||
$keyPath = '/owncloud_private_key/' . $keyId . '.private.key';
|
||||
$view = new \OC\Files\View('/');
|
||||
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
|
@ -46,7 +46,7 @@ if ($result) {
|
|||
|
||||
// success or failure
|
||||
if ($return) {
|
||||
\OCP\JSON::success(array("data" => array( "message" => $l->t('Password successfully changed.'))));
|
||||
\OCP\JSON::success(array('data' => array('message' => $l->t('Password successfully changed.'))));
|
||||
} else {
|
||||
\OCP\JSON::error(array("data" => array( "message" => $l->t('Could not change the password. Maybe the old password was not correct.'))));
|
||||
\OCP\JSON::error(array('data' => array('message' => $l->t('Could not change the password. Maybe the old password was not correct.'))));
|
||||
}
|
|
@ -10,32 +10,32 @@
|
|||
use OCA\Encryption;
|
||||
|
||||
\OCP\JSON::checkLoggedIn();
|
||||
\OCP\JSON::checkAppEnabled( 'files_encryption' );
|
||||
\OCP\JSON::checkAppEnabled('files_encryption');
|
||||
\OCP\JSON::callCheck();
|
||||
|
||||
if (
|
||||
isset( $_POST['userEnableRecovery'] )
|
||||
&& ( 0 == $_POST['userEnableRecovery'] || 1 == $_POST['userEnableRecovery'] )
|
||||
if (
|
||||
isset($_POST['userEnableRecovery'])
|
||||
&& (0 == $_POST['userEnableRecovery'] || '1' === $_POST['userEnableRecovery'])
|
||||
) {
|
||||
|
||||
$userId = \OCP\USER::getUser();
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
$util = new \OCA\Encryption\Util( $view, $userId );
|
||||
|
||||
// Save recovery preference to DB
|
||||
$return = $util->setRecoveryForUser( $_POST['userEnableRecovery'] );
|
||||
$view = new \OC_FilesystemView('/');
|
||||
$util = new \OCA\Encryption\Util($view, $userId);
|
||||
|
||||
if ($_POST['userEnableRecovery'] == "1") {
|
||||
// Save recovery preference to DB
|
||||
$return = $util->setRecoveryForUser($_POST['userEnableRecovery']);
|
||||
|
||||
if ($_POST['userEnableRecovery'] === '1') {
|
||||
$util->addRecoveryKeys();
|
||||
} else {
|
||||
$util->removeRecoveryKeys();
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
$return = false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Return success or failure
|
||||
( $return ) ? \OCP\JSON::success() : \OCP\JSON::error();
|
||||
($return) ? \OCP\JSON::success() : \OCP\JSON::error();
|
|
@ -10,7 +10,7 @@ OC::$CLASSPATH['OCA\Encryption\Session'] = 'files_encryption/lib/session.php';
|
|||
OC::$CLASSPATH['OCA\Encryption\Capabilities'] = 'files_encryption/lib/capabilities.php';
|
||||
OC::$CLASSPATH['OCA\Encryption\Helper'] = 'files_encryption/lib/helper.php';
|
||||
|
||||
OC_FileProxy::register( new OCA\Encryption\Proxy() );
|
||||
OC_FileProxy::register(new OCA\Encryption\Proxy());
|
||||
|
||||
// User related hooks
|
||||
OCA\Encryption\Helper::registerUserHooks();
|
||||
|
@ -21,7 +21,7 @@ OCA\Encryption\Helper::registerShareHooks();
|
|||
// Filesystem related hooks
|
||||
OCA\Encryption\Helper::registerFilesystemHooks();
|
||||
|
||||
stream_wrapper_register( 'crypt', 'OCA\Encryption\Stream' );
|
||||
stream_wrapper_register('crypt', 'OCA\Encryption\Stream');
|
||||
|
||||
// check if we are logged in
|
||||
if (OCP\User::isLoggedIn()) {
|
||||
|
@ -46,6 +46,6 @@ if (OCP\User::isLoggedIn()) {
|
|||
}
|
||||
|
||||
// Register settings scripts
|
||||
OCP\App::registerAdmin( 'files_encryption', 'settings-admin' );
|
||||
OCP\App::registerPersonal( 'files_encryption', 'settings-personal' );
|
||||
OCP\App::registerAdmin('files_encryption', 'settings-admin');
|
||||
OCP\App::registerPersonal('files_encryption', 'settings-personal');
|
||||
|
||||
|
|
|
@ -37,106 +37,106 @@ class Hooks {
|
|||
* @brief Startup encryption backend upon user login
|
||||
* @note This method should never be called for users using client side encryption
|
||||
*/
|
||||
public static function login( $params ) {
|
||||
|
||||
public static function login($params) {
|
||||
|
||||
// Manually initialise Filesystem{} singleton with correct
|
||||
// fake root path, in order to avoid fatal webdav errors
|
||||
// NOTE: disabled because this give errors on webdav!
|
||||
// NOTE: disabled because this give errors on webdav!
|
||||
//\OC\Files\Filesystem::init( $params['uid'], '/' . 'files' . '/' );
|
||||
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
|
||||
$util = new Util( $view, $params['uid'] );
|
||||
$view = new \OC_FilesystemView('/');
|
||||
|
||||
// setup user, if user not ready force relogin
|
||||
if(Helper::setupUser($util, $params['password']) === false) {
|
||||
return false;
|
||||
}
|
||||
$util = new Util($view, $params['uid']);
|
||||
|
||||
$encryptedKey = Keymanager::getPrivateKey( $view, $params['uid'] );
|
||||
|
||||
$privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] );
|
||||
// setup user, if user not ready force relogin
|
||||
if (Helper::setupUser($util, $params['password']) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$encryptedKey = Keymanager::getPrivateKey($view, $params['uid']);
|
||||
|
||||
$privateKey = Crypt::symmetricDecryptFileContent($encryptedKey, $params['password']);
|
||||
|
||||
$session = new \OCA\Encryption\Session($view);
|
||||
|
||||
$session->setPrivateKey($privateKey, $params['uid']);
|
||||
|
||||
$session = new \OCA\Encryption\Session( $view );
|
||||
|
||||
$session->setPrivateKey( $privateKey, $params['uid'] );
|
||||
|
||||
// Check if first-run file migration has already been performed
|
||||
$migrationCompleted = $util->getMigrationStatus();
|
||||
|
||||
|
||||
// If migration not yet done
|
||||
if ( ! $migrationCompleted ) {
|
||||
|
||||
$userView = new \OC_FilesystemView( '/' . $params['uid'] );
|
||||
|
||||
if (!$migrationCompleted) {
|
||||
|
||||
$userView = new \OC_FilesystemView('/' . $params['uid']);
|
||||
|
||||
// Set legacy encryption key if it exists, to support
|
||||
// depreciated encryption system
|
||||
if (
|
||||
$userView->file_exists( 'encryption.key' )
|
||||
&& $encLegacyKey = $userView->file_get_contents( 'encryption.key' )
|
||||
$userView->file_exists('encryption.key')
|
||||
&& $encLegacyKey = $userView->file_get_contents('encryption.key')
|
||||
) {
|
||||
|
||||
$plainLegacyKey = Crypt::legacyBlockDecrypt( $encLegacyKey, $params['password'] );
|
||||
|
||||
$session->setLegacyKey( $plainLegacyKey );
|
||||
|
||||
|
||||
$plainLegacyKey = Crypt::legacyBlockDecrypt($encLegacyKey, $params['password']);
|
||||
|
||||
$session->setLegacyKey($plainLegacyKey);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Encrypt existing user files:
|
||||
// This serves to upgrade old versions of the encryption
|
||||
// app (see appinfo/spec.txt)
|
||||
if (
|
||||
$util->encryptAll( '/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password'] )
|
||||
$util->encryptAll('/' . $params['uid'] . '/' . 'files', $session->getLegacyKey(), $params['password'])
|
||||
) {
|
||||
|
||||
\OC_Log::write(
|
||||
|
||||
\OC_Log::write(
|
||||
'Encryption library', 'Encryption of existing files belonging to "' . $params['uid'] . '" completed'
|
||||
, \OC_Log::INFO
|
||||
, \OC_Log::INFO
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Register successful migration in DB
|
||||
$util->setMigrationStatus( 1 );
|
||||
|
||||
$util->setMigrationStatus(1);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief setup encryption backend upon user created
|
||||
* @note This method should never be called for users using client side encryption
|
||||
*/
|
||||
public static function postCreateUser( $params ) {
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
/**
|
||||
* @brief setup encryption backend upon user created
|
||||
* @note This method should never be called for users using client side encryption
|
||||
*/
|
||||
public static function postCreateUser($params) {
|
||||
$view = new \OC_FilesystemView('/');
|
||||
|
||||
$util = new Util( $view, $params['uid'] );
|
||||
$util = new Util($view, $params['uid']);
|
||||
|
||||
Helper::setupUser($util, $params['password']);
|
||||
}
|
||||
Helper::setupUser($util, $params['password']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief cleanup encryption backend upon user deleted
|
||||
* @note This method should never be called for users using client side encryption
|
||||
*/
|
||||
public static function postDeleteUser( $params ) {
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
/**
|
||||
* @brief cleanup encryption backend upon user deleted
|
||||
* @note This method should never be called for users using client side encryption
|
||||
*/
|
||||
public static function postDeleteUser($params) {
|
||||
$view = new \OC_FilesystemView('/');
|
||||
|
||||
// cleanup public key
|
||||
$publicKey = '/public-keys/' . $params['uid'] . '.public.key';
|
||||
// cleanup public key
|
||||
$publicKey = '/public-keys/' . $params['uid'] . '.public.key';
|
||||
|
||||
// Disable encryption proxy to prevent recursive calls
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
// Disable encryption proxy to prevent recursive calls
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
$view->unlink($publicKey);
|
||||
$view->unlink($publicKey);
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
}
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Change a user's encryption passphrase
|
||||
* @param array $params keys: uid, password
|
||||
*/
|
||||
|
@ -145,9 +145,9 @@ class Hooks {
|
|||
// Only attempt to change passphrase if server-side encryption
|
||||
// is in use (client-side encryption does not have access to
|
||||
// the necessary keys)
|
||||
if (Crypt::mode() == 'server') {
|
||||
if (Crypt::mode() === 'server') {
|
||||
|
||||
if ($params['uid'] == \OCP\User::getUser()) {
|
||||
if ($params['uid'] === \OCP\User::getUser()) {
|
||||
|
||||
$view = new \OC_FilesystemView('/');
|
||||
|
||||
|
@ -165,10 +165,10 @@ class Hooks {
|
|||
// NOTE: Session does not need to be updated as the
|
||||
// private key has not changed, only the passphrase
|
||||
// used to decrypt it has changed
|
||||
|
||||
|
||||
|
||||
|
||||
} else { // admin changed the password for a different user, create new keys and reencrypt file keys
|
||||
|
||||
|
||||
$user = $params['uid'];
|
||||
$recoveryPassword = $params['recoveryPassword'];
|
||||
$newUserPassword = $params['password'];
|
||||
|
@ -179,21 +179,22 @@ class Hooks {
|
|||
\OC\Files\Filesystem::initMountPoints($user);
|
||||
|
||||
$keypair = Crypt::createKeypair();
|
||||
|
||||
|
||||
// Disable encryption proxy to prevent recursive calls
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
// Save public key
|
||||
$view->file_put_contents( '/public-keys/'.$user.'.public.key', $keypair['publicKey'] );
|
||||
$view->file_put_contents('/public-keys/' . $user . '.public.key', $keypair['publicKey']);
|
||||
|
||||
// Encrypt private key empty passphrase
|
||||
$encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $keypair['privateKey'], $newUserPassword );
|
||||
$encryptedPrivateKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], $newUserPassword);
|
||||
|
||||
// Save private key
|
||||
$view->file_put_contents( '/'.$user.'/files_encryption/'.$user.'.private.key', $encryptedPrivateKey );
|
||||
$view->file_put_contents(
|
||||
'/' . $user . '/files_encryption/' . $user . '.private.key', $encryptedPrivateKey);
|
||||
|
||||
if ( $recoveryPassword ) { // if recovery key is set we can re-encrypt the key files
|
||||
if ($recoveryPassword) { // if recovery key is set we can re-encrypt the key files
|
||||
$util = new Util($view, $user);
|
||||
$util->recoverUsersFiles($recoveryPassword);
|
||||
}
|
||||
|
@ -231,16 +232,17 @@ class Hooks {
|
|||
}
|
||||
}
|
||||
|
||||
if($error)
|
||||
// Set flag var 'run' to notify emitting
|
||||
if ($error) // Set flag var 'run' to notify emitting
|
||||
// script that hook execution failed
|
||||
{
|
||||
$params['run']->run = false;
|
||||
// TODO: Make sure files_sharing provides user
|
||||
// feedback on failed share
|
||||
}
|
||||
// TODO: Make sure files_sharing provides user
|
||||
// feedback on failed share
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @brief
|
||||
*/
|
||||
public static function postShared($params) {
|
||||
|
||||
|
@ -273,7 +275,7 @@ class Hooks {
|
|||
|
||||
$share = $util->getParentFromShare($params['id']);
|
||||
//if parent is set, then this is a re-share action
|
||||
if ($share['parent'] != null) {
|
||||
if ($share['parent'] !== null) {
|
||||
|
||||
// get the parent from current share
|
||||
$parent = $util->getShareParent($params['parent']);
|
||||
|
@ -325,6 +327,12 @@ class Hooks {
|
|||
|
||||
$sharingEnabled = \OCP\Share::isEnabled();
|
||||
|
||||
// get the path including mount point only if not a shared folder
|
||||
if(strncmp($path, '/Shared' , strlen('/Shared') !== 0)) {
|
||||
// get path including the the storage mount point
|
||||
$path = $util->getPathWithMountPoint($params['itemSource']);
|
||||
}
|
||||
|
||||
// if a folder was shared, get a list of all (sub-)folders
|
||||
if ($params['itemType'] === 'folder') {
|
||||
$allFiles = $util->getAllFiles($path);
|
||||
|
@ -334,15 +342,15 @@ class Hooks {
|
|||
|
||||
foreach ($allFiles as $path) {
|
||||
$usersSharing = $util->getSharingUsersArray($sharingEnabled, $path);
|
||||
$util->setSharedFileKeyfiles( $session, $usersSharing, $path );
|
||||
$util->setSharedFileKeyfiles($session, $usersSharing, $path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @brief
|
||||
*/
|
||||
public static function postUnshare( $params ) {
|
||||
public static function postUnshare($params) {
|
||||
|
||||
// NOTE: $params has keys:
|
||||
// [itemType] => file
|
||||
|
@ -351,40 +359,34 @@ class Hooks {
|
|||
// [shareWith] => test1
|
||||
// [itemParent] =>
|
||||
|
||||
if ( $params['itemType'] === 'file' || $params['itemType'] === 'folder' ) {
|
||||
if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
|
||||
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
$view = new \OC_FilesystemView('/');
|
||||
$userId = \OCP\User::getUser();
|
||||
$util = new Util( $view, $userId);
|
||||
$path = $util->fileIdToPath( $params['itemSource'] );
|
||||
$util = new Util($view, $userId);
|
||||
$path = $util->fileIdToPath($params['itemSource']);
|
||||
|
||||
// check if this is a re-share
|
||||
if ( $params['itemParent'] ) {
|
||||
if ($params['itemParent']) {
|
||||
|
||||
// get the parent from current share
|
||||
$parent = $util->getShareParent( $params['itemParent'] );
|
||||
$parent = $util->getShareParent($params['itemParent']);
|
||||
|
||||
// get target path
|
||||
$targetPath = $util->fileIdToPath( $params['itemSource'] );
|
||||
$targetPathSplit = array_reverse( explode( '/', $targetPath ) );
|
||||
$targetPath = $util->fileIdToPath($params['itemSource']);
|
||||
$targetPathSplit = array_reverse(explode('/', $targetPath));
|
||||
|
||||
// init values
|
||||
$path = '';
|
||||
$sharedPart = ltrim( $parent['file_target'], '/' );
|
||||
$sharedPart = ltrim($parent['file_target'], '/');
|
||||
|
||||
// rebuild path
|
||||
foreach ( $targetPathSplit as $pathPart ) {
|
||||
|
||||
if ( $pathPart !== $sharedPart ) {
|
||||
|
||||
foreach ($targetPathSplit as $pathPart) {
|
||||
if ($pathPart !== $sharedPart) {
|
||||
$path = '/' . $pathPart . $path;
|
||||
|
||||
} else {
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// prefix path with Shared
|
||||
|
@ -392,118 +394,127 @@ class Hooks {
|
|||
}
|
||||
|
||||
// for group shares get a list of the group members
|
||||
if ( $params['shareType'] == \OCP\Share::SHARE_TYPE_GROUP ) {
|
||||
if ($params['shareType'] === \OCP\Share::SHARE_TYPE_GROUP) {
|
||||
$userIds = \OC_Group::usersInGroup($params['shareWith']);
|
||||
} else if ( $params['shareType'] == \OCP\Share::SHARE_TYPE_LINK ){
|
||||
$userIds = array( $util->getPublicShareKeyId() );
|
||||
} else {
|
||||
$userIds = array( $params['shareWith'] );
|
||||
if ($params['shareType'] === \OCP\Share::SHARE_TYPE_LINK) {
|
||||
$userIds = array($util->getPublicShareKeyId());
|
||||
} else {
|
||||
$userIds = array($params['shareWith']);
|
||||
}
|
||||
}
|
||||
|
||||
// get the path including mount point only if not a shared folder
|
||||
if(strncmp($path, '/Shared' , strlen('/Shared') !== 0)) {
|
||||
// get path including the the storage mount point
|
||||
$path = $util->getPathWithMountPoint($params['itemSource']);
|
||||
}
|
||||
|
||||
// if we unshare a folder we need a list of all (sub-)files
|
||||
if ( $params['itemType'] === 'folder' ) {
|
||||
|
||||
if ($params['itemType'] === 'folder') {
|
||||
$allFiles = $util->getAllFiles( $path );
|
||||
|
||||
} else {
|
||||
|
||||
$allFiles = array( $path );
|
||||
$allFiles = array($path);
|
||||
}
|
||||
|
||||
foreach ( $allFiles as $path ) {
|
||||
foreach ($allFiles as $path) {
|
||||
|
||||
// check if the user still has access to the file, otherwise delete share key
|
||||
$sharingUsers = $util->getSharingUsersArray( true, $path );
|
||||
$sharingUsers = $util->getSharingUsersArray(true, $path);
|
||||
|
||||
// Unshare every user who no longer has access to the file
|
||||
$delUsers = array_diff( $userIds, $sharingUsers);
|
||||
$delUsers = array_diff($userIds, $sharingUsers);
|
||||
|
||||
// delete share key
|
||||
Keymanager::delShareKey( $view, $delUsers, $path );
|
||||
Keymanager::delShareKey($view, $delUsers, $path);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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;
|
||||
* @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 \OCA\Encryption\Session($view);
|
||||
$userId = \OCP\User::getUser();
|
||||
$util = new Util( $view, $userId );
|
||||
$view = new \OC_FilesystemView('/');
|
||||
$session = new \OCA\Encryption\Session($view);
|
||||
$userId = \OCP\User::getUser();
|
||||
$util = new Util($view, $userId);
|
||||
|
||||
// Format paths to be relative to user files dir
|
||||
$oldKeyfilePath = \OC\Files\Filesystem::normalizePath($userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $params['oldpath']);
|
||||
$newKeyfilePath = \OC\Files\Filesystem::normalizePath($userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $params['newpath']);
|
||||
// Format paths to be relative to user files dir
|
||||
$oldKeyfilePath = \OC\Files\Filesystem::normalizePath(
|
||||
$userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $params['oldpath']);
|
||||
$newKeyfilePath = \OC\Files\Filesystem::normalizePath(
|
||||
$userId . '/' . 'files_encryption' . '/' . 'keyfiles' . '/' . $params['newpath']);
|
||||
|
||||
// add key ext if this is not an folder
|
||||
if (!$view->is_dir($oldKeyfilePath)) {
|
||||
$oldKeyfilePath .= '.key';
|
||||
$newKeyfilePath .= '.key';
|
||||
// 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 = \OC\Files\Filesystem::normalizePath(str_replace($params['oldpath'], $params['newpath'], $src));
|
||||
// handle share-keys
|
||||
$localKeyPath = $view->getLocalFile($userId . '/files_encryption/share-keys/' . $params['oldpath']);
|
||||
$matches = glob(preg_quote($localKeyPath) . '*.shareKey');
|
||||
foreach ($matches as $src) {
|
||||
$dst = \OC\Files\Filesystem::normalizePath(str_replace($params['oldpath'], $params['newpath'], $src));
|
||||
|
||||
// create destination folder if not exists
|
||||
if(!file_exists(dirname($dst))) {
|
||||
mkdir(dirname($dst), 0750, true);
|
||||
}
|
||||
// create destination folder if not exists
|
||||
if (!file_exists(dirname($dst))) {
|
||||
mkdir(dirname($dst), 0750, true);
|
||||
}
|
||||
|
||||
rename($src, $dst);
|
||||
}
|
||||
rename($src, $dst);
|
||||
}
|
||||
|
||||
} else {
|
||||
// handle share-keys folders
|
||||
$oldShareKeyfilePath = \OC\Files\Filesystem::normalizePath($userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $params['oldpath']);
|
||||
$newShareKeyfilePath = \OC\Files\Filesystem::normalizePath($userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $params['newpath']);
|
||||
} else {
|
||||
// handle share-keys folders
|
||||
$oldShareKeyfilePath = \OC\Files\Filesystem::normalizePath(
|
||||
$userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $params['oldpath']);
|
||||
$newShareKeyfilePath = \OC\Files\Filesystem::normalizePath(
|
||||
$userId . '/' . 'files_encryption' . '/' . 'share-keys' . '/' . $params['newpath']);
|
||||
|
||||
// create destination folder if not exists
|
||||
if(!$view->file_exists(dirname($newShareKeyfilePath))) {
|
||||
$view->mkdir(dirname($newShareKeyfilePath), 0750, true);
|
||||
}
|
||||
// create destination folder if not exists
|
||||
if (!$view->file_exists(dirname($newShareKeyfilePath))) {
|
||||
$view->mkdir(dirname($newShareKeyfilePath), 0750, true);
|
||||
}
|
||||
|
||||
$view->rename($oldShareKeyfilePath, $newShareKeyfilePath);
|
||||
}
|
||||
$view->rename($oldShareKeyfilePath, $newShareKeyfilePath);
|
||||
}
|
||||
|
||||
// Rename keyfile so it isn't orphaned
|
||||
if($view->file_exists($oldKeyfilePath)) {
|
||||
// Rename keyfile so it isn't orphaned
|
||||
if ($view->file_exists($oldKeyfilePath)) {
|
||||
|
||||
// create destination folder if not exists
|
||||
if(!$view->file_exists(dirname($newKeyfilePath))) {
|
||||
$view->mkdir(dirname($newKeyfilePath), 0750, true);
|
||||
}
|
||||
// create destination folder if not exists
|
||||
if (!$view->file_exists(dirname($newKeyfilePath))) {
|
||||
$view->mkdir(dirname($newKeyfilePath), 0750, true);
|
||||
}
|
||||
|
||||
$view->rename($oldKeyfilePath, $newKeyfilePath);
|
||||
}
|
||||
$view->rename($oldKeyfilePath, $newKeyfilePath);
|
||||
}
|
||||
|
||||
// build the path to the file
|
||||
$newPath = '/' . $userId . '/files' .$params['newpath'];
|
||||
$newPathRelative = $params['newpath'];
|
||||
// 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();
|
||||
if ($util->fixFileSize($newPath)) {
|
||||
// get sharing app state
|
||||
$sharingEnabled = \OCP\Share::isEnabled();
|
||||
|
||||
// get users
|
||||
$usersSharing = $util->getSharingUsersArray($sharingEnabled, $newPathRelative);
|
||||
// get users
|
||||
$usersSharing = $util->getSharingUsersArray($sharingEnabled, $newPathRelative);
|
||||
|
||||
// update sharing-keys
|
||||
$util->setSharedFileKeyfiles($session, $usersSharing, $newPathRelative);
|
||||
}
|
||||
// update sharing-keys
|
||||
$util->setSharedFileKeyfiles($session, $usersSharing, $newPathRelative);
|
||||
}
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
}
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,22 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Recovery key successfully enabled" => "Taastevõtme lubamine õnnestus",
|
||||
"Could not enable recovery key. Please check your recovery key password!" => "Ei suutnud lubada taastevõtit. Palun kontrolli oma taastevõtme parooli!",
|
||||
"Recovery key successfully disabled" => "Taastevõtme keelamine õnnestus",
|
||||
"Could not disable recovery key. Please check your recovery key password!" => "Ei suuda keelata taastevõtit. Palun kontrolli oma taastevõtme parooli!",
|
||||
"Password successfully changed." => "Parool edukalt vahetatud.",
|
||||
"Could not change the password. Maybe the old password was not correct." => "Ei suutnud vahetada parooli. Võib-olla on vana parool valesti sisestatud.",
|
||||
"Saving..." => "Salvestamine...",
|
||||
"Encryption" => "Krüpteerimine"
|
||||
"Encryption" => "Krüpteerimine",
|
||||
"Enable encryption passwords recovery key (allow sharing to recovery key):" => "Luba krüpteerimise paroolide taastevõti (võimalda parooli jagamine taastevõtmesse):",
|
||||
"Recovery account password" => "Konto taasteparool",
|
||||
"Enabled" => "Sisse lülitatud",
|
||||
"Disabled" => "Väljalülitatud",
|
||||
"Change encryption passwords recovery key:" => "Muuda taaste võtme krüpteerimise paroole:",
|
||||
"Old Recovery account password" => "Konto vana taaste parool",
|
||||
"New Recovery account password" => "Konto uus taasteparool",
|
||||
"Change Password" => "Muuda parooli",
|
||||
"Enable password recovery by sharing all files with your administrator:" => "Luba parooli taaste jagades kõik failid administraatoriga:",
|
||||
"Enabling this option will allow you to reobtain access to your encrypted files if your password is lost" => "Valiku lubamine võimaldab taastada ligipääsu krüpteeritud failidele kui parool on kadunud",
|
||||
"File recovery settings updated" => "Faili taaste seaded uuendatud",
|
||||
"Could not update file recovery" => "Ei suuda uuendada taastefaili"
|
||||
);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Recovery key successfully " => "O contrasinal foi recuperado satisfactoriamente",
|
||||
"Could not " => "Non foi posíbel",
|
||||
"Recovery key successfully enabled" => "Activada satisfactoriamente a chave de recuperación",
|
||||
"Could not enable recovery key. Please check your recovery key password!" => "Non foi posíbel activar a chave de recuperación. Comprobe o contrasinal da chave de recuperación!",
|
||||
"Recovery key successfully disabled" => "Desactivada satisfactoriamente a chave de recuperación",
|
||||
"Could not disable recovery key. Please check your recovery key password!" => "Non foi posíbel desactivar a chave de recuperación. Comprobe o contrasinal da chave de recuperación!",
|
||||
"Password successfully changed." => "O contrasinal foi cambiado satisfactoriamente",
|
||||
"Could not change the password. Maybe the old password was not correct." => "Non foi posíbel cambiar o contrasinal. Probabelmente o contrasinal antigo non é o correcto.",
|
||||
"Saving..." => "Gardando...",
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Recovery key successfully " => "Chiave ripristinata correttamente",
|
||||
"Could not " => "Impossibile",
|
||||
"Recovery key successfully enabled" => "Chiave di ripristino abilitata correttamente",
|
||||
"Could not enable recovery key. Please check your recovery key password!" => "Impossibile abilitare la chiave di ripristino. Verifica la password della chiave di ripristino.",
|
||||
"Recovery key successfully disabled" => "Chiave di ripristinata disabilitata correttamente",
|
||||
"Could not disable recovery key. Please check your recovery key password!" => "Impossibile disabilitare la chiave di ripristino. Verifica la password della chiave di ripristino.",
|
||||
"Password successfully changed." => "Password modificata correttamente.",
|
||||
"Could not change the password. Maybe the old password was not correct." => "Impossibile cambiare la password. Forse la vecchia password non era corretta.",
|
||||
"Saving..." => "Salvataggio in corso...",
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Recovery key successfully " => "鍵を復旧することができました。",
|
||||
"Could not " => "できませんでした。",
|
||||
"Password successfully changed." => "パスワードを変更できました。",
|
||||
"Could not change the password. Maybe the old password was not correct." => "パスワードを変更できませんでした。古いパスワードが間違っているかもしれません。",
|
||||
"Saving..." => "保存中...",
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Recovery key successfully " => "Sleutelherstel succesvol",
|
||||
"Could not " => "Kon niet",
|
||||
"Password successfully changed." => "Wachtwoord succesvol gewijzigd.",
|
||||
"Could not change the password. Maybe the old password was not correct." => "Kon wachtwoord niet wijzigen. Wellicht oude wachtwoord niet juist ingevoerd.",
|
||||
"Saving..." => "Opslaan",
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Recovery key successfully " => "Odzyskanie klucza udane",
|
||||
"Could not " => "Nie można",
|
||||
"Password successfully changed." => "Zmiana hasła udana.",
|
||||
"Could not change the password. Maybe the old password was not correct." => "Nie można zmienić hasła. Może stare hasło nie było poprawne.",
|
||||
"Saving..." => "Zapisywanie...",
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Recovery key successfully " => "Recuperação de chave com sucesso",
|
||||
"Could not " => "Não foi possível",
|
||||
"Password successfully changed." => "Senha alterada com sucesso.",
|
||||
"Could not change the password. Maybe the old password was not correct." => "Não foi possível alterar a senha. Talvez a senha antiga não estava correta.",
|
||||
"Saving..." => "Salvando...",
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Password successfully changed." => "Password alterada com sucesso.",
|
||||
"Could not change the password. Maybe the old password was not correct." => "Não foi possivel alterar a password. Possivelmente a password antiga não está correcta.",
|
||||
"Saving..." => "A guardar...",
|
||||
"Encryption" => "Encriptação"
|
||||
"Encryption" => "Encriptação",
|
||||
"Enabled" => "Activado",
|
||||
"Disabled" => "Desactivado",
|
||||
"Change Password" => "Mudar a Password"
|
||||
);
|
||||
|
|
|
@ -1,4 +1,18 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Password successfully changed." => "Пароль изменен удачно.",
|
||||
"Could not change the password. Maybe the old password was not correct." => "Невозможно изменить пароль. Возможно старый пароль не был верен.",
|
||||
"Saving..." => "Сохранение...",
|
||||
"Encryption" => "Шифрование"
|
||||
"Encryption" => "Шифрование",
|
||||
"Enable encryption passwords recovery key (allow sharing to recovery key):" => "Включить шифрование пароля ключа восстановления (понадобится разрешение для восстановления ключа)",
|
||||
"Recovery account password" => "Восстановление пароля учетной записи",
|
||||
"Enabled" => "Включено",
|
||||
"Disabled" => "Отключено",
|
||||
"Change encryption passwords recovery key:" => "Изменить шифрование пароля ключа восстановления:",
|
||||
"Old Recovery account password" => "Старое Восстановление пароля учетной записи",
|
||||
"New Recovery account password" => "Новое Восстановление пароля учетной записи",
|
||||
"Change Password" => "Изменить пароль",
|
||||
"Enable password recovery by sharing all files with your administrator:" => "Включить восстановление пароля путем доступа Вашего администратора ко всем файлам",
|
||||
"Enabling this option will allow you to reobtain access to your encrypted files if your password is lost" => "Включение этой опции позволит вам получить доступ к зашифрованным файлам, в случае утери пароля",
|
||||
"File recovery settings updated" => "Настройки файла восстановления обновлены",
|
||||
"Could not update file recovery" => "Невозможно обновить файл восстановления"
|
||||
);
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Password successfully changed." => "Heslo úspešne zmenené.",
|
||||
"Saving..." => "Ukladám...",
|
||||
"Encryption" => "Šifrovanie"
|
||||
"Encryption" => "Šifrovanie",
|
||||
"Enabled" => "Povolené",
|
||||
"Disabled" => "Zakázané",
|
||||
"Change encryption passwords recovery key:" => "Zmeniť šifrovacie heslo obnovovacieho kľúča:",
|
||||
"Change Password" => "Zmeniť heslo",
|
||||
"File recovery settings updated" => "Nastavenie obnovy súborov aktualizované",
|
||||
"Could not update file recovery" => "Nemožno aktualizovať obnovenie súborov"
|
||||
);
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Recovery key successfully " => "成功還原金鑰",
|
||||
"Could not " => "無法",
|
||||
"Password successfully changed." => "成功變更密碼。",
|
||||
"Could not change the password. Maybe the old password was not correct." => "無法變更密碼,或許是輸入的舊密碼不正確。",
|
||||
"Saving..." => "儲存中...",
|
||||
|
|
|
@ -26,21 +26,20 @@
|
|||
namespace OCA\Encryption;
|
||||
|
||||
//require_once '../3rdparty/Crypt_Blowfish/Blowfish.php';
|
||||
require_once realpath( dirname( __FILE__ ) . '/../3rdparty/Crypt_Blowfish/Blowfish.php' );
|
||||
require_once realpath(dirname(__FILE__) . '/../3rdparty/Crypt_Blowfish/Blowfish.php');
|
||||
|
||||
/**
|
||||
* Class for common cryptography functionality
|
||||
*/
|
||||
|
||||
class Crypt
|
||||
{
|
||||
class Crypt {
|
||||
|
||||
/**
|
||||
* @brief return encryption mode client or server side encryption
|
||||
* @param string $user name (use system wide setting if name=null)
|
||||
* @return string 'client' or 'server'
|
||||
*/
|
||||
public static function mode( $user = null ) {
|
||||
public static function mode($user = null) {
|
||||
|
||||
return 'server';
|
||||
|
||||
|
@ -52,17 +51,20 @@ class Crypt
|
|||
*/
|
||||
public static function createKeypair() {
|
||||
|
||||
$res = openssl_pkey_new( array( 'private_key_bits' => 4096 ) );
|
||||
$res = openssl_pkey_new(array('private_key_bits' => 4096));
|
||||
|
||||
// Get private key
|
||||
openssl_pkey_export( $res, $privateKey );
|
||||
openssl_pkey_export($res, $privateKey);
|
||||
|
||||
// Get public key
|
||||
$publicKey = openssl_pkey_get_details( $res );
|
||||
$publicKey = openssl_pkey_get_details($res);
|
||||
|
||||
$publicKey = $publicKey['key'];
|
||||
|
||||
return ( array( 'publicKey' => $publicKey, 'privateKey' => $privateKey ) );
|
||||
return (array(
|
||||
'publicKey' => $publicKey,
|
||||
'privateKey' => $privateKey
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
|
@ -75,7 +77,7 @@ class Crypt
|
|||
* blocks with encryption alone, hence padding is added to achieve the
|
||||
* required length.
|
||||
*/
|
||||
public static function addPadding( $data ) {
|
||||
public static function addPadding($data) {
|
||||
|
||||
$padded = $data . 'xx';
|
||||
|
||||
|
@ -88,11 +90,11 @@ class Crypt
|
|||
* @param string $padded padded data to remove padding from
|
||||
* @return string unpadded data on success, false on error
|
||||
*/
|
||||
public static function removePadding( $padded ) {
|
||||
public static function removePadding($padded) {
|
||||
|
||||
if ( substr( $padded, -2 ) == 'xx' ) {
|
||||
if (substr($padded, -2) === 'xx') {
|
||||
|
||||
$data = substr( $padded, 0, -2 );
|
||||
$data = substr($padded, 0, -2);
|
||||
|
||||
return $data;
|
||||
|
||||
|
@ -111,26 +113,26 @@ class Crypt
|
|||
* @return boolean
|
||||
* @note see also OCA\Encryption\Util->isEncryptedPath()
|
||||
*/
|
||||
public static function isCatfileContent( $content ) {
|
||||
public static function isCatfileContent($content) {
|
||||
|
||||
if ( !$content ) {
|
||||
if (!$content) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
$noPadding = self::removePadding( $content );
|
||||
$noPadding = self::removePadding($content);
|
||||
|
||||
// Fetch encryption metadata from end of file
|
||||
$meta = substr( $noPadding, -22 );
|
||||
$meta = substr($noPadding, -22);
|
||||
|
||||
// Fetch IV from end of file
|
||||
$iv = substr( $meta, -16 );
|
||||
$iv = substr($meta, -16);
|
||||
|
||||
// Fetch identifier from start of metadata
|
||||
$identifier = substr( $meta, 0, 6 );
|
||||
$identifier = substr($meta, 0, 6);
|
||||
|
||||
if ( $identifier == '00iv00' ) {
|
||||
if ($identifier === '00iv00') {
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -147,15 +149,15 @@ class Crypt
|
|||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public static function isEncryptedMeta( $path ) {
|
||||
public static function isEncryptedMeta($path) {
|
||||
|
||||
// TODO: Use DI to get \OC\Files\Filesystem out of here
|
||||
|
||||
// Fetch all file metadata from DB
|
||||
$metadata = \OC\Files\Filesystem::getFileInfo( $path );
|
||||
$metadata = \OC\Files\Filesystem::getFileInfo($path);
|
||||
|
||||
// Return encryption status
|
||||
return isset( $metadata['encrypted'] ) and ( bool )$metadata['encrypted'];
|
||||
return isset($metadata['encrypted']) && ( bool )$metadata['encrypted'];
|
||||
|
||||
}
|
||||
|
||||
|
@ -166,18 +168,17 @@ class Crypt
|
|||
* e.g. filename or /Docs/filename, NOT admin/files/filename
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isLegacyEncryptedContent( $data, $relPath ) {
|
||||
public static function isLegacyEncryptedContent($data, $relPath) {
|
||||
|
||||
// Fetch all file metadata from DB
|
||||
$metadata = \OC\Files\Filesystem::getFileInfo( $relPath, '' );
|
||||
$metadata = \OC\Files\Filesystem::getFileInfo($relPath, '');
|
||||
|
||||
// If a file is flagged with encryption in DB, but isn't a
|
||||
// valid content + IV combination, it's probably using the
|
||||
// legacy encryption system
|
||||
if (
|
||||
isset( $metadata['encrypted'] )
|
||||
and $metadata['encrypted'] === true
|
||||
and !self::isCatfileContent( $data )
|
||||
if (isset($metadata['encrypted'])
|
||||
&& $metadata['encrypted'] === true
|
||||
&& !self::isCatfileContent($data)
|
||||
) {
|
||||
|
||||
return true;
|
||||
|
@ -197,15 +198,15 @@ class Crypt
|
|||
* @param string $passphrase
|
||||
* @return string encrypted file content
|
||||
*/
|
||||
public static function encrypt( $plainContent, $iv, $passphrase = '' ) {
|
||||
public static function encrypt($plainContent, $iv, $passphrase = '') {
|
||||
|
||||
if ( $encryptedContent = openssl_encrypt( $plainContent, 'AES-128-CFB', $passphrase, false, $iv ) ) {
|
||||
if ($encryptedContent = openssl_encrypt($plainContent, 'AES-128-CFB', $passphrase, false, $iv)) {
|
||||
|
||||
return $encryptedContent;
|
||||
|
||||
} else {
|
||||
|
||||
\OC_Log::write( 'Encryption library', 'Encryption (symmetric) of content failed', \OC_Log::ERROR );
|
||||
\OCP\Util::writeLog('Encryption library', 'Encryption (symmetric) of content failed', \OCP\Util::ERROR);
|
||||
|
||||
return false;
|
||||
|
||||
|
@ -221,15 +222,15 @@ class Crypt
|
|||
* @throws \Exception
|
||||
* @return string decrypted file content
|
||||
*/
|
||||
public static function decrypt( $encryptedContent, $iv, $passphrase ) {
|
||||
public static function decrypt($encryptedContent, $iv, $passphrase) {
|
||||
|
||||
if ( $plainContent = openssl_decrypt( $encryptedContent, 'AES-128-CFB', $passphrase, false, $iv ) ) {
|
||||
if ($plainContent = openssl_decrypt($encryptedContent, 'AES-128-CFB', $passphrase, false, $iv)) {
|
||||
|
||||
return $plainContent;
|
||||
|
||||
} else {
|
||||
|
||||
throw new \Exception( 'Encryption library: Decryption (symmetric) of content failed' );
|
||||
throw new \Exception('Encryption library: Decryption (symmetric) of content failed');
|
||||
|
||||
}
|
||||
|
||||
|
@ -241,7 +242,7 @@ class Crypt
|
|||
* @param string $iv IV to be concatenated
|
||||
* @returns string concatenated content
|
||||
*/
|
||||
public static function concatIv( $content, $iv ) {
|
||||
public static function concatIv($content, $iv) {
|
||||
|
||||
$combined = $content . '00iv00' . $iv;
|
||||
|
||||
|
@ -254,20 +255,20 @@ class Crypt
|
|||
* @param string $catFile concatenated data to be split
|
||||
* @returns array keys: encrypted, iv
|
||||
*/
|
||||
public static function splitIv( $catFile ) {
|
||||
public static function splitIv($catFile) {
|
||||
|
||||
// Fetch encryption metadata from end of file
|
||||
$meta = substr( $catFile, -22 );
|
||||
$meta = substr($catFile, -22);
|
||||
|
||||
// Fetch IV from end of file
|
||||
$iv = substr( $meta, -16 );
|
||||
$iv = substr($meta, -16);
|
||||
|
||||
// Remove IV and IV identifier text to expose encrypted content
|
||||
$encrypted = substr( $catFile, 0, -22 );
|
||||
$encrypted = substr($catFile, 0, -22);
|
||||
|
||||
$split = array(
|
||||
'encrypted' => $encrypted
|
||||
, 'iv' => $iv
|
||||
'encrypted' => $encrypted,
|
||||
'iv' => $iv
|
||||
);
|
||||
|
||||
return $split;
|
||||
|
@ -283,9 +284,9 @@ class Crypt
|
|||
* @note IV need not be specified, as it will be stored in the returned keyfile
|
||||
* and remain accessible therein.
|
||||
*/
|
||||
public static function symmetricEncryptFileContent( $plainContent, $passphrase = '' ) {
|
||||
public static function symmetricEncryptFileContent($plainContent, $passphrase = '') {
|
||||
|
||||
if ( !$plainContent ) {
|
||||
if (!$plainContent) {
|
||||
|
||||
return false;
|
||||
|
||||
|
@ -293,18 +294,18 @@ class Crypt
|
|||
|
||||
$iv = self::generateIv();
|
||||
|
||||
if ( $encryptedContent = self::encrypt( $plainContent, $iv, $passphrase ) ) {
|
||||
if ($encryptedContent = self::encrypt($plainContent, $iv, $passphrase)) {
|
||||
|
||||
// Combine content to encrypt with IV identifier and actual IV
|
||||
$catfile = self::concatIv( $encryptedContent, $iv );
|
||||
$catfile = self::concatIv($encryptedContent, $iv);
|
||||
|
||||
$padded = self::addPadding( $catfile );
|
||||
$padded = self::addPadding($catfile);
|
||||
|
||||
return $padded;
|
||||
|
||||
} else {
|
||||
|
||||
\OC_Log::write( 'Encryption library', 'Encryption (symmetric) of keyfile content failed', \OC_Log::ERROR );
|
||||
\OCP\Util::writeLog('Encryption library', 'Encryption (symmetric) of keyfile content failed', \OCP\Util::ERROR);
|
||||
|
||||
return false;
|
||||
|
||||
|
@ -326,21 +327,21 @@ class Crypt
|
|||
*
|
||||
* This function decrypts a file
|
||||
*/
|
||||
public static function symmetricDecryptFileContent( $keyfileContent, $passphrase = '' ) {
|
||||
public static function symmetricDecryptFileContent($keyfileContent, $passphrase = '') {
|
||||
|
||||
if ( !$keyfileContent ) {
|
||||
if (!$keyfileContent) {
|
||||
|
||||
throw new \Exception( 'Encryption library: no data provided for decryption' );
|
||||
throw new \Exception('Encryption library: no data provided for decryption');
|
||||
|
||||
}
|
||||
|
||||
// Remove padding
|
||||
$noPadding = self::removePadding( $keyfileContent );
|
||||
$noPadding = self::removePadding($keyfileContent);
|
||||
|
||||
// Split into enc data and catfile
|
||||
$catfile = self::splitIv( $noPadding );
|
||||
$catfile = self::splitIv($noPadding);
|
||||
|
||||
if ( $plainContent = self::decrypt( $catfile['encrypted'], $catfile['iv'], $passphrase ) ) {
|
||||
if ($plainContent = self::decrypt($catfile['encrypted'], $catfile['iv'], $passphrase)) {
|
||||
|
||||
return $plainContent;
|
||||
|
||||
|
@ -358,11 +359,11 @@ class Crypt
|
|||
*
|
||||
* This function decrypts a file
|
||||
*/
|
||||
public static function symmetricEncryptFileContentKeyfile( $plainContent ) {
|
||||
public static function symmetricEncryptFileContentKeyfile($plainContent) {
|
||||
|
||||
$key = self::generateKey();
|
||||
|
||||
if ( $encryptedContent = self::symmetricEncryptFileContent( $plainContent, $key ) ) {
|
||||
if ($encryptedContent = self::symmetricEncryptFileContent($plainContent, $key)) {
|
||||
|
||||
return array(
|
||||
'key' => $key,
|
||||
|
@ -384,13 +385,13 @@ class Crypt
|
|||
* @returns array keys: keys (array, key = userId), data
|
||||
* @note symmetricDecryptFileContent() can decrypt files created using this method
|
||||
*/
|
||||
public static function multiKeyEncrypt( $plainContent, array $publicKeys ) {
|
||||
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 ) ) {
|
||||
if (empty($plainContent)) {
|
||||
|
||||
throw new \Exception( 'Cannot mutliKeyEncrypt empty plain content' );
|
||||
throw new \Exception('Cannot mutliKeyEncrypt empty plain content');
|
||||
|
||||
}
|
||||
|
||||
|
@ -399,13 +400,13 @@ class Crypt
|
|||
$shareKeys = array();
|
||||
$mappedShareKeys = array();
|
||||
|
||||
if ( openssl_seal( $plainContent, $sealed, $shareKeys, $publicKeys ) ) {
|
||||
if (openssl_seal($plainContent, $sealed, $shareKeys, $publicKeys)) {
|
||||
|
||||
$i = 0;
|
||||
|
||||
// Ensure each shareKey is labelled with its
|
||||
// corresponding userId
|
||||
foreach ( $publicKeys as $userId => $publicKey ) {
|
||||
foreach ($publicKeys as $userId => $publicKey) {
|
||||
|
||||
$mappedShareKeys[$userId] = $shareKeys[$i];
|
||||
$i++;
|
||||
|
@ -437,21 +438,21 @@ class Crypt
|
|||
*
|
||||
* This function decrypts a file
|
||||
*/
|
||||
public static function multiKeyDecrypt( $encryptedContent, $shareKey, $privateKey ) {
|
||||
public static function multiKeyDecrypt($encryptedContent, $shareKey, $privateKey) {
|
||||
|
||||
if ( !$encryptedContent ) {
|
||||
if (!$encryptedContent) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
if ( openssl_open( $encryptedContent, $plainContent, $shareKey, $privateKey ) ) {
|
||||
if (openssl_open($encryptedContent, $plainContent, $shareKey, $privateKey)) {
|
||||
|
||||
return $plainContent;
|
||||
|
||||
} else {
|
||||
|
||||
\OC_Log::write( 'Encryption library', 'Decryption (asymmetric) of sealed content failed', \OC_Log::ERROR );
|
||||
\OCP\Util::writeLog('Encryption library', 'Decryption (asymmetric) of sealed content failed', \OCP\Util::ERROR);
|
||||
|
||||
return false;
|
||||
|
||||
|
@ -461,11 +462,13 @@ class Crypt
|
|||
|
||||
/**
|
||||
* @brief Asymetrically encrypt a string using a public key
|
||||
* @param $plainContent
|
||||
* @param $publicKey
|
||||
* @return string encrypted file
|
||||
*/
|
||||
public static function keyEncrypt( $plainContent, $publicKey ) {
|
||||
public static function keyEncrypt($plainContent, $publicKey) {
|
||||
|
||||
openssl_public_encrypt( $plainContent, $encryptedContent, $publicKey );
|
||||
openssl_public_encrypt($plainContent, $encryptedContent, $publicKey);
|
||||
|
||||
return $encryptedContent;
|
||||
|
||||
|
@ -473,13 +476,15 @@ class Crypt
|
|||
|
||||
/**
|
||||
* @brief Asymetrically decrypt a file using a private key
|
||||
* @param $encryptedContent
|
||||
* @param $privatekey
|
||||
* @return string decrypted file
|
||||
*/
|
||||
public static function keyDecrypt( $encryptedContent, $privatekey ) {
|
||||
public static function keyDecrypt($encryptedContent, $privatekey) {
|
||||
|
||||
$result = @openssl_private_decrypt( $encryptedContent, $plainContent, $privatekey );
|
||||
$result = @openssl_private_decrypt($encryptedContent, $plainContent, $privatekey);
|
||||
|
||||
if ( $result ) {
|
||||
if ($result) {
|
||||
return $plainContent;
|
||||
}
|
||||
|
||||
|
@ -493,24 +498,24 @@ class Crypt
|
|||
*/
|
||||
public static function generateIv() {
|
||||
|
||||
if ( $random = openssl_random_pseudo_bytes( 12, $strong ) ) {
|
||||
if ($random = openssl_random_pseudo_bytes(12, $strong)) {
|
||||
|
||||
if ( !$strong ) {
|
||||
if (!$strong) {
|
||||
|
||||
// If OpenSSL indicates randomness is insecure, log error
|
||||
\OC_Log::write( 'Encryption library', 'Insecure symmetric key was generated using openssl_random_pseudo_bytes()', \OC_Log::WARN );
|
||||
\OCP\Util::writeLog('Encryption library', 'Insecure symmetric key was generated using openssl_random_pseudo_bytes()', \OCP\Util::WARN);
|
||||
|
||||
}
|
||||
|
||||
// We encode the iv purely for string manipulation
|
||||
// purposes - it gets decoded before use
|
||||
$iv = base64_encode( $random );
|
||||
$iv = base64_encode($random);
|
||||
|
||||
return $iv;
|
||||
|
||||
} else {
|
||||
|
||||
throw new \Exception( 'Generating IV failed' );
|
||||
throw new \Exception('Generating IV failed');
|
||||
|
||||
}
|
||||
|
||||
|
@ -523,12 +528,12 @@ class Crypt
|
|||
public static function generateKey() {
|
||||
|
||||
// Generate key
|
||||
if ( $key = base64_encode( openssl_random_pseudo_bytes( 183, $strong ) ) ) {
|
||||
if ($key = base64_encode(openssl_random_pseudo_bytes(183, $strong))) {
|
||||
|
||||
if ( !$strong ) {
|
||||
if (!$strong) {
|
||||
|
||||
// If OpenSSL indicates randomness is insecure, log error
|
||||
throw new \Exception( 'Encryption library, Insecure symmetric key was generated using openssl_random_pseudo_bytes()' );
|
||||
throw new \Exception('Encryption library, Insecure symmetric key was generated using openssl_random_pseudo_bytes()');
|
||||
|
||||
}
|
||||
|
||||
|
@ -545,15 +550,15 @@ class Crypt
|
|||
/**
|
||||
* @brief Get the blowfish encryption handeler for a key
|
||||
* @param $key string (optional)
|
||||
* @return Crypt_Blowfish blowfish object
|
||||
* @return \Crypt_Blowfish blowfish object
|
||||
*
|
||||
* if the key is left out, the default handeler will be used
|
||||
*/
|
||||
public static function getBlowfish( $key = '' ) {
|
||||
public static function getBlowfish($key = '') {
|
||||
|
||||
if ( $key ) {
|
||||
if ($key) {
|
||||
|
||||
return new \Crypt_Blowfish( $key );
|
||||
return new \Crypt_Blowfish($key);
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -567,13 +572,13 @@ class Crypt
|
|||
* @param $passphrase
|
||||
* @return mixed
|
||||
*/
|
||||
public static function legacyCreateKey( $passphrase ) {
|
||||
public static function legacyCreateKey($passphrase) {
|
||||
|
||||
// Generate a random integer
|
||||
$key = mt_rand( 10000, 99999 ) . mt_rand( 10000, 99999 ) . mt_rand( 10000, 99999 ) . mt_rand( 10000, 99999 );
|
||||
$key = mt_rand(10000, 99999) . mt_rand(10000, 99999) . mt_rand(10000, 99999) . mt_rand(10000, 99999);
|
||||
|
||||
// Encrypt the key with the passphrase
|
||||
$legacyEncKey = self::legacyEncrypt( $key, $passphrase );
|
||||
$legacyEncKey = self::legacyEncrypt($key, $passphrase);
|
||||
|
||||
return $legacyEncKey;
|
||||
|
||||
|
@ -583,17 +588,15 @@ class Crypt
|
|||
* @brief encrypts content using legacy blowfish system
|
||||
* @param string $content the cleartext message you want to encrypt
|
||||
* @param string $passphrase
|
||||
* @return
|
||||
* @internal param \OCA\Encryption\the $key encryption key (optional)
|
||||
* @returns string encrypted content
|
||||
*
|
||||
* This function encrypts an content
|
||||
*/
|
||||
public static function legacyEncrypt( $content, $passphrase = '' ) {
|
||||
public static function legacyEncrypt($content, $passphrase = '') {
|
||||
|
||||
$bf = self::getBlowfish( $passphrase );
|
||||
$bf = self::getBlowfish($passphrase);
|
||||
|
||||
return $bf->encrypt( $content );
|
||||
return $bf->encrypt($content);
|
||||
|
||||
}
|
||||
|
||||
|
@ -601,20 +604,17 @@ class Crypt
|
|||
* @brief decrypts content using legacy blowfish system
|
||||
* @param string $content the cleartext message you want to decrypt
|
||||
* @param string $passphrase
|
||||
* @return string
|
||||
* @internal param \OCA\Encryption\the $key encryption key (optional)
|
||||
* @return string cleartext content
|
||||
*
|
||||
* This function decrypts an content
|
||||
*/
|
||||
private static function legacyDecrypt( $content, $passphrase = '' ) {
|
||||
private static function legacyDecrypt($content, $passphrase = '') {
|
||||
|
||||
$bf = self::getBlowfish( $passphrase );
|
||||
$bf = self::getBlowfish($passphrase);
|
||||
|
||||
$decrypted = $bf->decrypt( $content );
|
||||
$decrypted = $bf->decrypt($content);
|
||||
|
||||
return $decrypted;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -623,16 +623,17 @@ class Crypt
|
|||
* @param int $maxLength
|
||||
* @return string
|
||||
*/
|
||||
public static function legacyBlockDecrypt( $data, $key = '', $maxLength = 0 ) {
|
||||
public static function legacyBlockDecrypt($data, $key = '', $maxLength = 0) {
|
||||
|
||||
$result = '';
|
||||
while ( strlen( $data ) ) {
|
||||
$result .= self::legacyDecrypt( substr( $data, 0, 8192 ), $key );
|
||||
$data = substr( $data, 8192 );
|
||||
while (strlen($data)) {
|
||||
$result .= self::legacyDecrypt(substr($data, 0, 8192), $key);
|
||||
$data = substr($data, 8192);
|
||||
}
|
||||
if ( $maxLength > 0 ) {
|
||||
return substr( $result, 0, $maxLength );
|
||||
if ($maxLength > 0) {
|
||||
return substr($result, 0, $maxLength);
|
||||
} else {
|
||||
return rtrim( $result, "\0" );
|
||||
return rtrim($result, "\0");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -640,21 +641,23 @@ class Crypt
|
|||
* @param $legacyEncryptedContent
|
||||
* @param $legacyPassphrase
|
||||
* @param $publicKeys
|
||||
* @param $newPassphrase
|
||||
* @param $path
|
||||
* @return array
|
||||
*/
|
||||
public static function legacyKeyRecryptKeyfile( $legacyEncryptedContent, $legacyPassphrase, $publicKeys, $newPassphrase, $path ) {
|
||||
public static function legacyKeyRecryptKeyfile($legacyEncryptedContent, $legacyPassphrase, $publicKeys) {
|
||||
|
||||
$decrypted = self::legacyBlockDecrypt( $legacyEncryptedContent, $legacyPassphrase );
|
||||
$decrypted = self::legacyBlockDecrypt($legacyEncryptedContent, $legacyPassphrase);
|
||||
|
||||
// Encrypt plain data, generate keyfile & encrypted file
|
||||
$cryptedData = self::symmetricEncryptFileContentKeyfile( $decrypted );
|
||||
$cryptedData = self::symmetricEncryptFileContentKeyfile($decrypted);
|
||||
|
||||
// Encrypt plain keyfile to multiple sharefiles
|
||||
$multiEncrypted = Crypt::multiKeyEncrypt( $cryptedData['key'], $publicKeys );
|
||||
$multiEncrypted = Crypt::multiKeyEncrypt($cryptedData['key'], $publicKeys);
|
||||
|
||||
return array( 'data' => $cryptedData['encrypted'], 'filekey' => $multiEncrypted['data'], 'sharekeys' => $multiEncrypted['keys'] );
|
||||
return array(
|
||||
'data' => $cryptedData['encrypted'],
|
||||
'filekey' => $multiEncrypted['data'],
|
||||
'sharekeys' => $multiEncrypted['keys']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -23,15 +23,11 @@
|
|||
|
||||
namespace OCA\Encryption;
|
||||
|
||||
/**
|
||||
* @brief Class to manage registration of hooks an various helper methods
|
||||
*/
|
||||
/**
|
||||
* Class Helper
|
||||
* @brief Class to manage registration of hooks an various helper methods
|
||||
* @package OCA\Encryption
|
||||
*/
|
||||
class Helper
|
||||
{
|
||||
class Helper {
|
||||
|
||||
/**
|
||||
* @brief register share related hooks
|
||||
|
@ -39,9 +35,9 @@ class Helper
|
|||
*/
|
||||
public static function registerShareHooks() {
|
||||
|
||||
\OCP\Util::connectHook( 'OCP\Share', 'pre_shared', 'OCA\Encryption\Hooks', 'preShared' );
|
||||
\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_shared', 'OCA\Encryption\Hooks', 'preShared');
|
||||
\OCP\Util::connectHook('OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared');
|
||||
\OCP\Util::connectHook('OCP\Share', 'post_unshare', 'OCA\Encryption\Hooks', 'postUnshare');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,10 +46,10 @@ class Helper
|
|||
*/
|
||||
public static function registerUserHooks() {
|
||||
|
||||
\OCP\Util::connectHook( 'OC_User', 'post_login', 'OCA\Encryption\Hooks', 'login' );
|
||||
\OCP\Util::connectHook( 'OC_User', 'post_setPassword', 'OCA\Encryption\Hooks', 'setPassphrase' );
|
||||
\OCP\Util::connectHook( 'OC_User', 'post_createUser', 'OCA\Encryption\Hooks', 'postCreateUser' );
|
||||
\OCP\Util::connectHook( 'OC_User', 'post_deleteUser', 'OCA\Encryption\Hooks', 'postDeleteUser' );
|
||||
\OCP\Util::connectHook('OC_User', 'post_login', 'OCA\Encryption\Hooks', 'login');
|
||||
\OCP\Util::connectHook('OC_User', 'post_setPassword', 'OCA\Encryption\Hooks', 'setPassphrase');
|
||||
\OCP\Util::connectHook('OC_User', 'post_createUser', 'OCA\Encryption\Hooks', 'postCreateUser');
|
||||
\OCP\Util::connectHook('OC_User', 'post_deleteUser', 'OCA\Encryption\Hooks', 'postDeleteUser');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,7 +58,7 @@ class Helper
|
|||
*/
|
||||
public static function registerFilesystemHooks() {
|
||||
|
||||
\OCP\Util::connectHook( 'OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRename' );
|
||||
\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRename');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,13 +68,14 @@ class Helper
|
|||
* @param string $password
|
||||
* @return bool
|
||||
*/
|
||||
public static function setupUser( $util, $password ) {
|
||||
public static function setupUser($util, $password) {
|
||||
// Check files_encryption infrastructure is ready for action
|
||||
if ( !$util->ready() ) {
|
||||
if (!$util->ready()) {
|
||||
|
||||
\OC_Log::write( 'Encryption library', 'User account "' . $util->getUserId() . '" is not ready for encryption; configuration started', \OC_Log::DEBUG );
|
||||
\OCP\Util::writeLog('Encryption library', 'User account "' . $util->getUserId()
|
||||
. '" is not ready for encryption; configuration started', \OCP\Util::DEBUG);
|
||||
|
||||
if ( !$util->setupServerSide( $password ) ) {
|
||||
if (!$util->setupServerSide($password)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -95,21 +92,21 @@ class Helper
|
|||
* @internal param string $password
|
||||
* @return bool
|
||||
*/
|
||||
public static function adminEnableRecovery( $recoveryKeyId, $recoveryPassword ) {
|
||||
$view = new \OC\Files\View( '/' );
|
||||
public static function adminEnableRecovery($recoveryKeyId, $recoveryPassword) {
|
||||
$view = new \OC\Files\View('/');
|
||||
|
||||
if ( $recoveryKeyId === null ) {
|
||||
$recoveryKeyId = 'recovery_' . substr( md5( time() ), 0, 8 );
|
||||
\OC_Appconfig::setValue( 'files_encryption', 'recoveryKeyId', $recoveryKeyId );
|
||||
if ($recoveryKeyId === null) {
|
||||
$recoveryKeyId = 'recovery_' . substr(md5(time()), 0, 8);
|
||||
\OC_Appconfig::setValue('files_encryption', 'recoveryKeyId', $recoveryKeyId);
|
||||
}
|
||||
|
||||
if ( !$view->is_dir( '/owncloud_private_key' ) ) {
|
||||
$view->mkdir( '/owncloud_private_key' );
|
||||
if (!$view->is_dir('/owncloud_private_key')) {
|
||||
$view->mkdir('/owncloud_private_key');
|
||||
}
|
||||
|
||||
if (
|
||||
( !$view->file_exists( "/public-keys/" . $recoveryKeyId . ".public.key" )
|
||||
|| !$view->file_exists( "/owncloud_private_key/" . $recoveryKeyId . ".private.key" ) )
|
||||
(!$view->file_exists("/public-keys/" . $recoveryKeyId . ".public.key")
|
||||
|| !$view->file_exists("/owncloud_private_key/" . $recoveryKeyId . ".private.key"))
|
||||
) {
|
||||
|
||||
$keypair = \OCA\Encryption\Crypt::createKeypair();
|
||||
|
@ -118,37 +115,37 @@ class Helper
|
|||
|
||||
// Save public key
|
||||
|
||||
if ( !$view->is_dir( '/public-keys' ) ) {
|
||||
$view->mkdir( '/public-keys' );
|
||||
if (!$view->is_dir('/public-keys')) {
|
||||
$view->mkdir('/public-keys');
|
||||
}
|
||||
|
||||
$view->file_put_contents( '/public-keys/' . $recoveryKeyId . '.public.key', $keypair['publicKey'] );
|
||||
$view->file_put_contents('/public-keys/' . $recoveryKeyId . '.public.key', $keypair['publicKey']);
|
||||
|
||||
// Encrypt private key empthy passphrase
|
||||
$encryptedPrivateKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent( $keypair['privateKey'], $recoveryPassword );
|
||||
$encryptedPrivateKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($keypair['privateKey'], $recoveryPassword);
|
||||
|
||||
// Save private key
|
||||
$view->file_put_contents( '/owncloud_private_key/' . $recoveryKeyId . '.private.key', $encryptedPrivateKey );
|
||||
$view->file_put_contents('/owncloud_private_key/' . $recoveryKeyId . '.private.key', $encryptedPrivateKey);
|
||||
|
||||
// create control file which let us check later on if the entered password was correct.
|
||||
$encryptedControlData = \OCA\Encryption\Crypt::keyEncrypt( "ownCloud", $keypair['publicKey'] );
|
||||
if ( !$view->is_dir( '/control-file' ) ) {
|
||||
$view->mkdir( '/control-file' );
|
||||
$encryptedControlData = \OCA\Encryption\Crypt::keyEncrypt("ownCloud", $keypair['publicKey']);
|
||||
if (!$view->is_dir('/control-file')) {
|
||||
$view->mkdir('/control-file');
|
||||
}
|
||||
$view->file_put_contents( '/control-file/controlfile.enc', $encryptedControlData );
|
||||
$view->file_put_contents('/control-file/controlfile.enc', $encryptedControlData);
|
||||
|
||||
\OC_FileProxy::$enabled = true;
|
||||
|
||||
// Set recoveryAdmin as enabled
|
||||
\OC_Appconfig::setValue( 'files_encryption', 'recoveryAdminEnabled', 1 );
|
||||
\OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 1);
|
||||
|
||||
$return = true;
|
||||
|
||||
} else { // get recovery key and check the password
|
||||
$util = new \OCA\Encryption\Util( new \OC_FilesystemView( '/' ), \OCP\User::getUser() );
|
||||
$return = $util->checkRecoveryPassword( $recoveryPassword );
|
||||
if ( $return ) {
|
||||
\OC_Appconfig::setValue( 'files_encryption', 'recoveryAdminEnabled', 1 );
|
||||
$util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \OCP\User::getUser());
|
||||
$return = $util->checkRecoveryPassword($recoveryPassword);
|
||||
if ($return) {
|
||||
\OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,13 +159,13 @@ class Helper
|
|||
* @param $recoveryPassword
|
||||
* @return bool
|
||||
*/
|
||||
public static function adminDisableRecovery( $recoveryPassword ) {
|
||||
$util = new Util( new \OC_FilesystemView( '/' ), \OCP\User::getUser() );
|
||||
$return = $util->checkRecoveryPassword( $recoveryPassword );
|
||||
public static function adminDisableRecovery($recoveryPassword) {
|
||||
$util = new Util(new \OC_FilesystemView('/'), \OCP\User::getUser());
|
||||
$return = $util->checkRecoveryPassword($recoveryPassword);
|
||||
|
||||
if ( $return ) {
|
||||
if ($return) {
|
||||
// Set recoveryAdmin as disabled
|
||||
\OC_Appconfig::setValue( 'files_encryption', 'recoveryAdminEnabled', 0 );
|
||||
\OC_Appconfig::setValue('files_encryption', 'recoveryAdminEnabled', 0);
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
@ -189,4 +186,18 @@ class Helper
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Format a path to be relative to the /user/files/ directory
|
||||
* @param string $path the absolute path
|
||||
* @return string e.g. turns '/admin/files/test.txt' into 'test.txt'
|
||||
*/
|
||||
public static function stripUserFilesPath($path) {
|
||||
$trimmed = ltrim($path, '/');
|
||||
$split = explode('/', $trimmed);
|
||||
$sliced = array_slice($split, 2);
|
||||
$relPath = implode('/', $sliced);
|
||||
|
||||
return $relPath;
|
||||
}
|
||||
}
|
|
@ -27,8 +27,7 @@ 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
|
||||
{
|
||||
class Keymanager {
|
||||
|
||||
/**
|
||||
* @brief retrieve the ENCRYPTED private key from a user
|
||||
|
@ -38,14 +37,14 @@ class Keymanager
|
|||
* @return string private key or false (hopefully)
|
||||
* @note the key returned by this method must be decrypted before use
|
||||
*/
|
||||
public static function getPrivateKey( \OC_FilesystemView $view, $user ) {
|
||||
public static function getPrivateKey(\OC_FilesystemView $view, $user) {
|
||||
|
||||
$path = '/' . $user . '/' . 'files_encryption' . '/' . $user . '.private.key';
|
||||
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
$key = $view->file_get_contents( $path );
|
||||
$key = $view->file_get_contents($path);
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
|
@ -58,12 +57,12 @@ class Keymanager
|
|||
* @param $userId
|
||||
* @return string public key or false
|
||||
*/
|
||||
public static function getPublicKey( \OC_FilesystemView $view, $userId ) {
|
||||
public static function getPublicKey(\OC_FilesystemView $view, $userId) {
|
||||
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
$result = $view->file_get_contents( '/public-keys/' . $userId . '.public.key' );
|
||||
$result = $view->file_get_contents('/public-keys/' . $userId . '.public.key');
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
|
@ -77,11 +76,11 @@ class Keymanager
|
|||
* @param $userId
|
||||
* @return array keys: privateKey, publicKey
|
||||
*/
|
||||
public static function getUserKeys( \OC_FilesystemView $view, $userId ) {
|
||||
public static function getUserKeys(\OC_FilesystemView $view, $userId) {
|
||||
|
||||
return array(
|
||||
'publicKey' => self::getPublicKey( $view, $userId )
|
||||
, 'privateKey' => self::getPrivateKey( $view, $userId )
|
||||
'publicKey' => self::getPublicKey($view, $userId),
|
||||
'privateKey' => self::getPrivateKey($view, $userId)
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -92,13 +91,13 @@ class Keymanager
|
|||
* @param array $userIds
|
||||
* @return array of public keys for the specified users
|
||||
*/
|
||||
public static function getPublicKeys( \OC_FilesystemView $view, array $userIds ) {
|
||||
public static function getPublicKeys(\OC_FilesystemView $view, array $userIds) {
|
||||
|
||||
$keys = array();
|
||||
|
||||
foreach ( $userIds as $userId ) {
|
||||
foreach ($userIds as $userId) {
|
||||
|
||||
$keys[$userId] = self::getPublicKey( $view, $userId );
|
||||
$keys[$userId] = self::getPublicKey($view, $userId);
|
||||
|
||||
}
|
||||
|
||||
|
@ -118,40 +117,41 @@ class Keymanager
|
|||
* @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 ) {
|
||||
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
|
||||
$util = new Util( $view, \OCP\User::getUser() );
|
||||
list( $owner, $filename ) = $util->getUidAndFilename( $path );
|
||||
$util = new Util($view, \OCP\User::getUser());
|
||||
list($owner, $filename) = $util->getUidAndFilename($path);
|
||||
|
||||
$basePath = '/' . $owner . '/files_encryption/keyfiles';
|
||||
|
||||
$targetPath = self::keySetPreparation( $view, $filename, $basePath, $owner );
|
||||
$targetPath = self::keySetPreparation($view, $filename, $basePath, $owner);
|
||||
|
||||
if ( !$view->is_dir( $basePath . '/' . $targetPath ) ) {
|
||||
if (!$view->is_dir($basePath . '/' . $targetPath)) {
|
||||
|
||||
// create all parent folders
|
||||
$info = pathinfo( $basePath . '/' . $targetPath );
|
||||
$keyfileFolderName = $view->getLocalFolder( $info['dirname'] );
|
||||
$info = pathinfo($basePath . '/' . $targetPath);
|
||||
$keyfileFolderName = $view->getLocalFolder($info['dirname']);
|
||||
|
||||
if ( !file_exists( $keyfileFolderName ) ) {
|
||||
if (!file_exists($keyfileFolderName)) {
|
||||
|
||||
mkdir( $keyfileFolderName, 0750, true );
|
||||
mkdir($keyfileFolderName, 0750, true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// try reusing key file if part file
|
||||
if ( self::isPartialFilePath( $targetPath ) ) {
|
||||
if (self::isPartialFilePath($targetPath)) {
|
||||
|
||||
$result = $view->file_put_contents( $basePath . '/' . self::fixPartialFilePath( $targetPath ) . '.key', $catfile );
|
||||
$result = $view->file_put_contents(
|
||||
$basePath . '/' . self::fixPartialFilePath($targetPath) . '.key', $catfile);
|
||||
|
||||
} else {
|
||||
|
||||
$result = $view->file_put_contents( $basePath . '/' . $targetPath . '.key', $catfile );
|
||||
$result = $view->file_put_contents($basePath . '/' . $targetPath . '.key', $catfile);
|
||||
|
||||
}
|
||||
|
||||
|
@ -167,12 +167,12 @@ class Keymanager
|
|||
* @return string File path without .part extension
|
||||
* @note this is needed for reusing keys
|
||||
*/
|
||||
public static function fixPartialFilePath( $path ) {
|
||||
public static function fixPartialFilePath($path) {
|
||||
|
||||
if ( preg_match( '/\.part$/', $path ) ) {
|
||||
if (preg_match('/\.part$/', $path) || preg_match('/\.etmp$/', $path)) {
|
||||
|
||||
$newLength = strlen( $path ) - 5;
|
||||
$fPath = substr( $path, 0, $newLength );
|
||||
$newLength = strlen($path) - 5;
|
||||
$fPath = substr($path, 0, $newLength);
|
||||
|
||||
return $fPath;
|
||||
|
||||
|
@ -189,9 +189,9 @@ class Keymanager
|
|||
* @param string $path Path that may identify a .part file
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPartialFilePath( $path ) {
|
||||
public static function isPartialFilePath($path) {
|
||||
|
||||
if ( preg_match( '/\.part$/', $path ) ) {
|
||||
if (preg_match('/\.part$/', $path) || preg_match('/\.etmp$/', $path)) {
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -213,14 +213,14 @@ class Keymanager
|
|||
* @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 ) {
|
||||
public static function getFileKey(\OC_FilesystemView $view, $userId, $filePath) {
|
||||
|
||||
// try reusing key file if part file
|
||||
if ( self::isPartialFilePath( $filePath ) ) {
|
||||
if (self::isPartialFilePath($filePath)) {
|
||||
|
||||
$result = self::getFileKey( $view, $userId, self::fixPartialFilePath( $filePath ) );
|
||||
$result = self::getFileKey($view, $userId, self::fixPartialFilePath($filePath));
|
||||
|
||||
if ( $result ) {
|
||||
if ($result) {
|
||||
|
||||
return $result;
|
||||
|
||||
|
@ -228,19 +228,19 @@ class Keymanager
|
|||
|
||||
}
|
||||
|
||||
$util = new Util( $view, \OCP\User::getUser() );
|
||||
$util = new Util($view, \OCP\User::getUser());
|
||||
|
||||
list( $owner, $filename ) = $util->getUidAndFilename( $filePath );
|
||||
$filePath_f = ltrim( $filename, '/' );
|
||||
list($owner, $filename) = $util->getUidAndFilename($filePath);
|
||||
$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 ) ) {
|
||||
if ($view->file_exists($keyfilePath)) {
|
||||
|
||||
$result = $view->file_get_contents( $keyfilePath );
|
||||
$result = $view->file_get_contents($keyfilePath);
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -264,26 +264,29 @@ class Keymanager
|
|||
* @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 ) {
|
||||
public static function deleteFileKey(\OC_FilesystemView $view, $userId, $path) {
|
||||
|
||||
$trimmed = ltrim( $path, '/' );
|
||||
$trimmed = ltrim($path, '/');
|
||||
$keyPath = '/' . $userId . '/files_encryption/keyfiles/' . $trimmed;
|
||||
|
||||
$result = false;
|
||||
|
||||
if ( $view->is_dir( $keyPath ) ) {
|
||||
if ($view->is_dir($keyPath)) {
|
||||
|
||||
$result = $view->unlink( $keyPath );
|
||||
$result = $view->unlink($keyPath);
|
||||
|
||||
} else if ( $view->file_exists( $keyPath . '.key' ) ) {
|
||||
} else {
|
||||
if ($view->file_exists($keyPath . '.key')) {
|
||||
|
||||
$result = $view->unlink( $keyPath . '.key' );
|
||||
$result = $view->unlink($keyPath . '.key');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$result ) {
|
||||
if (!$result) {
|
||||
|
||||
\OC_Log::write( 'Encryption library', 'Could not delete keyfile; does not exist: "' . $keyPath, \OC_Log::ERROR );
|
||||
\OCP\Util::writeLog('Encryption library',
|
||||
'Could not delete keyfile; does not exist: "' . $keyPath, \OCP\Util::ERROR);
|
||||
|
||||
}
|
||||
|
||||
|
@ -298,19 +301,19 @@ class Keymanager
|
|||
* @note Encryption of the private key must be performed by client code
|
||||
* as no encryption takes place here
|
||||
*/
|
||||
public static function setPrivateKey( $key ) {
|
||||
public static function setPrivateKey($key) {
|
||||
|
||||
$user = \OCP\User::getUser();
|
||||
|
||||
$view = new \OC_FilesystemView( '/' . $user . '/files_encryption' );
|
||||
$view = new \OC_FilesystemView('/' . $user . '/files_encryption');
|
||||
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
if ( !$view->file_exists( '' ) )
|
||||
$view->mkdir( '' );
|
||||
if (!$view->file_exists(''))
|
||||
$view->mkdir('');
|
||||
|
||||
$result = $view->file_put_contents( $user . '.private.key', $key );
|
||||
$result = $view->file_put_contents($user . '.private.key', $key);
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
|
@ -331,21 +334,21 @@ class Keymanager
|
|||
* @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 ) {
|
||||
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
|
||||
$util = new Util( $view, \OCP\User::getUser() );
|
||||
$util = new Util($view, \OCP\User::getUser());
|
||||
|
||||
list( $owner, $filename ) = $util->getUidAndFilename( $path );
|
||||
list($owner, $filename) = $util->getUidAndFilename($path);
|
||||
|
||||
$basePath = '/' . $owner . '/files_encryption/share-keys';
|
||||
|
||||
$shareKeyPath = self::keySetPreparation( $view, $filename, $basePath, $owner );
|
||||
$shareKeyPath = self::keySetPreparation($view, $filename, $basePath, $owner);
|
||||
|
||||
// try reusing key file if part file
|
||||
if ( self::isPartialFilePath( $shareKeyPath ) ) {
|
||||
if (self::isPartialFilePath($shareKeyPath)) {
|
||||
|
||||
$writePath = $basePath . '/' . self::fixPartialFilePath( $shareKeyPath ) . '.' . $userId . '.shareKey';
|
||||
$writePath = $basePath . '/' . self::fixPartialFilePath($shareKeyPath) . '.' . $userId . '.shareKey';
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -356,12 +359,12 @@ class Keymanager
|
|||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
$result = $view->file_put_contents( $writePath, $shareKey );
|
||||
$result = $view->file_put_contents($writePath, $shareKey);
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
if (
|
||||
is_int( $result )
|
||||
is_int($result)
|
||||
&& $result > 0
|
||||
) {
|
||||
|
||||
|
@ -382,16 +385,16 @@ class Keymanager
|
|||
* @param array $shareKeys
|
||||
* @return bool
|
||||
*/
|
||||
public static function setShareKeys( \OC_FilesystemView $view, $path, array $shareKeys ) {
|
||||
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 ) {
|
||||
foreach ($shareKeys as $userId => $shareKey) {
|
||||
|
||||
if ( !self::setShareKey( $view, $path, $userId, $shareKey ) ) {
|
||||
if (!self::setShareKey($view, $path, $userId, $shareKey)) {
|
||||
|
||||
// If any of the keys are not set, flag false
|
||||
$result = false;
|
||||
|
@ -415,14 +418,14 @@ class Keymanager
|
|||
* @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 ) {
|
||||
public static function getShareKey(\OC_FilesystemView $view, $userId, $filePath) {
|
||||
|
||||
// try reusing key file if part file
|
||||
if ( self::isPartialFilePath( $filePath ) ) {
|
||||
if (self::isPartialFilePath($filePath)) {
|
||||
|
||||
$result = self::getShareKey( $view, $userId, self::fixPartialFilePath( $filePath ) );
|
||||
$result = self::getShareKey($view, $userId, self::fixPartialFilePath($filePath));
|
||||
|
||||
if ( $result ) {
|
||||
if ($result) {
|
||||
|
||||
return $result;
|
||||
|
||||
|
@ -434,14 +437,15 @@ class Keymanager
|
|||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
//here we need the currently logged in user, while userId can be a different user
|
||||
$util = new Util( $view, \OCP\User::getUser() );
|
||||
$util = new Util($view, \OCP\User::getUser());
|
||||
|
||||
list( $owner, $filename ) = $util->getUidAndFilename( $filePath );
|
||||
$shareKeyPath = \OC\Files\Filesystem::normalizePath( '/' . $owner . '/files_encryption/share-keys/' . $filename . '.' . $userId . '.shareKey' );
|
||||
list($owner, $filename) = $util->getUidAndFilename($filePath);
|
||||
$shareKeyPath = \OC\Files\Filesystem::normalizePath(
|
||||
'/' . $owner . '/files_encryption/share-keys/' . $filename . '.' . $userId . '.shareKey');
|
||||
|
||||
if ( $view->file_exists( $shareKeyPath ) ) {
|
||||
if ($view->file_exists($shareKeyPath)) {
|
||||
|
||||
$result = $view->file_get_contents( $shareKeyPath );
|
||||
$result = $view->file_get_contents($shareKeyPath);
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -461,17 +465,18 @@ class Keymanager
|
|||
* @param string $userId owner of the file
|
||||
* @param string $filePath path to the file, relative to the owners file dir
|
||||
*/
|
||||
public static function delAllShareKeys( \OC_FilesystemView $view, $userId, $filePath ) {
|
||||
public static function delAllShareKeys(\OC_FilesystemView $view, $userId, $filePath) {
|
||||
|
||||
if ( $view->is_dir( $userId . '/files/' . $filePath ) ) {
|
||||
$view->unlink( $userId . '/files_encryption/share-keys/' . $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 ) {
|
||||
$result = unlink( $ma );
|
||||
if ( !$result ) {
|
||||
\OC_Log::write( 'Encryption library', 'Keyfile or shareKey could not be deleted for file "' . $filePath . '"', \OC_Log::ERROR );
|
||||
$localKeyPath = $view->getLocalFile($userId . '/files_encryption/share-keys/' . $filePath);
|
||||
$matches = glob(preg_quote($localKeyPath) . '*.shareKey');
|
||||
foreach ($matches as $ma) {
|
||||
$result = unlink($ma);
|
||||
if (!$result) {
|
||||
\OCP\Util::writeLog('Encryption library',
|
||||
'Keyfile or shareKey could not be deleted for file "' . $filePath . '"', \OCP\Util::ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -480,29 +485,31 @@ class Keymanager
|
|||
/**
|
||||
* @brief Delete a single user's shareKey for a single file
|
||||
*/
|
||||
public static function delShareKey( \OC_FilesystemView $view, $userIds, $filePath ) {
|
||||
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
|
||||
$util = new Util( $view, \OCP\User::getUser() );
|
||||
$util = new Util($view, \OCP\User::getUser());
|
||||
|
||||
list( $owner, $filename ) = $util->getUidAndFilename( $filePath );
|
||||
list($owner, $filename) = $util->getUidAndFilename($filePath);
|
||||
|
||||
$shareKeyPath = \OC\Files\Filesystem::normalizePath( '/' . $owner . '/files_encryption/share-keys/' . $filename );
|
||||
$shareKeyPath = \OC\Files\Filesystem::normalizePath('/' . $owner . '/files_encryption/share-keys/' . $filename);
|
||||
|
||||
if ( $view->is_dir( $shareKeyPath ) ) {
|
||||
if ($view->is_dir($shareKeyPath)) {
|
||||
|
||||
$localPath = \OC\Files\Filesystem::normalizePath( $view->getLocalFolder( $shareKeyPath ) );
|
||||
self::recursiveDelShareKeys( $localPath, $userIds );
|
||||
$localPath = \OC\Files\Filesystem::normalizePath($view->getLocalFolder($shareKeyPath));
|
||||
self::recursiveDelShareKeys($localPath, $userIds);
|
||||
|
||||
} else {
|
||||
|
||||
foreach ( $userIds as $userId ) {
|
||||
foreach ($userIds as $userId) {
|
||||
|
||||
if ( !$view->unlink( $shareKeyPath . '.' . $userId . '.shareKey' ) ) {
|
||||
\OC_Log::write( 'Encryption library', 'Could not delete shareKey; does not exist: "' . $shareKeyPath . '.' . $userId . '.shareKey"', \OC_Log::ERROR );
|
||||
if (!$view->unlink($shareKeyPath . '.' . $userId . '.shareKey')) {
|
||||
\OCP\Util::writeLog('Encryption library',
|
||||
'Could not delete shareKey; does not exist: "' . $shareKeyPath . '.' . $userId
|
||||
. '.shareKey"', \OCP\Util::ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -517,42 +524,43 @@ class Keymanager
|
|||
* @param string $dir directory
|
||||
* @param array $userIds user ids for which the share keys should be deleted
|
||||
*/
|
||||
private static function recursiveDelShareKeys( $dir, $userIds ) {
|
||||
foreach ( $userIds as $userId ) {
|
||||
$matches = glob( preg_quote( $dir ) . '/*' . preg_quote( '.' . $userId . '.shareKey' ) );
|
||||
private static function recursiveDelShareKeys($dir, $userIds) {
|
||||
foreach ($userIds as $userId) {
|
||||
$matches = glob(preg_quote($dir) . '/*' . preg_quote('.' . $userId . '.shareKey'));
|
||||
}
|
||||
/** @var $matches array */
|
||||
foreach ( $matches as $ma ) {
|
||||
if ( !unlink( $ma ) ) {
|
||||
\OC_Log::write( 'Encryption library', 'Could not delete shareKey; does not exist: "' . $ma . '"', \OC_Log::ERROR );
|
||||
foreach ($matches as $ma) {
|
||||
if (!unlink($ma)) {
|
||||
\OCP\Util::writeLog('Encryption library',
|
||||
'Could not delete shareKey; does not exist: "' . $ma . '"', \OCP\Util::ERROR);
|
||||
}
|
||||
}
|
||||
$subdirs = $directories = glob( preg_quote( $dir ) . '/*', GLOB_ONLYDIR );
|
||||
foreach ( $subdirs as $subdir ) {
|
||||
self::recursiveDelShareKeys( $subdir, $userIds );
|
||||
$subdirs = $directories = glob(preg_quote($dir) . '/*', GLOB_ONLYDIR);
|
||||
foreach ($subdirs as $subdir) {
|
||||
self::recursiveDelShareKeys($subdir, $userIds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Make preparations to vars and filesystem for saving a keyfile
|
||||
*/
|
||||
public static function keySetPreparation( \OC_FilesystemView $view, $path, $basePath, $userId ) {
|
||||
public static function keySetPreparation(\OC_FilesystemView $view, $path, $basePath, $userId) {
|
||||
|
||||
$targetPath = ltrim( $path, '/' );
|
||||
$targetPath = ltrim($path, '/');
|
||||
|
||||
$path_parts = pathinfo( $targetPath );
|
||||
$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'] )
|
||||
isset($path_parts['dirname'])
|
||||
&& !$view->file_exists($basePath . '/' . $path_parts['dirname'])
|
||||
) {
|
||||
$sub_dirs = explode( DIRECTORY_SEPARATOR, $basePath . '/' . $path_parts['dirname'] );
|
||||
$sub_dirs = explode(DIRECTORY_SEPARATOR, $basePath . '/' . $path_parts['dirname']);
|
||||
$dir = '';
|
||||
foreach ( $sub_dirs as $sub_dir ) {
|
||||
foreach ($sub_dirs as $sub_dir) {
|
||||
$dir .= '/' . $sub_dir;
|
||||
if ( !$view->is_dir( $dir ) ) {
|
||||
$view->mkdir( $dir );
|
||||
if (!$view->is_dir($dir)) {
|
||||
$view->mkdir($dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,8 +34,7 @@ namespace OCA\Encryption;
|
|||
* Class Proxy
|
||||
* @package OCA\Encryption
|
||||
*/
|
||||
class Proxy extends \OC_FileProxy
|
||||
{
|
||||
class Proxy extends \OC_FileProxy {
|
||||
|
||||
private static $blackList = null; //mimetypes blacklisted from encryption
|
||||
|
||||
|
@ -48,13 +47,13 @@ class Proxy extends \OC_FileProxy
|
|||
*
|
||||
* Tests if server side encryption is enabled, and file is allowed by blacklists
|
||||
*/
|
||||
private static function shouldEncrypt( $path ) {
|
||||
private static function shouldEncrypt($path) {
|
||||
|
||||
if ( is_null( self::$enableEncryption ) ) {
|
||||
if (is_null(self::$enableEncryption)) {
|
||||
|
||||
if (
|
||||
\OCP\Config::getAppValue( 'files_encryption', 'enable_encryption', 'true' ) == 'true'
|
||||
&& Crypt::mode() == 'server'
|
||||
\OCP\Config::getAppValue('files_encryption', 'enable_encryption', 'true') === 'true'
|
||||
&& Crypt::mode() === 'server'
|
||||
) {
|
||||
|
||||
self::$enableEncryption = true;
|
||||
|
@ -67,27 +66,27 @@ class Proxy extends \OC_FileProxy
|
|||
|
||||
}
|
||||
|
||||
if ( !self::$enableEncryption ) {
|
||||
if (!self::$enableEncryption) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
if ( is_null( self::$blackList ) ) {
|
||||
if (is_null(self::$blackList)) {
|
||||
|
||||
self::$blackList = explode( ',', \OCP\Config::getAppValue( 'files_encryption', 'type_blacklist', '' ) );
|
||||
self::$blackList = explode(',', \OCP\Config::getAppValue('files_encryption', 'type_blacklist', ''));
|
||||
|
||||
}
|
||||
|
||||
if ( Crypt::isCatfileContent( $path ) ) {
|
||||
if (Crypt::isCatfileContent($path)) {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
$extension = substr( $path, strrpos( $path, '.' ) + 1 );
|
||||
$extension = substr($path, strrpos($path, '.') + 1);
|
||||
|
||||
if ( array_search( $extension, self::$blackList ) === false ) {
|
||||
if (array_search($extension, self::$blackList) === false) {
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -101,78 +100,44 @@ class Proxy extends \OC_FileProxy
|
|||
* @param $data
|
||||
* @return bool
|
||||
*/
|
||||
public function preFile_put_contents( $path, &$data ) {
|
||||
public function preFile_put_contents($path, &$data) {
|
||||
|
||||
if ( self::shouldEncrypt( $path ) ) {
|
||||
if (self::shouldEncrypt($path)) {
|
||||
|
||||
// Stream put contents should have been converted to fopen
|
||||
if ( !is_resource( $data ) ) {
|
||||
if (!is_resource($data)) {
|
||||
|
||||
$userId = \OCP\USER::getUser();
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
$util = new Util( $view, $userId );
|
||||
$session = new \OCA\Encryption\Session( $view );
|
||||
$privateKey = $session->getPrivateKey();
|
||||
$filePath = $util->stripUserFilesPath( $path );
|
||||
// Set the filesize for userland, before encrypting
|
||||
$size = strlen( $data );
|
||||
// get root view
|
||||
$view = new \OC_FilesystemView('/');
|
||||
|
||||
// Disable encryption proxy to prevent recursive calls
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
// Check if there is an existing key we can reuse
|
||||
if ( $encKeyfile = Keymanager::getFileKey( $view, $userId, $filePath ) ) {
|
||||
|
||||
// Fetch shareKey
|
||||
$shareKey = Keymanager::getShareKey( $view, $userId, $filePath );
|
||||
|
||||
// Decrypt the keyfile
|
||||
$plainKey = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey );
|
||||
|
||||
} else {
|
||||
|
||||
// Make a new key
|
||||
$plainKey = Crypt::generateKey();
|
||||
// get relative path
|
||||
$relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path);
|
||||
|
||||
if (!isset($relativePath)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Encrypt data
|
||||
$encData = Crypt::symmetricEncryptFileContent( $data, $plainKey );
|
||||
$handle = fopen('crypt://' . $relativePath . '.etmp', 'w');
|
||||
if (is_resource($handle)) {
|
||||
|
||||
$sharingEnabled = \OCP\Share::isEnabled();
|
||||
// write data to stream
|
||||
fwrite($handle, $data);
|
||||
|
||||
// if file exists try to get sharing users
|
||||
if ( $view->file_exists( $path ) ) {
|
||||
$uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $filePath, $userId );
|
||||
} else {
|
||||
$uniqueUserIds[] = $userId;
|
||||
// close stream
|
||||
fclose($handle);
|
||||
|
||||
// disable encryption proxy to prevent recursive calls
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
// get encrypted content
|
||||
$data = $view->file_get_contents($path . '.etmp');
|
||||
|
||||
// remove our temp file
|
||||
$view->unlink($path . '.etmp');
|
||||
|
||||
// re-enable proxy - our work is done
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
}
|
||||
|
||||
// Fetch public keys for all users who will share the file
|
||||
$publicKeys = Keymanager::getPublicKeys( $view, $uniqueUserIds );
|
||||
|
||||
// Encrypt plain keyfile to multiple sharefiles
|
||||
$multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys );
|
||||
|
||||
// Save sharekeys to user folders
|
||||
Keymanager::setShareKeys( $view, $filePath, $multiEncrypted['keys'] );
|
||||
|
||||
// Set encrypted keyfile as common varname
|
||||
$encKey = $multiEncrypted['data'];
|
||||
|
||||
// Save keyfile for newly encrypted file in parallel directory tree
|
||||
Keymanager::setFileKey( $view, $filePath, $userId, $encKey );
|
||||
|
||||
// Replace plain content with encrypted content by reference
|
||||
$data = $encData;
|
||||
|
||||
// Update the file cache with file info
|
||||
\OC\Files\Filesystem::putFileInfo( $filePath, array( 'encrypted' => true, 'size' => strlen( $data ), 'unencrypted_size' => $size ), '' );
|
||||
|
||||
// Re-enable proxy - our work is done
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,51 +149,46 @@ class Proxy extends \OC_FileProxy
|
|||
* @param string $path Path of file from which has been read
|
||||
* @param string $data Data that has been read from file
|
||||
*/
|
||||
public function postFile_get_contents( $path, $data ) {
|
||||
public function postFile_get_contents($path, $data) {
|
||||
|
||||
$userId = \OCP\USER::getUser();
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
$util = new Util( $view, $userId );
|
||||
$plainData = null;
|
||||
$view = new \OC_FilesystemView('/');
|
||||
|
||||
$relPath = $util->stripUserFilesPath( $path );
|
||||
|
||||
// Disable encryption proxy to prevent recursive calls
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
// get relative path
|
||||
$relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path);
|
||||
|
||||
// init session
|
||||
$session = new \OCA\Encryption\Session( $view );
|
||||
$session = new \OCA\Encryption\Session($view);
|
||||
|
||||
// If data is a catfile
|
||||
if (
|
||||
Crypt::mode() == 'server'
|
||||
&& Crypt::isCatfileContent( $data )
|
||||
Crypt::mode() === 'server'
|
||||
&& Crypt::isCatfileContent($data)
|
||||
) {
|
||||
|
||||
$privateKey = $session->getPrivateKey( $userId );
|
||||
$handle = fopen('crypt://' . $relativePath, 'r');
|
||||
|
||||
// Get the encrypted keyfile
|
||||
$encKeyfile = Keymanager::getFileKey( $view, $userId, $relPath );
|
||||
|
||||
// Attempt to fetch the user's shareKey
|
||||
$shareKey = Keymanager::getShareKey( $view, $userId, $relPath );
|
||||
|
||||
// Decrypt keyfile with shareKey
|
||||
$plainKeyfile = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey );
|
||||
|
||||
$plainData = Crypt::symmetricDecryptFileContent( $data, $plainKeyfile );
|
||||
if (is_resource($handle)) {
|
||||
while (($plainDataChunk = fgets($handle, 8192)) !== false) {
|
||||
$plainData .= $plainDataChunk;
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (
|
||||
Crypt::mode() == 'server'
|
||||
&&\OC::$session->exists('legacyenckey')
|
||||
&& Crypt::isEncryptedMeta( $path )
|
||||
&& \OC::$session->exists('legacyenckey')
|
||||
&& Crypt::isEncryptedMeta($path)
|
||||
) {
|
||||
$plainData = Crypt::legacyBlockDecrypt( $data, $session->getLegacyKey() );
|
||||
// Disable encryption proxy to prevent recursive calls
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
$plainData = Crypt::legacyBlockDecrypt($data, $session->getLegacyKey());
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
}
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
if ( !isset( $plainData ) ) {
|
||||
if (!isset($plainData)) {
|
||||
|
||||
$plainData = $data;
|
||||
|
||||
|
@ -241,10 +201,10 @@ class Proxy extends \OC_FileProxy
|
|||
/**
|
||||
* @brief When a file is deleted, remove its keyfile also
|
||||
*/
|
||||
public function preUnlink( $path ) {
|
||||
public function preUnlink($path) {
|
||||
|
||||
// let the trashbin handle this
|
||||
if ( \OCP\App::isEnabled( 'files_trashbin' ) ) {
|
||||
if (\OCP\App::isEnabled('files_trashbin')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -252,23 +212,24 @@ class Proxy extends \OC_FileProxy
|
|||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
$view = new \OC_FilesystemView('/');
|
||||
|
||||
$userId = \OCP\USER::getUser();
|
||||
|
||||
$util = new Util( $view, $userId );
|
||||
$util = new Util($view, $userId);
|
||||
|
||||
// Format path to be relative to user files dir
|
||||
$relPath = $util->stripUserFilesPath( $path );
|
||||
// get relative path
|
||||
$relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path);
|
||||
|
||||
list( $owner, $ownerPath ) = $util->getUidAndFilename( $relPath );
|
||||
list($owner, $ownerPath) = $util->getUidAndFilename($relativePath);
|
||||
|
||||
// Delete keyfile & shareKey so it isn't orphaned
|
||||
if ( !Keymanager::deleteFileKey( $view, $owner, $ownerPath ) ) {
|
||||
\OC_Log::write( 'Encryption library', 'Keyfile or shareKey could not be deleted for file "' . $ownerPath . '"', \OC_Log::ERROR );
|
||||
if (!Keymanager::deleteFileKey($view, $owner, $ownerPath)) {
|
||||
\OCP\Util::writeLog('Encryption library',
|
||||
'Keyfile or shareKey could not be deleted for file "' . $ownerPath . '"', \OCP\Util::ERROR);
|
||||
}
|
||||
|
||||
Keymanager::delAllShareKeys( $view, $owner, $ownerPath );
|
||||
Keymanager::delAllShareKeys($view, $owner, $ownerPath);
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
|
@ -282,8 +243,8 @@ class Proxy extends \OC_FileProxy
|
|||
* @param $path
|
||||
* @return bool
|
||||
*/
|
||||
public function postTouch( $path ) {
|
||||
$this->handleFile( $path );
|
||||
public function postTouch($path) {
|
||||
$this->handleFile($path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -293,20 +254,22 @@ class Proxy extends \OC_FileProxy
|
|||
* @param $result
|
||||
* @return resource
|
||||
*/
|
||||
public function postFopen( $path, &$result ) {
|
||||
public function postFopen($path, &$result) {
|
||||
|
||||
if ( !$result ) {
|
||||
if (!$result) {
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
// Reformat path for use with OC_FSV
|
||||
$path_split = explode( '/', $path );
|
||||
$path_f = implode( '/', array_slice( $path_split, 3 ) );
|
||||
// split the path parts
|
||||
$pathParts = explode('/', $path);
|
||||
|
||||
// get relative path
|
||||
$relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path);
|
||||
|
||||
// FIXME: handling for /userId/cache used by webdav for chunking. The cache chunks are NOT encrypted
|
||||
if ( count($path_split) >= 2 && $path_split[2] == 'cache' ) {
|
||||
if (isset($pathParts[2]) && $pathParts[2] === 'cache') {
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -314,31 +277,31 @@ class Proxy extends \OC_FileProxy
|
|||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
$meta = stream_get_meta_data( $result );
|
||||
$meta = stream_get_meta_data($result);
|
||||
|
||||
$view = new \OC_FilesystemView( '' );
|
||||
$view = new \OC_FilesystemView('');
|
||||
|
||||
$util = new Util( $view, \OCP\USER::getUser() );
|
||||
$util = new Util($view, \OCP\USER::getUser());
|
||||
|
||||
// If file is already encrypted, decrypt using crypto protocol
|
||||
if (
|
||||
Crypt::mode() == 'server'
|
||||
&& $util->isEncryptedPath( $path )
|
||||
Crypt::mode() === 'server'
|
||||
&& $util->isEncryptedPath($path)
|
||||
) {
|
||||
|
||||
// Close the original encrypted file
|
||||
fclose( $result );
|
||||
fclose($result);
|
||||
|
||||
// Open the file using the crypto stream wrapper
|
||||
// protocol and let it do the decryption work instead
|
||||
$result = fopen( 'crypt://' . $path_f, $meta['mode'] );
|
||||
$result = fopen('crypt://' . $relativePath, $meta['mode']);
|
||||
|
||||
} elseif (
|
||||
self::shouldEncrypt( $path )
|
||||
and $meta ['mode'] != 'r'
|
||||
and $meta['mode'] != 'rb'
|
||||
self::shouldEncrypt($path)
|
||||
and $meta ['mode'] !== 'r'
|
||||
and $meta['mode'] !== 'rb'
|
||||
) {
|
||||
$result = fopen( 'crypt://' . $path_f, $meta['mode'] );
|
||||
$result = fopen('crypt://' . $relativePath, $meta['mode']);
|
||||
}
|
||||
|
||||
// Re-enable the proxy
|
||||
|
@ -353,17 +316,17 @@ class Proxy extends \OC_FileProxy
|
|||
* @param $data
|
||||
* @return array
|
||||
*/
|
||||
public function postGetFileInfo( $path, $data ) {
|
||||
public function postGetFileInfo($path, $data) {
|
||||
|
||||
// if path is a folder do nothing
|
||||
if ( is_array( $data ) && array_key_exists( 'size', $data ) ) {
|
||||
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'] );
|
||||
$data['size'] = self::postFileSize($path, $data['size']);
|
||||
|
||||
// Re-enable the proxy
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
@ -377,51 +340,50 @@ class Proxy extends \OC_FileProxy
|
|||
* @param $size
|
||||
* @return bool
|
||||
*/
|
||||
public function postFileSize( $path, $size ) {
|
||||
public function postFileSize($path, $size) {
|
||||
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
$view = new \OC_FilesystemView('/');
|
||||
|
||||
// if path is a folder do nothing
|
||||
if ( $view->is_dir( $path ) ) {
|
||||
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 ) );
|
||||
// get relative path
|
||||
$relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path);
|
||||
|
||||
// if path is empty we cannot resolve anything
|
||||
if ( empty( $path_f ) ) {
|
||||
if (empty($relativePath)) {
|
||||
return $size;
|
||||
}
|
||||
|
||||
$fileInfo = false;
|
||||
// get file info from database/cache if not .part file
|
||||
if ( !Keymanager::isPartialFilePath( $path ) ) {
|
||||
$fileInfo = $view->getFileInfo( $path );
|
||||
if (!Keymanager::isPartialFilePath($path)) {
|
||||
$fileInfo = $view->getFileInfo($path);
|
||||
}
|
||||
|
||||
// if file is encrypted return real file size
|
||||
if ( is_array( $fileInfo ) && $fileInfo['encrypted'] === true ) {
|
||||
if (is_array($fileInfo) && $fileInfo['encrypted'] === true) {
|
||||
$size = $fileInfo['unencrypted_size'];
|
||||
} else {
|
||||
// self healing if file was removed from file cache
|
||||
if ( !is_array( $fileInfo ) ) {
|
||||
if (!is_array($fileInfo)) {
|
||||
$fileInfo = array();
|
||||
}
|
||||
|
||||
$userId = \OCP\User::getUser();
|
||||
$util = new Util( $view, $userId );
|
||||
$fixSize = $util->getFileSize( $path );
|
||||
if ( $fixSize > 0 ) {
|
||||
$util = new Util($view, $userId);
|
||||
$fixSize = $util->getFileSize($path);
|
||||
if ($fixSize > 0) {
|
||||
$size = $fixSize;
|
||||
|
||||
$fileInfo['encrypted'] = true;
|
||||
$fileInfo['unencrypted_size'] = $size;
|
||||
|
||||
// put file info if not .part file
|
||||
if ( !Keymanager::isPartialFilePath( $path_f ) ) {
|
||||
$view->putFileInfo( $path, $fileInfo );
|
||||
if (!Keymanager::isPartialFilePath($relativePath)) {
|
||||
$view->putFileInfo($path, $fileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,32 +394,34 @@ class Proxy extends \OC_FileProxy
|
|||
/**
|
||||
* @param $path
|
||||
*/
|
||||
public function handleFile( $path ) {
|
||||
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 \OCA\Encryption\Session( $view );
|
||||
$view = new \OC_FilesystemView('/');
|
||||
$session = new \OCA\Encryption\Session($view);
|
||||
$userId = \OCP\User::getUser();
|
||||
$util = new Util( $view, $userId );
|
||||
$util = new Util($view, $userId);
|
||||
|
||||
// Reformat path for use with OC_FSV
|
||||
$path_split = explode( '/', $path );
|
||||
$path_f = implode( '/', array_slice( $path_split, 3 ) );
|
||||
// split the path parts
|
||||
$pathParts = explode('/', $path);
|
||||
|
||||
// get relative path
|
||||
$relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path);
|
||||
|
||||
// only if file is on 'files' folder fix file size and sharing
|
||||
if ( count($path_split) >= 2 && $path_split[2] == 'files' && $util->fixFileSize( $path ) ) {
|
||||
if (isset($pathParts[2]) && $pathParts[2] === 'files' && $util->fixFileSize($path)) {
|
||||
|
||||
// get sharing app state
|
||||
$sharingEnabled = \OCP\Share::isEnabled();
|
||||
|
||||
// get users
|
||||
$usersSharing = $util->getSharingUsersArray( $sharingEnabled, $path_f );
|
||||
$usersSharing = $util->getSharingUsersArray($sharingEnabled, $relativePath);
|
||||
|
||||
// update sharing-keys
|
||||
$util->setSharedFileKeyfiles( $session, $usersSharing, $path_f );
|
||||
$util->setSharedFileKeyfiles($session, $usersSharing, $relativePath);
|
||||
}
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
|
|
@ -26,8 +26,7 @@ namespace OCA\Encryption;
|
|||
* Class for handling encryption related session data
|
||||
*/
|
||||
|
||||
class Session
|
||||
{
|
||||
class Session {
|
||||
|
||||
private $view;
|
||||
|
||||
|
@ -37,26 +36,26 @@ class Session
|
|||
*
|
||||
* @note The ownCloud key pair is used to allow public link sharing even if encryption is enabled
|
||||
*/
|
||||
public function __construct( $view ) {
|
||||
public function __construct($view) {
|
||||
|
||||
$this->view = $view;
|
||||
|
||||
if ( !$this->view->is_dir( 'owncloud_private_key' ) ) {
|
||||
if (!$this->view->is_dir('owncloud_private_key')) {
|
||||
|
||||
$this->view->mkdir( 'owncloud_private_key' );
|
||||
$this->view->mkdir('owncloud_private_key');
|
||||
|
||||
}
|
||||
|
||||
$publicShareKeyId = \OC_Appconfig::getValue( 'files_encryption', 'publicShareKeyId' );
|
||||
$publicShareKeyId = \OC_Appconfig::getValue('files_encryption', 'publicShareKeyId');
|
||||
|
||||
if ( $publicShareKeyId === null ) {
|
||||
$publicShareKeyId = 'pubShare_' . substr( md5( time() ), 0, 8 );
|
||||
\OC_Appconfig::setValue( 'files_encryption', 'publicShareKeyId', $publicShareKeyId );
|
||||
if ($publicShareKeyId === null) {
|
||||
$publicShareKeyId = 'pubShare_' . substr(md5(time()), 0, 8);
|
||||
\OC_Appconfig::setValue('files_encryption', 'publicShareKeyId', $publicShareKeyId);
|
||||
}
|
||||
|
||||
if (
|
||||
!$this->view->file_exists( "/public-keys/" . $publicShareKeyId . ".public.key" )
|
||||
|| !$this->view->file_exists( "/owncloud_private_key/" . $publicShareKeyId . ".private.key" )
|
||||
!$this->view->file_exists("/public-keys/" . $publicShareKeyId . ".public.key")
|
||||
|| !$this->view->file_exists("/owncloud_private_key/" . $publicShareKeyId . ".private.key")
|
||||
) {
|
||||
|
||||
$keypair = Crypt::createKeypair();
|
||||
|
@ -67,17 +66,18 @@ class Session
|
|||
|
||||
// Save public key
|
||||
|
||||
if ( !$view->is_dir( '/public-keys' ) ) {
|
||||
$view->mkdir( '/public-keys' );
|
||||
if (!$view->is_dir('/public-keys')) {
|
||||
$view->mkdir('/public-keys');
|
||||
}
|
||||
|
||||
$this->view->file_put_contents( '/public-keys/' . $publicShareKeyId . '.public.key', $keypair['publicKey'] );
|
||||
$this->view->file_put_contents('/public-keys/' . $publicShareKeyId . '.public.key', $keypair['publicKey']);
|
||||
|
||||
// Encrypt private key empty passphrase
|
||||
$encryptedPrivateKey = Crypt::symmetricEncryptFileContent( $keypair['privateKey'], '' );
|
||||
$encryptedPrivateKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], '');
|
||||
|
||||
// Save private key
|
||||
$this->view->file_put_contents( '/owncloud_private_key/' . $publicShareKeyId . '.private.key', $encryptedPrivateKey );
|
||||
$this->view->file_put_contents(
|
||||
'/owncloud_private_key/' . $publicShareKeyId . '.private.key', $encryptedPrivateKey);
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
|
@ -103,7 +103,7 @@ class Session
|
|||
*
|
||||
* @note this should only be set on login
|
||||
*/
|
||||
public function setPrivateKey( $privateKey ) {
|
||||
public function setPrivateKey($privateKey) {
|
||||
|
||||
\OC::$session->set('privateKey', $privateKey);
|
||||
|
||||
|
@ -117,7 +117,6 @@ class Session
|
|||
*
|
||||
*/
|
||||
public function getPrivateKey() {
|
||||
|
||||
// return the public share private key if this is a public access
|
||||
if (\OCA\Encryption\Helper::isPublicAccess()) {
|
||||
return $this->getPublicSharePrivateKey();
|
||||
|
@ -163,7 +162,7 @@ class Session
|
|||
* @param $legacyKey
|
||||
* @return bool
|
||||
*/
|
||||
public function setLegacyKey( $legacyKey ) {
|
||||
public function setLegacyKey($legacyKey) {
|
||||
|
||||
\OC::$session->set('legacyKey', $legacyKey);
|
||||
|
||||
|
|
|
@ -48,8 +48,7 @@ namespace OCA\Encryption;
|
|||
* previous version deleted, this is handled by OC\Files\View, and thus the
|
||||
* encryption proxies are used and keyfiles deleted.
|
||||
*/
|
||||
class Stream
|
||||
{
|
||||
class Stream {
|
||||
private $plainKey;
|
||||
private $encKeyfiles;
|
||||
|
||||
|
@ -77,18 +76,18 @@ class Stream
|
|||
* @param $opened_path
|
||||
* @return bool
|
||||
*/
|
||||
public function stream_open( $path, $mode, $options, &$opened_path ) {
|
||||
public function stream_open($path, $mode, $options, &$opened_path) {
|
||||
|
||||
if ( !isset( $this->rootView ) ) {
|
||||
$this->rootView = new \OC_FilesystemView( '/' );
|
||||
if (!isset($this->rootView)) {
|
||||
$this->rootView = new \OC_FilesystemView('/');
|
||||
}
|
||||
|
||||
$util = new Util( $this->rootView, \OCP\USER::getUser() );
|
||||
$util = new Util($this->rootView, \OCP\USER::getUser());
|
||||
|
||||
$this->userId = $util->getUserId();
|
||||
|
||||
// Strip identifier text from path, this gives us the path relative to data/<user>/files
|
||||
$this->relPath = \OC\Files\Filesystem::normalizePath( str_replace( 'crypt://', '', $path ) );
|
||||
$this->relPath = \OC\Files\Filesystem::normalizePath(str_replace('crypt://', '', $path));
|
||||
|
||||
// rawPath is relative to the data directory
|
||||
$this->rawPath = $util->getUserFilesDir() . $this->relPath;
|
||||
|
@ -98,10 +97,10 @@ class Stream
|
|||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
if (
|
||||
$mode == 'w'
|
||||
or $mode == 'w+'
|
||||
or $mode == 'wb'
|
||||
or $mode == 'wb+'
|
||||
$mode === 'w'
|
||||
or $mode === 'w+'
|
||||
or $mode === 'wb'
|
||||
or $mode === 'wb+'
|
||||
) {
|
||||
|
||||
// We're writing a new file so start write counter with 0 bytes
|
||||
|
@ -110,25 +109,25 @@ class Stream
|
|||
|
||||
} else {
|
||||
|
||||
$this->size = $this->rootView->filesize( $this->rawPath, $mode );
|
||||
$this->size = $this->rootView->filesize($this->rawPath, $mode);
|
||||
}
|
||||
|
||||
$this->handle = $this->rootView->fopen( $this->rawPath, $mode );
|
||||
$this->handle = $this->rootView->fopen($this->rawPath, $mode);
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
if ( !is_resource( $this->handle ) ) {
|
||||
if (!is_resource($this->handle)) {
|
||||
|
||||
\OCP\Util::writeLog( 'files_encryption', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR );
|
||||
\OCP\Util::writeLog('files_encryption', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR);
|
||||
|
||||
} else {
|
||||
|
||||
$this->meta = stream_get_meta_data( $this->handle );
|
||||
$this->meta = stream_get_meta_data($this->handle);
|
||||
|
||||
}
|
||||
|
||||
|
||||
return is_resource( $this->handle );
|
||||
return is_resource($this->handle);
|
||||
|
||||
}
|
||||
|
||||
|
@ -136,11 +135,11 @@ class Stream
|
|||
* @param $offset
|
||||
* @param int $whence
|
||||
*/
|
||||
public function stream_seek( $offset, $whence = SEEK_SET ) {
|
||||
public function stream_seek($offset, $whence = SEEK_SET) {
|
||||
|
||||
$this->flush();
|
||||
|
||||
fseek( $this->handle, $offset, $whence );
|
||||
fseek($this->handle, $offset, $whence);
|
||||
|
||||
}
|
||||
|
||||
|
@ -149,36 +148,37 @@ class Stream
|
|||
* @return bool|string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function stream_read( $count ) {
|
||||
public function stream_read($count) {
|
||||
|
||||
$this->writeCache = '';
|
||||
|
||||
if ( $count != 8192 ) {
|
||||
if ($count !== 8192) {
|
||||
|
||||
// $count will always be 8192 https://bugs.php.net/bug.php?id=21641
|
||||
// This makes this function a lot simpler, but will break this class if the above 'bug' gets 'fixed'
|
||||
\OCP\Util::writeLog( 'files_encryption', 'PHP "bug" 21641 no longer holds, decryption system requires refactoring', \OCP\Util::FATAL );
|
||||
\OCP\Util::writeLog('files_encryption', 'PHP "bug" 21641 no longer holds, decryption system requires refactoring', \OCP\Util::FATAL);
|
||||
|
||||
die();
|
||||
|
||||
}
|
||||
|
||||
// Get the data from the file handle
|
||||
$data = fread( $this->handle, 8192 );
|
||||
$data = fread($this->handle, 8192);
|
||||
|
||||
$result = '';
|
||||
|
||||
if ( strlen( $data ) ) {
|
||||
if (strlen($data)) {
|
||||
|
||||
if ( !$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' );
|
||||
throw new \Exception(
|
||||
'Encryption key not found for "' . $this->rawPath . '" during attempted read via stream');
|
||||
|
||||
}
|
||||
|
||||
// Decrypt data
|
||||
$result = Crypt::symmetricDecryptFileContent( $data, $this->plainKey );
|
||||
$result = Crypt::symmetricDecryptFileContent($data, $this->plainKey);
|
||||
|
||||
}
|
||||
|
||||
|
@ -192,10 +192,10 @@ class Stream
|
|||
* @param string $key key to use for encryption
|
||||
* @return string encrypted data on success, false on failure
|
||||
*/
|
||||
public function preWriteEncrypt( $plainData, $key ) {
|
||||
public function preWriteEncrypt($plainData, $key) {
|
||||
|
||||
// Encrypt data to 'catfile', which includes IV
|
||||
if ( $encrypted = Crypt::symmetricEncryptFileContent( $plainData, $key ) ) {
|
||||
if ($encrypted = Crypt::symmetricEncryptFileContent($plainData, $key)) {
|
||||
|
||||
return $encrypted;
|
||||
|
||||
|
@ -215,7 +215,7 @@ class Stream
|
|||
public function getKey() {
|
||||
|
||||
// Check if key is already set
|
||||
if ( isset( $this->plainKey ) && isset( $this->encKeyfile ) ) {
|
||||
if (isset($this->plainKey) && isset($this->encKeyfile)) {
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -223,18 +223,18 @@ class Stream
|
|||
|
||||
// Fetch and decrypt keyfile
|
||||
// Fetch existing keyfile
|
||||
$this->encKeyfile = Keymanager::getFileKey( $this->rootView, $this->userId, $this->relPath );
|
||||
$this->encKeyfile = Keymanager::getFileKey($this->rootView, $this->userId, $this->relPath);
|
||||
|
||||
// If a keyfile already exists
|
||||
if ( $this->encKeyfile ) {
|
||||
if ($this->encKeyfile) {
|
||||
|
||||
$session = new \OCA\Encryption\Session( $this->rootView );
|
||||
|
||||
$privateKey = $session->getPrivateKey( $this->userId );
|
||||
$privateKey = $session->getPrivateKey($this->userId);
|
||||
|
||||
$shareKey = Keymanager::getShareKey( $this->rootView, $this->userId, $this->relPath );
|
||||
$shareKey = Keymanager::getShareKey($this->rootView, $this->userId, $this->relPath);
|
||||
|
||||
$this->plainKey = Crypt::multiKeyDecrypt( $this->encKeyfile, $shareKey, $privateKey );
|
||||
$this->plainKey = Crypt::multiKeyDecrypt($this->encKeyfile, $shareKey, $privateKey);
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -255,7 +255,7 @@ class Stream
|
|||
* @note Padding is added to each encrypted block to ensure that the resulting block is exactly 8192 bytes. This is removed during stream_read
|
||||
* @note PHP automatically updates the file pointer after writing data to reflect it's length. There is generally no need to update the poitner manually using fseek
|
||||
*/
|
||||
public function stream_write( $data ) {
|
||||
public function stream_write($data) {
|
||||
|
||||
// Disable the file proxies so that encryption is not
|
||||
// automatically attempted when the file is written to disk -
|
||||
|
@ -265,16 +265,16 @@ class Stream
|
|||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
// Get the length of the unencrypted data that we are handling
|
||||
$length = strlen( $data );
|
||||
$length = strlen($data);
|
||||
|
||||
// Find out where we are up to in the writing of data to the
|
||||
// file
|
||||
$pointer = ftell( $this->handle );
|
||||
$pointer = ftell($this->handle);
|
||||
|
||||
// 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() ) {
|
||||
if (!$this->getKey()) {
|
||||
|
||||
$this->plainKey = Crypt::generateKey();
|
||||
|
||||
|
@ -282,7 +282,7 @@ class Stream
|
|||
|
||||
// If extra data is left over from the last round, make sure it
|
||||
// is integrated into the next 6126 / 8192 block
|
||||
if ( $this->writeCache ) {
|
||||
if ($this->writeCache) {
|
||||
|
||||
// Concat writeCache to start of $data
|
||||
$data = $this->writeCache . $data;
|
||||
|
@ -294,15 +294,15 @@ class Stream
|
|||
}
|
||||
|
||||
// While there still remains some data to be processed & written
|
||||
while ( strlen( $data ) > 0 ) {
|
||||
while (strlen($data) > 0) {
|
||||
|
||||
// Remaining length for this iteration, not of the
|
||||
// entire file (may be greater than 8192 bytes)
|
||||
$remainingLength = strlen( $data );
|
||||
$remainingLength = strlen($data);
|
||||
|
||||
// If data remaining to be written is less than the
|
||||
// size of 1 6126 byte block
|
||||
if ( $remainingLength < 6126 ) {
|
||||
if ($remainingLength < 6126) {
|
||||
|
||||
// Set writeCache to contents of $data
|
||||
// The writeCache will be carried over to the
|
||||
|
@ -320,25 +320,25 @@ class Stream
|
|||
} else {
|
||||
|
||||
// Read the chunk from the start of $data
|
||||
$chunk = substr( $data, 0, 6126 );
|
||||
$chunk = substr($data, 0, 6126);
|
||||
|
||||
$encrypted = $this->preWriteEncrypt( $chunk, $this->plainKey );
|
||||
$encrypted = $this->preWriteEncrypt($chunk, $this->plainKey);
|
||||
|
||||
// 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
|
||||
fwrite( $this->handle, $encrypted );
|
||||
fwrite($this->handle, $encrypted);
|
||||
|
||||
// Remove the chunk we just processed from
|
||||
// $data, leaving only unprocessed data in $data
|
||||
// var, for handling on the next round
|
||||
$data = substr( $data, 6126 );
|
||||
$data = substr($data, 6126);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->size = max( $this->size, $pointer + $length );
|
||||
$this->size = max($this->size, $pointer + $length);
|
||||
$this->unencryptedSize += $length;
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
@ -353,17 +353,17 @@ class Stream
|
|||
* @param $arg1
|
||||
* @param $arg2
|
||||
*/
|
||||
public function stream_set_option( $option, $arg1, $arg2 ) {
|
||||
public function stream_set_option($option, $arg1, $arg2) {
|
||||
$return = false;
|
||||
switch ( $option ) {
|
||||
switch ($option) {
|
||||
case STREAM_OPTION_BLOCKING:
|
||||
$return = stream_set_blocking( $this->handle, $arg1 );
|
||||
$return = stream_set_blocking($this->handle, $arg1);
|
||||
break;
|
||||
case STREAM_OPTION_READ_TIMEOUT:
|
||||
$return = stream_set_timeout( $this->handle, $arg1, $arg2 );
|
||||
$return = stream_set_timeout($this->handle, $arg1, $arg2);
|
||||
break;
|
||||
case STREAM_OPTION_WRITE_BUFFER:
|
||||
$return = stream_set_write_buffer( $this->handle, $arg1 );
|
||||
$return = stream_set_write_buffer($this->handle, $arg1);
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
@ -373,14 +373,14 @@ class Stream
|
|||
* @return array
|
||||
*/
|
||||
public function stream_stat() {
|
||||
return fstat( $this->handle );
|
||||
return fstat($this->handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $mode
|
||||
*/
|
||||
public function stream_lock( $mode ) {
|
||||
return flock( $this->handle, $mode );
|
||||
public function stream_lock($mode) {
|
||||
return flock($this->handle, $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -388,7 +388,7 @@ class Stream
|
|||
*/
|
||||
public function stream_flush() {
|
||||
|
||||
return fflush( $this->handle );
|
||||
return fflush($this->handle);
|
||||
// Not a typo: http://php.net/manual/en/function.fflush.php
|
||||
|
||||
}
|
||||
|
@ -397,19 +397,19 @@ class Stream
|
|||
* @return bool
|
||||
*/
|
||||
public function stream_eof() {
|
||||
return feof( $this->handle );
|
||||
return feof($this->handle);
|
||||
}
|
||||
|
||||
private function flush() {
|
||||
|
||||
if ( $this->writeCache ) {
|
||||
if ($this->writeCache) {
|
||||
|
||||
// Set keyfile property for file in question
|
||||
$this->getKey();
|
||||
|
||||
$encrypted = $this->preWriteEncrypt( $this->writeCache, $this->plainKey );
|
||||
$encrypted = $this->preWriteEncrypt($this->writeCache, $this->plainKey);
|
||||
|
||||
fwrite( $this->handle, $encrypted );
|
||||
fwrite($this->handle, $encrypted);
|
||||
|
||||
$this->writeCache = '';
|
||||
|
||||
|
@ -425,42 +425,42 @@ class Stream
|
|||
$this->flush();
|
||||
|
||||
if (
|
||||
$this->meta['mode'] != 'r'
|
||||
and $this->meta['mode'] != 'rb'
|
||||
and $this->size > 0
|
||||
$this->meta['mode'] !== 'r'
|
||||
and $this->meta['mode'] !== 'rb'
|
||||
and $this->size > 0
|
||||
) {
|
||||
// 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 );
|
||||
$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 );
|
||||
$util = new Util($this->rootView, $this->userId);
|
||||
|
||||
// Get all users sharing the file includes current user
|
||||
$uniqueUserIds = $util->getSharingUsersArray( $sharingEnabled, $this->relPath, $this->userId );
|
||||
$uniqueUserIds = $util->getSharingUsersArray($sharingEnabled, $this->relPath, $this->userId);
|
||||
|
||||
// Fetch public keys for all sharing users
|
||||
$publicKeys = Keymanager::getPublicKeys( $this->rootView, $uniqueUserIds );
|
||||
$publicKeys = Keymanager::getPublicKeys($this->rootView, $uniqueUserIds);
|
||||
|
||||
// Encrypt enc key for all sharing users
|
||||
$this->encKeyfiles = Crypt::multiKeyEncrypt( $this->plainKey, $publicKeys );
|
||||
$this->encKeyfiles = Crypt::multiKeyEncrypt($this->plainKey, $publicKeys);
|
||||
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
$view = new \OC_FilesystemView('/');
|
||||
|
||||
// Save the new encrypted file key
|
||||
Keymanager::setFileKey( $this->rootView, $this->relPath, $this->userId, $this->encKeyfiles['data'] );
|
||||
Keymanager::setFileKey($this->rootView, $this->relPath, $this->userId, $this->encKeyfiles['data']);
|
||||
|
||||
// Save the sharekeys
|
||||
Keymanager::setShareKeys( $view, $this->relPath, $this->encKeyfiles['keys'] );
|
||||
Keymanager::setShareKeys($view, $this->relPath, $this->encKeyfiles['keys']);
|
||||
|
||||
// get file info
|
||||
$fileInfo = $view->getFileInfo( $this->rawPath );
|
||||
if ( !is_array( $fileInfo ) ) {
|
||||
$fileInfo = $view->getFileInfo($this->rawPath);
|
||||
if (!is_array($fileInfo)) {
|
||||
$fileInfo = array();
|
||||
}
|
||||
|
||||
|
@ -473,10 +473,10 @@ class Stream
|
|||
$fileInfo['unencrypted_size'] = $this->unencryptedSize;
|
||||
|
||||
// set fileinfo
|
||||
$view->putFileInfo( $this->rawPath, $fileInfo );
|
||||
$view->putFileInfo($this->rawPath, $fileInfo);
|
||||
}
|
||||
|
||||
return fclose( $this->handle );
|
||||
return fclose($this->handle);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -188,7 +188,9 @@ class Util {
|
|||
|
||||
/**
|
||||
* @brief Sets up user folders and keys for serverside encryption
|
||||
* @param string $passphrase passphrase to encrypt server-stored private key with
|
||||
*
|
||||
* @param string $passphrase to encrypt server-stored private key with
|
||||
* @return bool
|
||||
*/
|
||||
public function setupServerSide($passphrase = null) {
|
||||
|
||||
|
@ -382,7 +384,7 @@ class Util {
|
|||
// we handle them
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
if ($found == false) {
|
||||
if ($found === false) {
|
||||
$found = array(
|
||||
'plain' => array(),
|
||||
'encrypted' => array(),
|
||||
|
@ -398,12 +400,12 @@ class Util {
|
|||
while (false !== ($file = readdir($handle))) {
|
||||
|
||||
if (
|
||||
$file != "."
|
||||
&& $file != ".."
|
||||
$file !== "."
|
||||
&& $file !== ".."
|
||||
) {
|
||||
|
||||
$filePath = $directory . '/' . $this->view->getRelativePath('/' . $file);
|
||||
$relPath = $this->stripUserFilesPath($filePath);
|
||||
$relPath = \OCA\Encryption\Helper::stripUserFilesPath($filePath);
|
||||
|
||||
// If the path is a directory, search
|
||||
// its contents
|
||||
|
@ -528,7 +530,7 @@ class Util {
|
|||
|
||||
/**
|
||||
* @brief Check if a given path identifies an encrypted file
|
||||
* @param $path
|
||||
* @param string $path
|
||||
* @return boolean
|
||||
*/
|
||||
public function isEncryptedPath($path) {
|
||||
|
@ -541,7 +543,7 @@ class Util {
|
|||
// we only need 24 byte from the last chunk
|
||||
$data = '';
|
||||
$handle = $this->view->fopen($path, 'r');
|
||||
if (!fseek($handle, -24, SEEK_END)) {
|
||||
if (is_resource($handle) && !fseek($handle, -24, SEEK_END)) {
|
||||
$data = fgets($handle);
|
||||
}
|
||||
|
||||
|
@ -565,11 +567,13 @@ class Util {
|
|||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
// Reformat path for use with OC_FSV
|
||||
$pathSplit = explode('/', $path);
|
||||
$pathRelative = implode('/', array_slice($pathSplit, 3));
|
||||
// split the path parts
|
||||
$pathParts = explode('/', $path);
|
||||
|
||||
if ($pathSplit[2] == 'files' && $this->view->file_exists($path) && $this->isEncryptedPath($path)) {
|
||||
// get relative path
|
||||
$relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path);
|
||||
|
||||
if (isset($pathParts[2]) && $pathParts[2] === 'files' && $this->view->file_exists($path) && $this->isEncryptedPath($path)) {
|
||||
|
||||
// get the size from filesystem
|
||||
$fullPath = $this->view->getLocalFile($path);
|
||||
|
@ -579,7 +583,7 @@ class Util {
|
|||
$lastChunkNr = floor($size / 8192);
|
||||
|
||||
// open stream
|
||||
$stream = fopen('crypt://' . $pathRelative, "r");
|
||||
$stream = fopen('crypt://' . $relativePath, "r");
|
||||
|
||||
if (is_resource($stream)) {
|
||||
// calculate last chunk position
|
||||
|
@ -639,21 +643,7 @@ class Util {
|
|||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Format a path to be relative to the /user/files/ directory
|
||||
* @note e.g. turns '/admin/files/test.txt' into 'test.txt'
|
||||
*/
|
||||
public function stripUserFilesPath($path) {
|
||||
|
||||
$trimmed = ltrim($path, '/');
|
||||
$split = explode('/', $trimmed);
|
||||
$sliced = array_slice($split, 2);
|
||||
$relPath = implode('/', $sliced);
|
||||
|
||||
return $relPath;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @return bool
|
||||
|
@ -663,7 +653,7 @@ class Util {
|
|||
$trimmed = ltrim($path, '/');
|
||||
$split = explode('/', $trimmed);
|
||||
|
||||
if ($split[2] == "Shared") {
|
||||
if (isset($split[2]) && $split[2] === 'Shared') {
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -745,10 +735,10 @@ class Util {
|
|||
$publicKeys = Keymanager::getPublicKeys($this->view, $uniqueUserIds);
|
||||
|
||||
// Recrypt data, generate catfile
|
||||
$recrypted = Crypt::legacyKeyRecryptKeyfile($legacyData, $legacyPassphrase, $publicKeys, $newPassphrase, $legacyFile['path']);
|
||||
$recrypted = Crypt::legacyKeyRecryptKeyfile( $legacyData, $legacyPassphrase, $publicKeys );
|
||||
|
||||
$rawPath = $legacyFile['path'];
|
||||
$relPath = $this->stripUserFilesPath($rawPath);
|
||||
$relPath = \OCA\Encryption\Helper::stripUserFilesPath($rawPath);
|
||||
|
||||
// Save keyfile
|
||||
Keymanager::setFileKey($this->view, $relPath, $this->userId, $recrypted['filekey']);
|
||||
|
@ -869,8 +859,8 @@ class Util {
|
|||
// Check that the user is encryption capable, or is the
|
||||
// public system user 'ownCloud' (for public shares)
|
||||
if (
|
||||
$user == $this->publicShareKeyId
|
||||
or $user == $this->recoveryKeyId
|
||||
$user === $this->publicShareKeyId
|
||||
or $user === $this->recoveryKeyId
|
||||
or $util->ready()
|
||||
) {
|
||||
|
||||
|
@ -903,6 +893,7 @@ class Util {
|
|||
* @param string $filePath
|
||||
* @param string $fileOwner
|
||||
* @param string $privateKey
|
||||
* @return bool|string
|
||||
* @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,
|
||||
|
@ -918,7 +909,7 @@ class Util {
|
|||
// We need to decrypt the keyfile
|
||||
// Has the file been shared yet?
|
||||
if (
|
||||
$this->userId == $fileOwner
|
||||
$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
|
||||
) {
|
||||
|
||||
|
@ -1028,7 +1019,7 @@ class Util {
|
|||
if ($sharingEnabled) {
|
||||
|
||||
// Find out who, if anyone, is sharing the file
|
||||
$result = \OCP\Share::getUsersSharingFile($ownerPath, $owner, true, true, true);
|
||||
$result = \OCP\Share::getUsersSharingFile($ownerPath, $owner, true);
|
||||
$userIds = $result['users'];
|
||||
if ($result['public']) {
|
||||
$userIds[] = $this->publicShareKeyId;
|
||||
|
@ -1049,7 +1040,7 @@ class Util {
|
|||
}
|
||||
|
||||
// add current user if given
|
||||
if ($currentUserId != false) {
|
||||
if ($currentUserId !== false) {
|
||||
|
||||
$userIds[] = $currentUserId;
|
||||
|
||||
|
@ -1136,6 +1127,7 @@ class Util {
|
|||
/**
|
||||
* @brief get uid of the owners of the file and the path to the file
|
||||
* @param string $path Path of the file to check
|
||||
* @throws \Exception
|
||||
* @note $shareFilePath must be relative to data/UID/files. Files
|
||||
* relative to /Shared are also acceptable
|
||||
* @return array
|
||||
|
@ -1166,7 +1158,7 @@ class Util {
|
|||
\OC\Files\Filesystem::initMountPoints($fileOwnerUid);
|
||||
|
||||
// If the file owner is the currently logged in user
|
||||
if ($fileOwnerUid == $this->userId) {
|
||||
if ($fileOwnerUid === $this->userId) {
|
||||
|
||||
// Assume the path supplied is correct
|
||||
$filename = $path;
|
||||
|
@ -1199,14 +1191,14 @@ class Util {
|
|||
|
||||
$result = array();
|
||||
|
||||
$content = $this->view->getDirectoryContent($this->userFilesDir . $dir);
|
||||
$content = $this->view->getDirectoryContent(\OC\Files\Filesystem::normalizePath($this->userFilesDir . '/' . $dir));
|
||||
|
||||
// handling for re shared folders
|
||||
$path_split = explode('/', $dir);
|
||||
$pathSplit = explode('/', $dir);
|
||||
|
||||
foreach ($content as $c) {
|
||||
|
||||
$sharedPart = $path_split[sizeof($path_split) - 1];
|
||||
$sharedPart = $pathSplit[sizeof($pathSplit) - 1];
|
||||
$targetPathSplit = array_reverse(explode('/', $c['path']));
|
||||
|
||||
$path = '';
|
||||
|
@ -1228,7 +1220,7 @@ class Util {
|
|||
|
||||
$path = $dir . $path;
|
||||
|
||||
if ($c['type'] === "dir") {
|
||||
if ($c['type'] === 'dir') {
|
||||
|
||||
$result = array_merge($result, $this->getAllFiles($path));
|
||||
|
||||
|
@ -1417,11 +1409,12 @@ class Util {
|
|||
foreach ($dirContent as $item) {
|
||||
// get relative path from files_encryption/keyfiles/
|
||||
$filePath = substr($item['path'], strlen('files_encryption/keyfiles'));
|
||||
if ($item['type'] == 'dir') {
|
||||
if ($item['type'] === 'dir') {
|
||||
$this->addRecoveryKeys($filePath . '/');
|
||||
} else {
|
||||
$session = new \OCA\Encryption\Session(new \OC_FilesystemView('/'));
|
||||
$sharingEnabled = \OCP\Share::isEnabled();
|
||||
// remove '.key' extension from path e.g. 'file.txt.key' to 'file.txt'
|
||||
$file = substr($filePath, 0, -4);
|
||||
$usersSharing = $this->getSharingUsersArray($sharingEnabled, $file);
|
||||
$this->setSharedFileKeyfiles($session, $usersSharing, $file);
|
||||
|
@ -1437,9 +1430,10 @@ class Util {
|
|||
foreach ($dirContent as $item) {
|
||||
// get relative path from files_encryption/keyfiles
|
||||
$filePath = substr($item['path'], strlen('files_encryption/keyfiles'));
|
||||
if ($item['type'] == 'dir') {
|
||||
if ($item['type'] === 'dir') {
|
||||
$this->removeRecoveryKeys($filePath . '/');
|
||||
} else {
|
||||
// remove '.key' extension from path e.g. 'file.txt.key' to 'file.txt'
|
||||
$file = substr($filePath, 0, -4);
|
||||
$this->view->unlink($this->shareKeysPath . '/' . $file . '.' . $this->recoveryKeyId . '.shareKey');
|
||||
}
|
||||
|
@ -1457,7 +1451,7 @@ class Util {
|
|||
|
||||
// Find out who, if anyone, is sharing the file
|
||||
if ($sharingEnabled) {
|
||||
$result = \OCP\Share::getUsersSharingFile($file, $this->userId, true, true, true);
|
||||
$result = \OCP\Share::getUsersSharingFile($file, $this->userId, true);
|
||||
$userIds = $result['users'];
|
||||
$userIds[] = $this->recoveryKeyId;
|
||||
if ($result['public']) {
|
||||
|
@ -1502,10 +1496,12 @@ class Util {
|
|||
private function recoverAllFiles($path, $privateKey) {
|
||||
$dirContent = $this->view->getDirectoryContent($this->keyfilesPath . $path);
|
||||
foreach ($dirContent as $item) {
|
||||
$filePath = substr($item['path'], 25);
|
||||
if ($item['type'] == 'dir') {
|
||||
// get relative path from files_encryption/keyfiles
|
||||
$filePath = substr($item['path'], strlen('files_encryption/keyfiles'));
|
||||
if ($item['type'] === 'dir') {
|
||||
$this->recoverAllFiles($filePath . '/', $privateKey);
|
||||
} else {
|
||||
// remove '.key' extension from path e.g. 'file.txt.key' to 'file.txt'
|
||||
$file = substr($filePath, 0, -4);
|
||||
$this->recoverFile($file, $privateKey);
|
||||
}
|
||||
|
@ -1531,4 +1527,21 @@ class Util {
|
|||
$this->recoverAllFiles('/', $privateKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path including the storage mount point
|
||||
* @param int $id
|
||||
* @return string the path including the mount point like AmazonS3/folder/file.txt
|
||||
*/
|
||||
public function getPathWithMountPoint($id) {
|
||||
list($storage, $internalPath) = \OC\Files\Cache\Cache::getById($id);
|
||||
$mount = \OC\Files\Filesystem::getMountByStorageId($storage);
|
||||
$mountPoint = $mount[0]->getMountPoint();
|
||||
$path = \OC\Files\Filesystem::normalizePath($mountPoint.'/'.$internalPath);
|
||||
|
||||
// reformat the path to be relative e.g. /user/files/folder becomes /folder/
|
||||
$relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path);
|
||||
|
||||
return $relativePath;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,16 +8,16 @@
|
|||
|
||||
\OC_Util::checkAdminUser();
|
||||
|
||||
$tmpl = new OCP\Template( 'files_encryption', 'settings-admin' );
|
||||
$tmpl = new OCP\Template('files_encryption', 'settings-admin');
|
||||
|
||||
// Check if an adminRecovery account is enabled for recovering files after lost pwd
|
||||
$view = new OC_FilesystemView( '' );
|
||||
$view = new OC_FilesystemView('');
|
||||
|
||||
$recoveryAdminEnabled = OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminEnabled' );
|
||||
$recoveryAdminEnabled = OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled');
|
||||
|
||||
$tmpl->assign( 'recoveryEnabled', $recoveryAdminEnabled );
|
||||
$tmpl->assign('recoveryEnabled', $recoveryAdminEnabled);
|
||||
|
||||
\OCP\Util::addscript( 'files_encryption', 'settings-admin' );
|
||||
\OCP\Util::addscript( 'core', 'multiselect' );
|
||||
\OCP\Util::addscript('files_encryption', 'settings-admin');
|
||||
\OCP\Util::addscript('core', 'multiselect');
|
||||
|
||||
return $tmpl->fetchPage();
|
||||
|
|
|
@ -7,22 +7,22 @@
|
|||
*/
|
||||
|
||||
// Add CSS stylesheet
|
||||
\OC_Util::addStyle( 'files_encryption', 'settings-personal' );
|
||||
|
||||
$tmpl = new OCP\Template( 'files_encryption', 'settings-personal');
|
||||
\OC_Util::addStyle('files_encryption', 'settings-personal');
|
||||
|
||||
$tmpl = new OCP\Template('files_encryption', 'settings-personal');
|
||||
|
||||
$user = \OCP\USER::getUser();
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
$util = new \OCA\Encryption\Util( $view, $user );
|
||||
$view = new \OC_FilesystemView('/');
|
||||
$util = new \OCA\Encryption\Util($view, $user);
|
||||
|
||||
$recoveryAdminEnabled = OC_Appconfig::getValue( 'files_encryption', 'recoveryAdminEnabled' );
|
||||
$recoveryAdminEnabled = OC_Appconfig::getValue('files_encryption', 'recoveryAdminEnabled');
|
||||
$recoveryEnabledForUser = $util->recoveryEnabledForUser();
|
||||
|
||||
\OCP\Util::addscript( 'files_encryption', 'settings-personal' );
|
||||
\OCP\Util::addScript( 'settings', 'personal' );
|
||||
\OCP\Util::addscript('files_encryption', 'settings-personal');
|
||||
\OCP\Util::addScript('settings', 'personal');
|
||||
|
||||
$tmpl->assign( 'recoveryEnabled', $recoveryAdminEnabled );
|
||||
$tmpl->assign( 'recoveryEnabledForUser', $recoveryEnabledForUser );
|
||||
$tmpl->assign('recoveryEnabled', $recoveryAdminEnabled);
|
||||
$tmpl->assign('recoveryEnabledForUser', $recoveryEnabledForUser);
|
||||
|
||||
return $tmpl->fetchPage();
|
||||
|
||||
|
|
|
@ -575,7 +575,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase {
|
|||
*/
|
||||
function testLegacyKeyRecryptKeyfileEncrypt($crypted) {
|
||||
|
||||
$recrypted = Encryption\Crypt::LegacyKeyRecryptKeyfile($crypted, $this->pass, array($this->genPublicKey), $this->pass, '');
|
||||
$recrypted = Encryption\Crypt::LegacyKeyRecryptKeyfile($crypted, $this->pass, array($this->genPublicKey));
|
||||
|
||||
$this->assertNotEquals($this->dataLong, $recrypted['data']);
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
|
|||
|
||||
$_SERVER['REQUEST_METHOD'] = 'PUT';
|
||||
$_SERVER['REQUEST_URI'] = '/remote.php/webdav' . $filename;
|
||||
$_SERVER['HTTP_AUTHORIZATION'] = 'Basic YWRtaW46YWRtaW4=';
|
||||
$_SERVER['HTTP_AUTHORIZATION'] = 'Basic dGVzdC13ZWJkYXYtdXNlcjE6dGVzdC13ZWJkYXYtdXNlcjE=';
|
||||
$_SERVER['CONTENT_TYPE'] = 'application/octet-stream';
|
||||
$_SERVER['PATH_INFO'] = '/webdav' . $filename;
|
||||
$_SERVER['CONTENT_LENGTH'] = strlen($this->dataShort);
|
||||
|
@ -172,7 +172,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
|
|||
// set server vars
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
$_SERVER['REQUEST_URI'] = '/remote.php/webdav' . $filename;
|
||||
$_SERVER['HTTP_AUTHORIZATION'] = 'Basic YWRtaW46YWRtaW4=';
|
||||
$_SERVER['HTTP_AUTHORIZATION'] = 'Basic dGVzdC13ZWJkYXYtdXNlcjE6dGVzdC13ZWJkYXYtdXNlcjE=';
|
||||
$_SERVER['PATH_INFO'] = '/webdav' . $filename;
|
||||
|
||||
// handle webdav request
|
||||
|
@ -193,7 +193,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
|
|||
// set server vars
|
||||
$_SERVER['REQUEST_METHOD'] = 'DELETE';
|
||||
$_SERVER['REQUEST_URI'] = '/remote.php/webdav' . $filename;
|
||||
$_SERVER['HTTP_AUTHORIZATION'] = 'Basic YWRtaW46YWRtaW4=';
|
||||
$_SERVER['HTTP_AUTHORIZATION'] = 'Basic dGVzdC13ZWJkYXYtdXNlcjE6dGVzdC13ZWJkYXYtdXNlcjE=';
|
||||
$_SERVER['PATH_INFO'] = '/webdav' . $filename;
|
||||
|
||||
// handle webdav request
|
||||
|
@ -216,7 +216,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase {
|
|||
*
|
||||
* @param bool $body
|
||||
*
|
||||
* @note this init procedure is copied from /apps/files/remote.php
|
||||
* @note this init procedure is copied from /apps/files/appinfo/remote.php
|
||||
*/
|
||||
function handleWebdavRequest($body = false) {
|
||||
// Backends
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"Error configuring Google Drive storage" => "Klaida nustatinėjant Google Drive talpyklą",
|
||||
"<b>Warning:</b> \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "<b>Įspėjimas:</b> \"smbclient\" nėra įdiegtas. CIFS/SMB dalinimasis nėra galimas. Prašome susisiekti su sistemos administratoriumi kad būtų įdiegtas \"smbclient\"",
|
||||
"<b>Warning:</b> 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." => "<b>Įspėjimas:</b> FTP palaikymas PHP sistemoje nėra įjungtas arba nėra įdiegtas. FTP dalinimosi įjungimas nėra galimas. Prašome susisiekti su sistemos administratoriumi kad būtų įdiegtas FTP palaikymas. ",
|
||||
"<b>Warning:</b> 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." => "<b>Įspėjimas:</b> \"Curl\" palaikymas PHP terpėje nėra įjungtas arba įdiegtas. ownCloud/WebDAV ar GoogleDrive įjungimas nebus įmanomas. Prašome susisiekti su sistemos administratoriumi kad būtų įdiegtas arba įjungtas \"Curl\" palaikymas.",
|
||||
"External Storage" => "Išorinės saugyklos",
|
||||
"Folder name" => "Katalogo pavadinimas",
|
||||
"External storage" => "Išorinė saugykla",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Configuration" => "Innstillingar",
|
||||
"Groups" => "Grupper",
|
||||
"Users" => "Brukarar",
|
||||
"Delete" => "Slett"
|
||||
|
|
|
@ -70,6 +70,28 @@ class Shared_Permissions extends Permissions {
|
|||
return $filePermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the permissions for all files in a folder
|
||||
*
|
||||
* @param int $parentId
|
||||
* @param string $user
|
||||
* @return int[]
|
||||
*/
|
||||
public function getDirectoryPermissions($parentId, $user) {
|
||||
// Root of the Shared folder
|
||||
if ($parentId === -1) {
|
||||
return \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_PERMISSIONS);
|
||||
}
|
||||
$permissions = $this->get($parentId, $user);
|
||||
$query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `parent` = ?');
|
||||
$result = $query->execute(array($parentId));
|
||||
$filePermissions = array();
|
||||
while ($row = $result->fetchRow()) {
|
||||
$filePermissions[$row['fileid']] = $permissions;
|
||||
}
|
||||
return $filePermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove the permissions for a file
|
||||
*
|
||||
|
@ -83,4 +105,5 @@ class Shared_Permissions extends Permissions {
|
|||
public function removeMultiple($fileIds, $user) {
|
||||
// Not a valid action for Shared Permissions
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -26,6 +26,7 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent {
|
|||
const FORMAT_FILE_APP_ROOT = 2;
|
||||
const FORMAT_OPENDIR = 3;
|
||||
const FORMAT_GET_ALL = 4;
|
||||
const FORMAT_PERMISSIONS = 5;
|
||||
|
||||
private $path;
|
||||
|
||||
|
@ -125,6 +126,12 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent {
|
|||
$ids[] = $item['file_source'];
|
||||
}
|
||||
return $ids;
|
||||
} else if ($format === self::FORMAT_PERMISSIONS) {
|
||||
$filePermissions = array();
|
||||
foreach ($items as $item) {
|
||||
$filePermissions[$item['file_source']] = $item['permissions'];
|
||||
}
|
||||
return $filePermissions;
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
|
|
@ -113,8 +113,16 @@ class Storage {
|
|||
mkdir($versionsFolderName.'/'.$info['dirname'], 0750, true);
|
||||
}
|
||||
|
||||
// disable proxy to prevent multiple fopen calls
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
// store a new version of a file
|
||||
$users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename));
|
||||
|
||||
// reset proxy state
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
$versionsSize = self::getVersionsSize($uid);
|
||||
if ( $versionsSize === false || $versionsSize < 0 ) {
|
||||
$versionsSize = self::calculateSize($uid);
|
||||
|
@ -195,7 +203,16 @@ class Storage {
|
|||
//first create a new version
|
||||
$version = 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename);
|
||||
if ( !$users_view->file_exists($version)) {
|
||||
|
||||
// disable proxy to prevent multiple fopen calls
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
$users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename));
|
||||
|
||||
// reset proxy state
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
$versionCreated = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,8 @@
|
|||
"Override UUID detection" => "Zastąp wykrywanie UUID",
|
||||
"UUID Attribute:" => "Atrybuty UUID:",
|
||||
"Username-LDAP User Mapping" => "Mapowanie użytkownika LDAP",
|
||||
"Clear Username-LDAP User Mapping" => "Czyść Mapowanie użytkownika LDAP",
|
||||
"Clear Groupname-LDAP Group Mapping" => "Czyść Mapowanie nazwy grupy LDAP",
|
||||
"Test Configuration" => "Konfiguracja testowa",
|
||||
"Help" => "Pomoc"
|
||||
);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"Failed to clear the mappings." => "Nepodarilo sa vymazať mapovania.",
|
||||
"Failed to delete the server configuration" => "Zlyhalo zmazanie nastavenia servera.",
|
||||
"The configuration is valid and the connection could be established!" => "Nastavenie je v poriadku a pripojenie je stabilné.",
|
||||
"The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "Nastavenie je v poriadku, ale pripojenie zlyhalo. Skontrolujte nastavenia servera a prihlasovacie údaje.",
|
||||
|
@ -7,6 +8,7 @@
|
|||
"Take over settings from recent server configuration?" => "Prebrať nastavenia z nedávneho nastavenia servera?",
|
||||
"Keep settings?" => "Ponechať nastavenia?",
|
||||
"Cannot add server configuration" => "Nemožno pridať nastavenie servera",
|
||||
"mappings cleared" => "mapovanie vymazané",
|
||||
"Success" => "Úspešné",
|
||||
"Error" => "Chyba",
|
||||
"Connection test succeeded" => "Test pripojenia bol úspešný",
|
||||
|
@ -72,6 +74,11 @@
|
|||
"Email Field" => "Pole email",
|
||||
"User Home Folder Naming Rule" => "Pravidlo pre nastavenie mena používateľského priečinka dát",
|
||||
"Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "Nechajte prázdne pre používateľské meno (predvolené). Inak uveďte atribút LDAP/AD.",
|
||||
"Internal Username" => "Interné používateľské meno",
|
||||
"By default the internal username will be created from the UUID attribute. It makes sure that the username is unique and characters do not need to be converted. The internal username has the restriction that only these characters are allowed: [ a-zA-Z0-9_.@- ]. Other characters are replaced with their ASCII correspondence or simply omitted. On collisions a number will be added/increased. The internal username is used to identify a user internally. It is also the default name for the user home folder in ownCloud. It is also a port of remote URLs, for instance for all *DAV services. With this setting, the default behaviour can be overriden. To achieve a similar behaviour as before ownCloud 5 enter the user display name attribute in the following field. Leave it empty for default behaviour. Changes will have effect only on newly mapped (added) LDAP users." => "V predvolenom nastavení bude interné používateľské meno vytvorené z UUID atribútu. Zabezpečí sa to, že používateľské meno bude jedinečné a znaky nemusia byť prevedené. Interné meno má obmedzenie, iba tieto znaky sú povolené: [a-zA-Z0-9_ @ -.]. Ostatné znaky sú nahradené ich ASCII alebo jednoducho vynechané. Pri kolíziách bude číslo byť pridané / odobrané. Interné používateľské meno sa používa na identifikáciu používateľa interne. Je to tiež predvolený názov používateľského domovského priečinka v ownCloud. To je tiež port vzdialeného URL, napríklad pre všetky služby * DAV. S týmto nastavením sa dá prepísať predvolené správanie. Pre dosiahnutie podobného správania sa ako pred ownCloud 5 zadajte atribút zobrazenia používateľského mena v tomto poli. Ponechajte prázdne pre predvolené správanie. Zmeny budú mať vplyv iba na novo mapovaných (pridaných) LDAP používateľov.",
|
||||
"Internal Username Attribute:" => "Atribút interného používateľského mena:",
|
||||
"Override UUID detection" => "Prepísať UUID detekciu",
|
||||
"UUID Attribute:" => "UUID atribút:",
|
||||
"Test Configuration" => "Test nastavenia",
|
||||
"Help" => "Pomoc"
|
||||
);
|
||||
|
|
|
@ -441,8 +441,8 @@ abstract class Access {
|
|||
//while loop is just a precaution. If a name is not generated within
|
||||
//20 attempts, something else is very wrong. Avoids infinite loop.
|
||||
while($attempts < 20){
|
||||
$altName = $name . '_' . uniqid();
|
||||
if(\OCP\User::userExists($altName)) {
|
||||
$altName = $name . '_' . rand(1000,9999);
|
||||
if(!\OCP\User::userExists($altName)) {
|
||||
return $altName;
|
||||
}
|
||||
$attempts++;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"WebDAV Authentication" => "WebDAV-autentisering",
|
||||
"URL: http://" => "Nettadresse: http://",
|
||||
"ownCloud will send the user credentials to this URL. This plugin checks the response and will interpret the HTTP statuscodes 401 and 403 as invalid credentials, and all other responses as valid credentials." => "ownCloud sender brukarakkreditiv til denne nettadressa. Dette programtillegget kontrollerer svaret og tolkar HTTP-statuskodane 401 og 403 som ugyldige, og alle andre svar som gyldige."
|
||||
);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -67,8 +67,8 @@
|
|||
"Password" => "Contrasenya",
|
||||
"Email link to person" => "Enllaç per correu electrónic amb la persona",
|
||||
"Send" => "Envia",
|
||||
"Set expiration date" => "Estableix la data d'expiració",
|
||||
"Expiration date" => "Data d'expiració",
|
||||
"Set expiration date" => "Estableix la data de venciment",
|
||||
"Expiration date" => "Data de venciment",
|
||||
"Share via email:" => "Comparteix per correu electrònic",
|
||||
"No people found" => "No s'ha trobat ningú",
|
||||
"Resharing is not allowed" => "No es permet compartir de nou",
|
||||
|
@ -81,8 +81,8 @@
|
|||
"delete" => "elimina",
|
||||
"share" => "comparteix",
|
||||
"Password protected" => "Protegeix amb contrasenya",
|
||||
"Error unsetting expiration date" => "Error en eliminar la data d'expiració",
|
||||
"Error setting expiration date" => "Error en establir la data d'expiració",
|
||||
"Error unsetting expiration date" => "Error en eliminar la data de venciment",
|
||||
"Error setting expiration date" => "Error en establir la data de venciment",
|
||||
"Sending ..." => "Enviant...",
|
||||
"Email sent" => "El correu electrónic s'ha enviat",
|
||||
"The update was unsuccessful. Please report this issue to the <a href=\"https://github.com/owncloud/core/issues\" target=\"_blank\">ownCloud community</a>." => "L'actualització ha estat incorrecte. Comuniqueu aquest error a <a href=\"https://github.com/owncloud/core/issues\" target=\"_blank\">la comunitat ownCloud</a>.",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php $TRANSLATIONS = array(
|
||||
"User %s shared a file with you" => "Kasutaja %s jagas Sinuga faili",
|
||||
"User %s shared a file with you" => "Kasutaja %s jagas sinuga faili",
|
||||
"User %s shared a folder with you" => "Kasutaja %s jagas Sinuga kausta.",
|
||||
"User %s shared the file \"%s\" with you. It is available for download here: %s" => "Kasutaja %s jagas Sinuga faili \"%s\". See on allalaadimiseks saadaval siin: %s",
|
||||
"User %s shared the folder \"%s\" with you. It is available for download here: %s" => "Kasutaja %s jagas Sinuga kataloogi \"%s\". See on allalaadimiseks saadaval siin: %s",
|
||||
"User %s shared the file \"%s\" with you. It is available for download here: %s" => "Kasutaja %s jagas sinuga faili \"%s\". See on allalaadimiseks saadaval siin: %s",
|
||||
"User %s shared the folder \"%s\" with you. It is available for download here: %s" => "Kasutaja %s jagas sinuga kausta \"%s\". See on allalaadimiseks saadaval siin: %s",
|
||||
"Category type not provided." => "Kategooria tüüp puudub.",
|
||||
"No category to add?" => "Pole kategooriat, mida lisada?",
|
||||
"This category already exists: %s" => "See kategooria on juba olemas: %s",
|
||||
|
@ -10,7 +10,7 @@
|
|||
"%s ID not provided." => "%s ID puudub.",
|
||||
"Error adding %s to favorites." => "Viga %s lisamisel lemmikutesse.",
|
||||
"No categories selected for deletion." => "Kustutamiseks pole kategooriat valitud.",
|
||||
"Error removing %s from favorites." => "Viga %s eemaldamisel lemmikutest",
|
||||
"Error removing %s from favorites." => "Viga %s eemaldamisel lemmikutest.",
|
||||
"Sunday" => "Pühapäev",
|
||||
"Monday" => "Esmaspäev",
|
||||
"Tuesday" => "Teisipäev",
|
||||
|
@ -52,7 +52,7 @@
|
|||
"Ok" => "Ok",
|
||||
"The object type is not specified." => "Objekti tüüp pole määratletud.",
|
||||
"Error" => "Viga",
|
||||
"The app name is not specified." => "Rakenduse nimi ole määratletud",
|
||||
"The app name is not specified." => "Rakenduse nimi ole määratletud.",
|
||||
"The required file {file} is not installed!" => "Vajalikku faili {file} pole paigaldatud!",
|
||||
"Shared" => "Jagatud",
|
||||
"Share" => "Jaga",
|
||||
|
@ -83,13 +83,13 @@
|
|||
"Password protected" => "Parooliga kaitstud",
|
||||
"Error unsetting expiration date" => "Viga aegumise kuupäeva eemaldamisel",
|
||||
"Error setting expiration date" => "Viga aegumise kuupäeva määramisel",
|
||||
"Sending ..." => "Saadan ...",
|
||||
"Email sent" => "Email saadetud",
|
||||
"Sending ..." => "Saatmine ...",
|
||||
"Email sent" => "E-kiri on saadetud",
|
||||
"The update was unsuccessful. Please report this issue to the <a href=\"https://github.com/owncloud/core/issues\" target=\"_blank\">ownCloud community</a>." => "Uuendus ebaõnnestus. Palun teavita probleemidest <a href=\"https://github.com/owncloud/core/issues\" target=\"_blank\">ownCloud kogukonda</a>.",
|
||||
"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}",
|
||||
"The link to reset your password has been sent to your email.<br>If you do not receive it within a reasonable amount of time, check your spam/junk folders.<br>If it is not there ask your local administrator ." => "Link parooli vahetuseks on saadetud Sinu e-posti aadressil.<br>Kui kiri pole saabunud mõistliku aja jooksul, siis kontrolli oma spam-/rämpskirjade katalooge.<br>Kui kirja pole ka seal, siis küsi abi süsteemihaldurilt.",
|
||||
"The link to reset your password has been sent to your email.<br>If you do not receive it within a reasonable amount of time, check your spam/junk folders.<br>If it is not there ask your local administrator ." => "Link parooli vahetuseks on saadetud Sinu e-posti aadressile.<br>Kui kiri pole saabunud mõistliku aja jooksul, siis kontrolli oma spam-/rämpskirjade katalooge.<br>Kui kirja pole ka seal, siis küsi abi süsteemihaldurilt.",
|
||||
"Request failed!<br>Did you make sure your email/username was right?" => "Päring ebaõnnestus!<br>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.",
|
||||
"Username" => "Kasutajanimi",
|
||||
|
@ -113,7 +113,7 @@
|
|||
"No secure random number generator is available, please enable the PHP OpenSSL extension." => "Turvalist juhuslike numbrite generaatorit pole saadaval. Palun luba PHP-s OpenSSL laiendus.",
|
||||
"Without a secure random number generator an attacker may be able to predict password reset tokens and take over your account." => "Ilma turvalise juhuslike numbrite generaatorita võib ründaja ennustada paroolivahetuse võtme ning hõivata su konto.",
|
||||
"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 <a href=\"http://doc.owncloud.org/server/5.0/admin_manual/installation.html\" target=\"_blank\">documentation</a>." => "Serveri korrektseks seadistuseks palun tutvu <a href=\"http://doc.owncloud.org/server/5.0/admin_manual/installation.html\" target=\"_blank\">dokumentatsiooniga</a>.",
|
||||
"For information how to properly configure your server, please see the <a href=\"http://doc.owncloud.org/server/5.0/admin_manual/installation.html\" target=\"_blank\">documentation</a>." => "Serveri korrektseks seadistuseks tutvu palun <a href=\"http://doc.owncloud.org/server/5.0/admin_manual/installation.html\" target=\"_blank\">dokumentatsiooniga</a>.",
|
||||
"Create an <strong>admin account</strong>" => "Loo <strong>admini konto</strong>",
|
||||
"Advanced" => "Täpsem",
|
||||
"Data folder" => "Andmete kaust",
|
||||
|
@ -125,17 +125,17 @@
|
|||
"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",
|
||||
"%s is available. Get more information on how to update." => "%s on saadaval. Vaata lähemalt kuidas uuendada.",
|
||||
"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!",
|
||||
"If you did not change your password recently, your account may be compromised!" => "Kui sa ei muutnud oma parooli hiljuti, siis võib su kasutajakonto olla ohustatud!",
|
||||
"Please change your password to secure your account again." => "Palun muuda parooli, et oma kasutajakonto uuesti turvata.",
|
||||
"Lost your password?" => "Kaotasid oma parooli?",
|
||||
"remember" => "pea meeles",
|
||||
"Log in" => "Logi sisse",
|
||||
"Alternative Logins" => "Alternatiivsed meldimised",
|
||||
"Alternative Logins" => "Alternatiivsed sisselogimisviisid",
|
||||
"prev" => "eelm",
|
||||
"next" => "järgm",
|
||||
"Updating ownCloud to version %s, this may take a while." => "Uuendan ownCloudi versioonile %s. Läheb pisut aega."
|
||||
"Updating ownCloud to version %s, this may take a while." => "ownCloudi uuendamine versioonile %s. See võib veidi aega võtta."
|
||||
);
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
"years ago" => "anos atrás",
|
||||
"Choose" => "Escolha",
|
||||
"Cancel" => "Cancelar",
|
||||
"Error loading file picker template" => "Erro ao carregar arquivo do separador modelo",
|
||||
"Yes" => "Sim",
|
||||
"No" => "Não",
|
||||
"Ok" => "Ok",
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
"years ago" => "несколько лет назад",
|
||||
"Choose" => "Выбрать",
|
||||
"Cancel" => "Отменить",
|
||||
"Error loading file picker template" => "Ошибка при загрузке файла выбора шаблона",
|
||||
"Yes" => "Да",
|
||||
"No" => "Нет",
|
||||
"Ok" => "Ок",
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-27 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-26 00:02+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 00:42+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Afrikaans (South Africa) (http://www.transifex.com/projects/p/owncloud/language/af_ZA/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -564,12 +564,12 @@ msgstr "Maak opstelling klaar"
|
|||
msgid "web services under your control"
|
||||
msgstr "webdienste onder jou beheer"
|
||||
|
||||
#: templates/layout.user.php:36
|
||||
#: templates/layout.user.php:37
|
||||
#, php-format
|
||||
msgid "%s is available. Get more information on how to update."
|
||||
msgstr ""
|
||||
|
||||
#: templates/layout.user.php:61
|
||||
#: templates/layout.user.php:62
|
||||
msgid "Log out"
|
||||
msgstr "Teken uit"
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-25 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-25 00:02+0000\n"
|
||||
"POT-Creation-Date: 2013-05-30 02:27+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 00:27+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Afrikaans (South Africa) (http://www.transifex.com/projects/p/owncloud/language/af_ZA/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -17,12 +17,22 @@ msgstr ""
|
|||
"Language: af_ZA\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ajax/adminrecovery.php:40
|
||||
msgid "Recovery key successfully "
|
||||
#: ajax/adminrecovery.php:29
|
||||
msgid "Recovery key successfully enabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:42
|
||||
msgid "Could not "
|
||||
#: ajax/adminrecovery.php:34
|
||||
msgid ""
|
||||
"Could not enable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:48
|
||||
msgid "Recovery key successfully disabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:53
|
||||
msgid ""
|
||||
"Could not disable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/changeRecoveryPassword.php:49
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-28 00:02+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:59+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 00:42+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Afrikaans (South Africa) (http://www.transifex.com/projects/p/owncloud/language/af_ZA/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -57,7 +57,7 @@ msgstr ""
|
|||
msgid "Selected files too large to generate zip file."
|
||||
msgstr ""
|
||||
|
||||
#: helper.php:228
|
||||
#: helper.php:236
|
||||
msgid "couldn't be determined"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -564,12 +564,12 @@ msgstr "انهاء التعديلات"
|
|||
msgid "web services under your control"
|
||||
msgstr "خدمات الشبكة تحت سيطرتك"
|
||||
|
||||
#: templates/layout.user.php:36
|
||||
#: templates/layout.user.php:37
|
||||
#, php-format
|
||||
msgid "%s is available. Get more information on how to update."
|
||||
msgstr ""
|
||||
|
||||
#: templates/layout.user.php:61
|
||||
#: templates/layout.user.php:62
|
||||
msgid "Log out"
|
||||
msgstr "الخروج"
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-26 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-25 00:20+0000\n"
|
||||
"POT-Creation-Date: 2013-05-30 02:27+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 00:27+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -17,12 +17,22 @@ msgstr ""
|
|||
"Language: ar\n"
|
||||
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
|
||||
|
||||
#: ajax/adminrecovery.php:40
|
||||
msgid "Recovery key successfully "
|
||||
#: ajax/adminrecovery.php:29
|
||||
msgid "Recovery key successfully enabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:42
|
||||
msgid "Could not "
|
||||
#: ajax/adminrecovery.php:34
|
||||
msgid ""
|
||||
"Could not enable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:48
|
||||
msgid "Recovery key successfully disabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:53
|
||||
msgid ""
|
||||
"Could not disable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/changeRecoveryPassword.php:49
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-28 00:02+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:59+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -57,7 +57,7 @@ msgstr "العودة الى الملفات"
|
|||
msgid "Selected files too large to generate zip file."
|
||||
msgstr "الملفات المحددة كبيرة جدا ليتم ضغطها في ملف zip"
|
||||
|
||||
#: helper.php:228
|
||||
#: helper.php:236
|
||||
msgid "couldn't be determined"
|
||||
msgstr "تعذّر تحديده"
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:59+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -324,11 +324,11 @@ msgstr "المزيد"
|
|||
msgid "Less"
|
||||
msgstr "أقل"
|
||||
|
||||
#: templates/admin.php:235 templates/personal.php:105
|
||||
#: templates/admin.php:235 templates/personal.php:111
|
||||
msgid "Version"
|
||||
msgstr "إصدار"
|
||||
|
||||
#: templates/admin.php:237 templates/personal.php:108
|
||||
#: templates/admin.php:237 templates/personal.php:114
|
||||
msgid ""
|
||||
"Developed by the <a href=\"http://ownCloud.org/contact\" "
|
||||
"target=\"_blank\">ownCloud community</a>, the <a "
|
||||
|
@ -427,31 +427,31 @@ msgstr "عدل كلمة السر"
|
|||
msgid "Display Name"
|
||||
msgstr "اسم الحساب"
|
||||
|
||||
#: templates/personal.php:68
|
||||
#: templates/personal.php:71
|
||||
msgid "Email"
|
||||
msgstr "البريد الإلكترونى"
|
||||
|
||||
#: templates/personal.php:70
|
||||
#: templates/personal.php:73
|
||||
msgid "Your email address"
|
||||
msgstr "عنوانك البريدي"
|
||||
|
||||
#: templates/personal.php:71
|
||||
#: templates/personal.php:74
|
||||
msgid "Fill in an email address to enable password recovery"
|
||||
msgstr "أدخل عنوانك البريدي لتفعيل استرجاع كلمة المرور"
|
||||
|
||||
#: templates/personal.php:77 templates/personal.php:78
|
||||
#: templates/personal.php:83 templates/personal.php:84
|
||||
msgid "Language"
|
||||
msgstr "اللغة"
|
||||
|
||||
#: templates/personal.php:89
|
||||
#: templates/personal.php:95
|
||||
msgid "Help translate"
|
||||
msgstr "ساعد في الترجمه"
|
||||
|
||||
#: templates/personal.php:94
|
||||
#: templates/personal.php:100
|
||||
msgid "WebDAV"
|
||||
msgstr "WebDAV"
|
||||
|
||||
#: templates/personal.php:96
|
||||
#: templates/personal.php:102
|
||||
msgid "Use this address to connect to your ownCloud in your file manager"
|
||||
msgstr "إستخدم هذا العنوان للإتصال بـ ownCloud في مدير الملفات"
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-25 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-25 00:02+0000\n"
|
||||
"POT-Creation-Date: 2013-05-30 02:27+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 00:27+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Belarusian (http://www.transifex.com/projects/p/owncloud/language/be/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -17,12 +17,22 @@ msgstr ""
|
|||
"Language: be\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: ajax/adminrecovery.php:40
|
||||
msgid "Recovery key successfully "
|
||||
#: ajax/adminrecovery.php:29
|
||||
msgid "Recovery key successfully enabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:42
|
||||
msgid "Could not "
|
||||
#: ajax/adminrecovery.php:34
|
||||
msgid ""
|
||||
"Could not enable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:48
|
||||
msgid "Recovery key successfully disabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:53
|
||||
msgid ""
|
||||
"Could not disable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/changeRecoveryPassword.php:49
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -564,12 +564,12 @@ msgstr "Завършване на настройките"
|
|||
msgid "web services under your control"
|
||||
msgstr "уеб услуги под Ваш контрол"
|
||||
|
||||
#: templates/layout.user.php:36
|
||||
#: templates/layout.user.php:37
|
||||
#, php-format
|
||||
msgid "%s is available. Get more information on how to update."
|
||||
msgstr ""
|
||||
|
||||
#: templates/layout.user.php:61
|
||||
#: templates/layout.user.php:62
|
||||
msgid "Log out"
|
||||
msgstr "Изход"
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-26 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-25 00:20+0000\n"
|
||||
"POT-Creation-Date: 2013-05-30 02:27+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 00:27+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -17,12 +17,22 @@ msgstr ""
|
|||
"Language: bg_BG\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ajax/adminrecovery.php:40
|
||||
msgid "Recovery key successfully "
|
||||
#: ajax/adminrecovery.php:29
|
||||
msgid "Recovery key successfully enabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:42
|
||||
msgid "Could not "
|
||||
#: ajax/adminrecovery.php:34
|
||||
msgid ""
|
||||
"Could not enable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:48
|
||||
msgid "Recovery key successfully disabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:53
|
||||
msgid ""
|
||||
"Could not disable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/changeRecoveryPassword.php:49
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-28 00:02+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:59+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -57,7 +57,7 @@ msgstr "Назад към файловете"
|
|||
msgid "Selected files too large to generate zip file."
|
||||
msgstr "Избраните файлове са прекалено големи за генерирането на ZIP архив."
|
||||
|
||||
#: helper.php:228
|
||||
#: helper.php:236
|
||||
msgid "couldn't be determined"
|
||||
msgstr "не може да се определи"
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:59+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -324,11 +324,11 @@ msgstr "Още"
|
|||
msgid "Less"
|
||||
msgstr "По-малко"
|
||||
|
||||
#: templates/admin.php:235 templates/personal.php:105
|
||||
#: templates/admin.php:235 templates/personal.php:111
|
||||
msgid "Version"
|
||||
msgstr "Версия"
|
||||
|
||||
#: templates/admin.php:237 templates/personal.php:108
|
||||
#: templates/admin.php:237 templates/personal.php:114
|
||||
msgid ""
|
||||
"Developed by the <a href=\"http://ownCloud.org/contact\" "
|
||||
"target=\"_blank\">ownCloud community</a>, the <a "
|
||||
|
@ -427,31 +427,31 @@ msgstr "Промяна на паролата"
|
|||
msgid "Display Name"
|
||||
msgstr "Екранно име"
|
||||
|
||||
#: templates/personal.php:68
|
||||
#: templates/personal.php:71
|
||||
msgid "Email"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: templates/personal.php:70
|
||||
#: templates/personal.php:73
|
||||
msgid "Your email address"
|
||||
msgstr "Вашия email адрес"
|
||||
|
||||
#: templates/personal.php:71
|
||||
#: templates/personal.php:74
|
||||
msgid "Fill in an email address to enable password recovery"
|
||||
msgstr "Въведете е-поща за възстановяване на паролата"
|
||||
|
||||
#: templates/personal.php:77 templates/personal.php:78
|
||||
#: templates/personal.php:83 templates/personal.php:84
|
||||
msgid "Language"
|
||||
msgstr "Език"
|
||||
|
||||
#: templates/personal.php:89
|
||||
#: templates/personal.php:95
|
||||
msgid "Help translate"
|
||||
msgstr "Помогнете с превода"
|
||||
|
||||
#: templates/personal.php:94
|
||||
#: templates/personal.php:100
|
||||
msgid "WebDAV"
|
||||
msgstr "WebDAV"
|
||||
|
||||
#: templates/personal.php:96
|
||||
#: templates/personal.php:102
|
||||
msgid "Use this address to connect to your ownCloud in your file manager"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-28 00:02+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -564,12 +564,12 @@ msgstr "সেটআপ সুসম্পন্ন কর"
|
|||
msgid "web services under your control"
|
||||
msgstr "ওয়েব সার্ভিস আপনার হাতের মুঠোয়"
|
||||
|
||||
#: templates/layout.user.php:36
|
||||
#: templates/layout.user.php:37
|
||||
#, php-format
|
||||
msgid "%s is available. Get more information on how to update."
|
||||
msgstr ""
|
||||
|
||||
#: templates/layout.user.php:61
|
||||
#: templates/layout.user.php:62
|
||||
msgid "Log out"
|
||||
msgstr "প্রস্থান"
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-26 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-25 00:20+0000\n"
|
||||
"POT-Creation-Date: 2013-05-30 02:27+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 00:27+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -17,12 +17,22 @@ msgstr ""
|
|||
"Language: bn_BD\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ajax/adminrecovery.php:40
|
||||
msgid "Recovery key successfully "
|
||||
#: ajax/adminrecovery.php:29
|
||||
msgid "Recovery key successfully enabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:42
|
||||
msgid "Could not "
|
||||
#: ajax/adminrecovery.php:34
|
||||
msgid ""
|
||||
"Could not enable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:48
|
||||
msgid "Recovery key successfully disabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:53
|
||||
msgid ""
|
||||
"Could not disable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/changeRecoveryPassword.php:49
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-28 00:02+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:59+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -57,7 +57,7 @@ msgstr "ফাইলে ফিরে চল"
|
|||
msgid "Selected files too large to generate zip file."
|
||||
msgstr "নির্বাচিত ফাইলগুলো এতই বৃহৎ যে জিপ ফাইল তৈরী করা সম্ভব নয়।"
|
||||
|
||||
#: helper.php:228
|
||||
#: helper.php:236
|
||||
msgid "couldn't be determined"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:59+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -324,11 +324,11 @@ msgstr "বেশী"
|
|||
msgid "Less"
|
||||
msgstr "কম"
|
||||
|
||||
#: templates/admin.php:235 templates/personal.php:105
|
||||
#: templates/admin.php:235 templates/personal.php:111
|
||||
msgid "Version"
|
||||
msgstr "ভার্সন"
|
||||
|
||||
#: templates/admin.php:237 templates/personal.php:108
|
||||
#: templates/admin.php:237 templates/personal.php:114
|
||||
msgid ""
|
||||
"Developed by the <a href=\"http://ownCloud.org/contact\" "
|
||||
"target=\"_blank\">ownCloud community</a>, the <a "
|
||||
|
@ -427,31 +427,31 @@ msgstr "কূটশব্দ পরিবর্তন করুন"
|
|||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#: templates/personal.php:68
|
||||
#: templates/personal.php:71
|
||||
msgid "Email"
|
||||
msgstr "ইমেইল"
|
||||
|
||||
#: templates/personal.php:70
|
||||
#: templates/personal.php:73
|
||||
msgid "Your email address"
|
||||
msgstr "আপনার ই-মেইল ঠিকানা"
|
||||
|
||||
#: templates/personal.php:71
|
||||
#: templates/personal.php:74
|
||||
msgid "Fill in an email address to enable password recovery"
|
||||
msgstr "কূটশব্দ পূনরূদ্ধার সক্রিয় করার জন্য ই-মেইল ঠিকানাটি পূরণ করুন"
|
||||
|
||||
#: templates/personal.php:77 templates/personal.php:78
|
||||
#: templates/personal.php:83 templates/personal.php:84
|
||||
msgid "Language"
|
||||
msgstr "ভাষা"
|
||||
|
||||
#: templates/personal.php:89
|
||||
#: templates/personal.php:95
|
||||
msgid "Help translate"
|
||||
msgstr "অনুবাদ করতে সহায়তা করুন"
|
||||
|
||||
#: templates/personal.php:94
|
||||
#: templates/personal.php:100
|
||||
msgid "WebDAV"
|
||||
msgstr "WebDAV"
|
||||
|
||||
#: templates/personal.php:96
|
||||
#: templates/personal.php:102
|
||||
msgid "Use this address to connect to your ownCloud in your file manager"
|
||||
msgstr "আপনার ownCloud এ সংযুক্ত হতে এই ঠিকানাটি আপনার ফাইল ব্যবস্থাপকে ব্যবহার করুন"
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -9,8 +9,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: rogerc\n"
|
||||
"Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -313,11 +313,11 @@ msgstr "Envia"
|
|||
|
||||
#: js/share.js:178
|
||||
msgid "Set expiration date"
|
||||
msgstr "Estableix la data d'expiració"
|
||||
msgstr "Estableix la data de venciment"
|
||||
|
||||
#: js/share.js:179
|
||||
msgid "Expiration date"
|
||||
msgstr "Data d'expiració"
|
||||
msgstr "Data de venciment"
|
||||
|
||||
#: js/share.js:211
|
||||
msgid "Share via email:"
|
||||
|
@ -369,11 +369,11 @@ msgstr "Protegeix amb contrasenya"
|
|||
|
||||
#: js/share.js:577
|
||||
msgid "Error unsetting expiration date"
|
||||
msgstr "Error en eliminar la data d'expiració"
|
||||
msgstr "Error en eliminar la data de venciment"
|
||||
|
||||
#: js/share.js:589
|
||||
msgid "Error setting expiration date"
|
||||
msgstr "Error en establir la data d'expiració"
|
||||
msgstr "Error en establir la data de venciment"
|
||||
|
||||
#: js/share.js:604
|
||||
msgid "Sending ..."
|
||||
|
@ -566,12 +566,12 @@ msgstr "Acaba la configuració"
|
|||
msgid "web services under your control"
|
||||
msgstr "controleu els vostres serveis web"
|
||||
|
||||
#: templates/layout.user.php:36
|
||||
#: templates/layout.user.php:37
|
||||
#, php-format
|
||||
msgid "%s is available. Get more information on how to update."
|
||||
msgstr "%s està disponible. Obtingueu més informació de com actualitzar."
|
||||
|
||||
#: templates/layout.user.php:61
|
||||
#: templates/layout.user.php:62
|
||||
msgid "Log out"
|
||||
msgstr "Surt"
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: rogerc\n"
|
||||
"Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -8,8 +8,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-26 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-25 00:20+0000\n"
|
||||
"POT-Creation-Date: 2013-05-30 02:27+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 00:27+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -18,12 +18,22 @@ msgstr ""
|
|||
"Language: ca\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: ajax/adminrecovery.php:40
|
||||
msgid "Recovery key successfully "
|
||||
#: ajax/adminrecovery.php:29
|
||||
msgid "Recovery key successfully enabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:42
|
||||
msgid "Could not "
|
||||
#: ajax/adminrecovery.php:34
|
||||
msgid ""
|
||||
"Could not enable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:48
|
||||
msgid "Recovery key successfully disabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:53
|
||||
msgid ""
|
||||
"Could not disable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/changeRecoveryPassword.php:49
|
||||
|
|
|
@ -8,8 +8,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: rogerc\n"
|
||||
"Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -8,8 +8,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-28 00:02+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:59+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: rogerc\n"
|
||||
"Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -58,7 +58,7 @@ msgstr "Torna a Fitxers"
|
|||
msgid "Selected files too large to generate zip file."
|
||||
msgstr "Els fitxers seleccionats son massa grans per generar un fitxer zip."
|
||||
|
||||
#: helper.php:228
|
||||
#: helper.php:236
|
||||
msgid "couldn't be determined"
|
||||
msgstr "no s'ha pogut determinar"
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:59+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: rogerc\n"
|
||||
"Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -326,11 +326,11 @@ msgstr "Més"
|
|||
msgid "Less"
|
||||
msgstr "Menys"
|
||||
|
||||
#: templates/admin.php:235 templates/personal.php:105
|
||||
#: templates/admin.php:235 templates/personal.php:111
|
||||
msgid "Version"
|
||||
msgstr "Versió"
|
||||
|
||||
#: templates/admin.php:237 templates/personal.php:108
|
||||
#: templates/admin.php:237 templates/personal.php:114
|
||||
msgid ""
|
||||
"Developed by the <a href=\"http://ownCloud.org/contact\" "
|
||||
"target=\"_blank\">ownCloud community</a>, the <a "
|
||||
|
@ -429,31 +429,31 @@ msgstr "Canvia la contrasenya"
|
|||
msgid "Display Name"
|
||||
msgstr "Nom a mostrar"
|
||||
|
||||
#: templates/personal.php:68
|
||||
#: templates/personal.php:71
|
||||
msgid "Email"
|
||||
msgstr "Correu electrònic"
|
||||
|
||||
#: templates/personal.php:70
|
||||
#: templates/personal.php:73
|
||||
msgid "Your email address"
|
||||
msgstr "Correu electrònic"
|
||||
|
||||
#: templates/personal.php:71
|
||||
#: templates/personal.php:74
|
||||
msgid "Fill in an email address to enable password recovery"
|
||||
msgstr "Ompliu el correu electrònic per activar la recuperació de contrasenya"
|
||||
|
||||
#: templates/personal.php:77 templates/personal.php:78
|
||||
#: templates/personal.php:83 templates/personal.php:84
|
||||
msgid "Language"
|
||||
msgstr "Idioma"
|
||||
|
||||
#: templates/personal.php:89
|
||||
#: templates/personal.php:95
|
||||
msgid "Help translate"
|
||||
msgstr "Ajudeu-nos amb la traducció"
|
||||
|
||||
#: templates/personal.php:94
|
||||
#: templates/personal.php:100
|
||||
msgid "WebDAV"
|
||||
msgstr "WebDAV"
|
||||
|
||||
#: templates/personal.php:96
|
||||
#: templates/personal.php:102
|
||||
msgid "Use this address to connect to your ownCloud in your file manager"
|
||||
msgstr "Useu aquesta adreça per connectar amb ownCloud des del gestor de fitxers"
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: rogerc\n"
|
||||
"Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -8,8 +8,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: Tomáš Chvátal <tomas.chvatal@gmail.com>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -565,12 +565,12 @@ msgstr "Dokončit nastavení"
|
|||
msgid "web services under your control"
|
||||
msgstr "služby webu pod Vaší kontrolou"
|
||||
|
||||
#: templates/layout.user.php:36
|
||||
#: templates/layout.user.php:37
|
||||
#, php-format
|
||||
msgid "%s is available. Get more information on how to update."
|
||||
msgstr "%s je dostupná. Získejte více informací k postupu aktualizace."
|
||||
|
||||
#: templates/layout.user.php:61
|
||||
#: templates/layout.user.php:62
|
||||
msgid "Log out"
|
||||
msgstr "Odhlásit se"
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-26 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-25 00:20+0000\n"
|
||||
"POT-Creation-Date: 2013-05-30 02:27+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 00:27+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -17,12 +17,22 @@ msgstr ""
|
|||
"Language: cs_CZ\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
|
||||
#: ajax/adminrecovery.php:40
|
||||
msgid "Recovery key successfully "
|
||||
#: ajax/adminrecovery.php:29
|
||||
msgid "Recovery key successfully enabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:42
|
||||
msgid "Could not "
|
||||
#: ajax/adminrecovery.php:34
|
||||
msgid ""
|
||||
"Could not enable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:48
|
||||
msgid "Recovery key successfully disabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:53
|
||||
msgid ""
|
||||
"Could not disable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/changeRecoveryPassword.php:49
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-28 00:02+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:59+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -57,7 +57,7 @@ msgstr "Zpět k souborům"
|
|||
msgid "Selected files too large to generate zip file."
|
||||
msgstr "Vybrané soubory jsou příliš velké pro vytvoření zip souboru."
|
||||
|
||||
#: helper.php:228
|
||||
#: helper.php:236
|
||||
msgid "couldn't be determined"
|
||||
msgstr "nelze zjistit"
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:59+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -324,11 +324,11 @@ msgstr "Více"
|
|||
msgid "Less"
|
||||
msgstr "Méně"
|
||||
|
||||
#: templates/admin.php:235 templates/personal.php:105
|
||||
#: templates/admin.php:235 templates/personal.php:111
|
||||
msgid "Version"
|
||||
msgstr "Verze"
|
||||
|
||||
#: templates/admin.php:237 templates/personal.php:108
|
||||
#: templates/admin.php:237 templates/personal.php:114
|
||||
msgid ""
|
||||
"Developed by the <a href=\"http://ownCloud.org/contact\" "
|
||||
"target=\"_blank\">ownCloud community</a>, the <a "
|
||||
|
@ -427,31 +427,31 @@ msgstr "Změnit heslo"
|
|||
msgid "Display Name"
|
||||
msgstr "Zobrazované jméno"
|
||||
|
||||
#: templates/personal.php:68
|
||||
#: templates/personal.php:71
|
||||
msgid "Email"
|
||||
msgstr "E-mail"
|
||||
|
||||
#: templates/personal.php:70
|
||||
#: templates/personal.php:73
|
||||
msgid "Your email address"
|
||||
msgstr "Vaše e-mailová adresa"
|
||||
|
||||
#: templates/personal.php:71
|
||||
#: templates/personal.php:74
|
||||
msgid "Fill in an email address to enable password recovery"
|
||||
msgstr "Pro povolení změny hesla vyplňte adresu e-mailu"
|
||||
|
||||
#: templates/personal.php:77 templates/personal.php:78
|
||||
#: templates/personal.php:83 templates/personal.php:84
|
||||
msgid "Language"
|
||||
msgstr "Jazyk"
|
||||
|
||||
#: templates/personal.php:89
|
||||
#: templates/personal.php:95
|
||||
msgid "Help translate"
|
||||
msgstr "Pomoci s překladem"
|
||||
|
||||
#: templates/personal.php:94
|
||||
#: templates/personal.php:100
|
||||
msgid "WebDAV"
|
||||
msgstr "WebDAV"
|
||||
|
||||
#: templates/personal.php:96
|
||||
#: templates/personal.php:102
|
||||
msgid "Use this address to connect to your ownCloud in your file manager"
|
||||
msgstr "Použijte tuto adresu pro připojení k vašemu ownCloud skrze správce souborů"
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -8,8 +8,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: ubuntucymraeg <owen.llywelyn@gmail.com>\n"
|
||||
"Language-Team: Welsh (United Kingdom) (http://www.transifex.com/projects/p/owncloud/language/cy_GB/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -565,12 +565,12 @@ msgstr "Gorffen sefydlu"
|
|||
msgid "web services under your control"
|
||||
msgstr "gwasanaethau gwe a reolir gennych"
|
||||
|
||||
#: templates/layout.user.php:36
|
||||
#: templates/layout.user.php:37
|
||||
#, php-format
|
||||
msgid "%s is available. Get more information on how to update."
|
||||
msgstr "%s ar gael. Mwy o wybodaeth am sut i ddiweddaru."
|
||||
|
||||
#: templates/layout.user.php:61
|
||||
#: templates/layout.user.php:62
|
||||
msgid "Log out"
|
||||
msgstr "Allgofnodi"
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:16+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:15+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Welsh (United Kingdom) (http://www.transifex.com/projects/p/owncloud/language/cy_GB/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -8,8 +8,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-26 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-25 00:20+0000\n"
|
||||
"POT-Creation-Date: 2013-05-30 02:27+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 00:27+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Welsh (United Kingdom) (http://www.transifex.com/projects/p/owncloud/language/cy_GB/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -18,12 +18,22 @@ msgstr ""
|
|||
"Language: cy_GB\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;\n"
|
||||
|
||||
#: ajax/adminrecovery.php:40
|
||||
msgid "Recovery key successfully "
|
||||
#: ajax/adminrecovery.php:29
|
||||
msgid "Recovery key successfully enabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:42
|
||||
msgid "Could not "
|
||||
#: ajax/adminrecovery.php:34
|
||||
msgid ""
|
||||
"Could not enable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:48
|
||||
msgid "Recovery key successfully disabled"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/adminrecovery.php:53
|
||||
msgid ""
|
||||
"Could not disable recovery key. Please check your recovery key password!"
|
||||
msgstr ""
|
||||
|
||||
#: ajax/changeRecoveryPassword.php:49
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: I Robot <owncloud-bot@tmit.eu>\n"
|
||||
"Language-Team: Welsh (United Kingdom) (http://www.transifex.com/projects/p/owncloud/language/cy_GB/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: ubuntucymraeg <owen.llywelyn@gmail.com>\n"
|
||||
"Language-Team: Welsh (United Kingdom) (http://www.transifex.com/projects/p/owncloud/language/cy_GB/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-27 23:17+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:58+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: ubuntucymraeg <owen.llywelyn@gmail.com>\n"
|
||||
"Language-Team: Welsh (United Kingdom) (http://www.transifex.com/projects/p/owncloud/language/cy_GB/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: ownCloud\n"
|
||||
"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n"
|
||||
"POT-Creation-Date: 2013-05-28 02:01+0200\n"
|
||||
"PO-Revision-Date: 2013-05-28 00:02+0000\n"
|
||||
"POT-Creation-Date: 2013-05-31 01:59+0200\n"
|
||||
"PO-Revision-Date: 2013-05-30 23:16+0000\n"
|
||||
"Last-Translator: ubuntucymraeg <owen.llywelyn@gmail.com>\n"
|
||||
"Language-Team: Welsh (United Kingdom) (http://www.transifex.com/projects/p/owncloud/language/cy_GB/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -57,7 +57,7 @@ msgstr "Nôl i Ffeiliau"
|
|||
msgid "Selected files too large to generate zip file."
|
||||
msgstr "Mae'r ffeiliau ddewiswyd yn rhy fawr i gynhyrchu ffeil zip."
|
||||
|
||||
#: helper.php:228
|
||||
#: helper.php:236
|
||||
msgid "couldn't be determined"
|
||||
msgstr "methwyd pennu"
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue