diff options
Diffstat (limited to 'apps/files_encryption/lib')
-rwxr-xr-x | apps/files_encryption/lib/helper.php | 2 | ||||
-rwxr-xr-x | apps/files_encryption/lib/keymanager.php | 55 | ||||
-rw-r--r-- | apps/files_encryption/lib/proxy.php | 76 | ||||
-rw-r--r-- | apps/files_encryption/lib/util.php | 54 |
4 files changed, 85 insertions, 102 deletions
diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 5dcb05fa196..bb06a57c714 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -63,6 +63,8 @@ class Helper { \OCP\Util::connectHook('OC_Filesystem', 'rename', 'OCA\Encryption\Hooks', 'preRename'); \OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRename'); + \OCP\Util::connectHook('OC_Filesystem', 'post_delete', 'OCA\Encryption\Hooks', 'postDelete'); + \OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Encryption\Hooks', 'preDelete'); } /** diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index b2c756894b4..7abc565f609 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -214,15 +214,24 @@ class Keymanager { * * @param \OC_FilesystemView $view * @param string $path path of the file the key belongs to + * @param string $userId the user to whom the file belongs * @return bool Outcome of unlink operation * @note $path must be relative to data/user/files. e.g. mydoc.txt NOT * /data/admin/files/mydoc.txt */ - public static function deleteFileKey(\OC_FilesystemView $view, $path) { + public static function deleteFileKey($view, $path, $userId=null) { $trimmed = ltrim($path, '/'); - $userId = Helper::getUser($path); + if ($trimmed === '') { + \OCP\Util::writeLog('Encryption library', + 'Can\'t delete file-key empty path given!', \OCP\Util::ERROR); + return false; + } + + if ($userId === null) { + $userId = Helper::getUser($path); + } $util = new Util($view, $userId); if($util->isSystemWideMountPoint($path)) { @@ -402,7 +411,15 @@ 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($view, $userId, $filePath) { + + $filePath = ltrim($filePath, '/'); + + if ($filePath === '') { + \OCP\Util::writeLog('Encryption library', + 'Can\'t delete share-keys empty path given!', \OCP\Util::ERROR); + return false; + } $util = new util($view, $userId); @@ -413,17 +430,15 @@ class Keymanager { } - if ($view->is_dir($userId . '/files/' . $filePath)) { + if ($view->is_dir($baseDir . $filePath)) { $view->unlink($baseDir . $filePath); } else { - $localKeyPath = $view->getLocalFile($baseDir . $filePath); - $escapedPath = Helper::escapeGlobPattern($localKeyPath); - $matches = glob($escapedPath . '*.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); + $parentDir = dirname($baseDir . $filePath); + $filename = pathinfo($filePath, PATHINFO_BASENAME); + foreach($view->getDirectoryContent($parentDir) as $content) { + $path = $content['path']; + if (self::getFilenameFromShareKey($content['name']) === $filename) { + $view->unlink('/' . $userId . '/' . $path); } } } @@ -523,4 +538,20 @@ class Keymanager { return $targetPath; } + + /** + * @brief extract filename from share key name + * @param string $shareKey (filename.userid.sharekey) + * @return mixed filename or false + */ + protected static function getFilenameFromShareKey($shareKey) { + $parts = explode('.', $shareKey); + + $filename = false; + if(count($parts) > 2) { + $filename = implode('.', array_slice($parts, 0, count($parts)-2)); + } + + return $filename; + } } diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 41f352d853a..11048005969 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -37,6 +37,7 @@ namespace OCA\Encryption; class Proxy extends \OC_FileProxy { private static $blackList = null; //mimetypes blacklisted from encryption + private static $unencryptedSizes = array(); // remember unencrypted size /** * Check if a file requires encryption @@ -114,14 +115,12 @@ class Proxy extends \OC_FileProxy { // get encrypted content $data = $view->file_get_contents($tmpPath); - // update file cache for target file + // store new unenecrypted size so that it can be updated + // in the post proxy $tmpFileInfo = $view->getFileInfo($tmpPath); - $fileInfo = $view->getFileInfo($path); - if (is_array($fileInfo) && is_array($tmpFileInfo)) { - $fileInfo['encrypted'] = true; - $fileInfo['unencrypted_size'] = $tmpFileInfo['size']; - $view->putFileInfo($path, $fileInfo); - } + if ( isset($tmpFileInfo['size']) ) { + self::$unencryptedSizes[\OC_Filesystem::normalizePath($path)] = $tmpFileInfo['size']; + } // remove our temp file $view->deleteAll('/' . \OCP\User::getUser() . '/cache/' . $cacheFolder); @@ -137,6 +136,24 @@ class Proxy extends \OC_FileProxy { } /** + * @brief update file cache with the new unencrypted size after file was written + * @param string $path + * @param mixed $result + * @return mixed + */ + public function postFile_put_contents($path, $result) { + $normalizedPath = \OC_Filesystem::normalizePath($path); + if ( isset(self::$unencryptedSizes[$normalizedPath]) ) { + $view = new \OC_FilesystemView('/'); + $view->putFileInfo($normalizedPath, + array('encrypted' => true, 'encrypted_size' => self::$unencryptedSizes[$normalizedPath])); + unset(self::$unencryptedSizes[$normalizedPath]); + } + + return $result; + } + + /** * @param string $path Path of file from which has been read * @param string $data Data that has been read from file */ @@ -187,47 +204,6 @@ class Proxy extends \OC_FileProxy { } /** - * @brief When a file is deleted, remove its keyfile also - */ - public function preUnlink($path) { - - $relPath = Helper::stripUserFilesPath($path); - - // skip this method if the trash bin is enabled or if we delete a file - // outside of /data/user/files - if (\OCP\App::isEnabled('files_trashbin') || $relPath === false) { - return true; - } - - // Disable encryption proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - - $view = new \OC_FilesystemView('/'); - - $userId = \OCP\USER::getUser(); - - $util = new Util($view, $userId); - - list($owner, $ownerPath) = $util->getUidAndFilename($relPath); - - // Delete keyfile & shareKey so it isn't orphaned - if (!Keymanager::deleteFileKey($view, $ownerPath)) { - \OCP\Util::writeLog('Encryption library', - 'Keyfile or shareKey could not be deleted for file "' . $ownerPath . '"', \OCP\Util::ERROR); - } - - Keymanager::delAllShareKeys($view, $owner, $ownerPath); - - \OC_FileProxy::$enabled = $proxyStatus; - - // If we don't return true then file delete will fail; better - // to leave orphaned keyfiles than to disallow file deletion - return true; - - } - - /** * @param $path * @return bool */ @@ -255,8 +231,8 @@ class Proxy extends \OC_FileProxy { // split the path parts $pathParts = explode('/', $path); - // FIXME: handling for /userId/cache used by webdav for chunking. The cache chunks are NOT encrypted - if (isset($pathParts[2]) && $pathParts[2] === 'cache') { + // don't try to encrypt/decrypt cache chunks or files in the trash bin + if (isset($pathParts[2]) && ($pathParts[2] === 'cache' || $pathParts[2] === 'files_trashbin')) { return $result; } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 8a5dfabeec1..ae3e2a2e15a 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -2,9 +2,10 @@ /** * ownCloud * - * @author Sam Tuke, Frank Karlitschek + * @author Sam Tuke, Frank Karlitschek, Bjoern Schiessle * @copyright 2012 Sam Tuke <samtuke@owncloud.com>, - * Frank Karlitschek <frank@owncloud.org> + * Frank Karlitschek <frank@owncloud.org>, + * Bjoern Schiessle <schiessle@owncloud.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -56,7 +57,7 @@ class Util { * @param $userId * @param bool $client */ - public function __construct(\OC_FilesystemView $view, $userId, $client = false) { + public function __construct($view, $userId, $client = false) { $this->view = $view; $this->client = $client; @@ -1360,59 +1361,32 @@ class Util { } } - /** * @brief go recursively through a dir and collect all files and sub files. * @param string $dir relative to the users files folder * @return array with list of files relative to the users files folder */ public function getAllFiles($dir) { - $result = array(); + $dirList = array($dir); - $content = $this->view->getDirectoryContent(\OC\Files\Filesystem::normalizePath( - $this->userFilesDir . '/' . $dir)); - - // handling for re shared folders - $pathSplit = explode('/', $dir); - - foreach ($content as $c) { - - $sharedPart = $pathSplit[sizeof($pathSplit) - 1]; - $targetPathSplit = array_reverse(explode('/', $c['path'])); - - $path = ''; - - // rebuild path - foreach ($targetPathSplit as $pathPart) { - - if ($pathPart !== $sharedPart) { - - $path = '/' . $pathPart . $path; + while ($dirList) { + $dir = array_pop($dirList); + $content = $this->view->getDirectoryContent(\OC\Files\Filesystem::normalizePath( + $this->userFilesDir . '/' . $dir)); + foreach ($content as $c) { + $usersPath = isset($c['usersPath']) ? $c['usersPath'] : $c['path']; + if ($c['type'] === 'dir') { + $dirList[] = substr($usersPath, strlen("files")); } else { - - break; - + $result[] = substr($usersPath, strlen("files")); } - } - $path = $dir . $path; - - if ($c['type'] === 'dir') { - - $result = array_merge($result, $this->getAllFiles($path)); - - } else { - - $result[] = $path; - - } } return $result; - } /** |