aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/files
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/files')
-rw-r--r--lib/private/files/cache/cache.php29
-rw-r--r--lib/private/files/cache/homecache.php14
-rw-r--r--lib/private/files/fileinfo.php7
-rw-r--r--lib/private/files/storage/common.php43
-rw-r--r--lib/private/files/storage/localtempfiletrait.php85
-rw-r--r--lib/private/files/storage/wrapper/encryption.php181
-rw-r--r--lib/private/files/storage/wrapper/quota.php5
-rw-r--r--lib/private/files/stream/encryption.php126
-rw-r--r--lib/private/files/view.php22
9 files changed, 327 insertions, 185 deletions
diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php
index 9a785d071f7..c5e118946e5 100644
--- a/lib/private/files/cache/cache.php
+++ b/lib/private/files/cache/cache.php
@@ -152,7 +152,7 @@ class Cache {
$params = array($file);
}
$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`,
- `storage_mtime`, `encrypted`, `unencrypted_size`, `etag`, `permissions`
+ `storage_mtime`, `encrypted`, `etag`, `permissions`
FROM `*PREFIX*filecache` ' . $where;
$result = \OC_DB::executeAudited($sql, $params);
$data = $result->fetchRow();
@@ -175,7 +175,6 @@ class Cache {
$data['mtime'] = (int)$data['mtime'];
$data['storage_mtime'] = (int)$data['storage_mtime'];
$data['encrypted'] = (bool)$data['encrypted'];
- $data['unencrypted_size'] = 0 + $data['unencrypted_size'];
$data['storage'] = $this->storageId;
$data['mimetype'] = $this->getMimetype($data['mimetype']);
$data['mimepart'] = $this->getMimetype($data['mimepart']);
@@ -208,7 +207,7 @@ class Cache {
public function getFolderContentsById($fileId) {
if ($fileId > -1) {
$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`,
- `storage_mtime`, `encrypted`, `unencrypted_size`, `etag`, `permissions`
+ `storage_mtime`, `encrypted`, `etag`, `permissions`
FROM `*PREFIX*filecache` WHERE `parent` = ? ORDER BY `name` ASC';
$result = \OC_DB::executeAudited($sql, array($fileId));
$files = $result->fetchAll();
@@ -218,10 +217,6 @@ class Cache {
if ($file['storage_mtime'] == 0) {
$file['storage_mtime'] = $file['mtime'];
}
- if ($file['encrypted'] or ($file['unencrypted_size'] > 0 and $file['mimetype'] === 'httpd/unix-directory')) {
- $file['encrypted_size'] = $file['size'];
- $file['size'] = $file['unencrypted_size'];
- }
$file['permissions'] = (int)$file['permissions'];
$file['mtime'] = (int)$file['mtime'];
$file['storage_mtime'] = (int)$file['storage_mtime'];
@@ -325,7 +320,7 @@ class Cache {
*/
function buildParts(array $data) {
$fields = array(
- 'path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'storage_mtime', 'encrypted', 'unencrypted_size',
+ 'path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'storage_mtime', 'encrypted',
'etag', 'permissions');
$params = array();
$queryParts = array();
@@ -521,7 +516,7 @@ class Cache {
$sql = '
SELECT `fileid`, `storage`, `path`, `parent`, `name`,
`mimetype`, `mimepart`, `size`, `mtime`, `encrypted`,
- `unencrypted_size`, `etag`, `permissions`
+ `etag`, `permissions`
FROM `*PREFIX*filecache`
WHERE `storage` = ? AND `name` ILIKE ?';
$result = \OC_DB::executeAudited($sql,
@@ -549,7 +544,7 @@ class Cache {
} else {
$where = '`mimepart` = ?';
}
- $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag`, `permissions`
+ $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag`, `permissions`
FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?';
$mimetype = $this->getMimetypeId($mimetype);
$result = \OC_DB::executeAudited($sql, array($mimetype, $this->getNumericStorageId()));
@@ -574,7 +569,7 @@ class Cache {
public function searchByTag($tag, $userId) {
$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, ' .
'`mimetype`, `mimepart`, `size`, `mtime`, ' .
- '`encrypted`, `unencrypted_size`, `etag`, `permissions` ' .
+ '`encrypted`, `etag`, `permissions` ' .
'FROM `*PREFIX*filecache` `file`, ' .
'`*PREFIX*vcategory_to_object` `tagmap`, ' .
'`*PREFIX*vcategory` `tag` ' .
@@ -638,17 +633,15 @@ class Cache {
}
if (isset($entry['mimetype']) && $entry['mimetype'] === 'httpd/unix-directory') {
$id = $entry['fileid'];
- $sql = 'SELECT SUM(`size`) AS f1, MIN(`size`) AS f2, ' .
- 'SUM(`unencrypted_size`) AS f3 ' .
+ $sql = 'SELECT SUM(`size`) AS f1, MIN(`size`) AS f2 ' .
'FROM `*PREFIX*filecache` ' .
'WHERE `parent` = ? AND `storage` = ?';
$result = \OC_DB::executeAudited($sql, array($id, $this->getNumericStorageId()));
if ($row = $result->fetchRow()) {
$result->closeCursor();
- list($sum, $min, $unencryptedSum) = array_values($row);
+ list($sum, $min) = array_values($row);
$sum = 0 + $sum;
$min = 0 + $min;
- $unencryptedSum = 0 + $unencryptedSum;
if ($min === -1) {
$totalSize = $min;
} else {
@@ -658,15 +651,9 @@ class Cache {
if ($entry['size'] !== $totalSize) {
$update['size'] = $totalSize;
}
- if (!isset($entry['unencrypted_size']) or $entry['unencrypted_size'] !== $unencryptedSum) {
- $update['unencrypted_size'] = $unencryptedSum;
- }
if (count($update) > 0) {
$this->update($id, $update);
}
- if ($totalSize !== -1 and $unencryptedSum > 0) {
- $totalSize = $unencryptedSum;
- }
} else {
$result->closeCursor();
}
diff --git a/lib/private/files/cache/homecache.php b/lib/private/files/cache/homecache.php
index aa075d41221..1b85462d615 100644
--- a/lib/private/files/cache/homecache.php
+++ b/lib/private/files/cache/homecache.php
@@ -48,26 +48,18 @@ class HomeCache extends Cache {
}
if ($entry && $entry['mimetype'] === 'httpd/unix-directory') {
$id = $entry['fileid'];
- $sql = 'SELECT SUM(`size`) AS f1, ' .
- 'SUM(`unencrypted_size`) AS f2 FROM `*PREFIX*filecache` ' .
+ $sql = 'SELECT SUM(`size`) AS f1 ' .
+ 'FROM `*PREFIX*filecache` ' .
'WHERE `parent` = ? AND `storage` = ? AND `size` >= 0';
$result = \OC_DB::executeAudited($sql, array($id, $this->getNumericStorageId()));
if ($row = $result->fetchRow()) {
$result->closeCursor();
- list($sum, $unencryptedSum) = array_values($row);
+ list($sum) = array_values($row);
$totalSize = 0 + $sum;
- $unencryptedSize = 0 + $unencryptedSum;
$entry['size'] += 0;
- if (!isset($entry['unencrypted_size'])) {
- $entry['unencrypted_size'] = 0;
- }
- $entry['unencrypted_size'] += 0;
if ($entry['size'] !== $totalSize) {
$this->update($id, array('size' => $totalSize));
}
- if ($entry['unencrypted_size'] !== $unencryptedSize) {
- $this->update($id, array('unencrypted_size' => $unencryptedSize));
- }
}
}
return $totalSize;
diff --git a/lib/private/files/fileinfo.php b/lib/private/files/fileinfo.php
index 03aad56e103..82c8f3de690 100644
--- a/lib/private/files/fileinfo.php
+++ b/lib/private/files/fileinfo.php
@@ -170,13 +170,6 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
/**
* @return int
*/
- public function getUnencryptedSize() {
- return isset($this->data['unencrypted_size']) ? $this->data['unencrypted_size'] : 0;
- }
-
- /**
- * @return int
- */
public function getPermissions() {
return $this->data['permissions'];
}
diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php
index 9fef53fa95a..ed85d3c07cc 100644
--- a/lib/private/files/storage/common.php
+++ b/lib/private/files/storage/common.php
@@ -56,6 +56,9 @@ use OCP\Files\ReservedWordException;
* in classes which extend it, e.g. $this->stat() .
*/
abstract class Common implements Storage {
+
+ use LocalTempFileTrait;
+
protected $cache;
protected $scanner;
protected $watcher;
@@ -63,11 +66,6 @@ abstract class Common implements Storage {
protected $mountOptions = [];
- /**
- * @var string[]
- */
- protected $cachedFiles = array();
-
public function __construct($parameters) {
}
@@ -247,27 +245,6 @@ abstract class Common implements Storage {
return $this->getCachedFile($path);
}
- /**
- * @param string $path
- * @return string
- */
- protected function toTmpFile($path) { //no longer in the storage api, still useful here
- $source = $this->fopen($path, 'r');
- if (!$source) {
- return false;
- }
- if ($pos = strrpos($path, '.')) {
- $extension = substr($path, $pos);
- } else {
- $extension = '';
- }
- $tmpFile = \OC_Helper::tmpFile($extension);
- $target = fopen($tmpFile, 'w');
- \OC_Helper::streamCopy($source, $target);
- fclose($target);
- return $tmpFile;
- }
-
public function getLocalFolder($path) {
$baseDir = \OC_Helper::tmpFolder();
$this->addLocalFolder($path, $baseDir);
@@ -451,20 +428,6 @@ abstract class Common implements Storage {
}
/**
- * @param string $path
- */
- protected function getCachedFile($path) {
- if (!isset($this->cachedFiles[$path])) {
- $this->cachedFiles[$path] = $this->toTmpFile($path);
- }
- return $this->cachedFiles[$path];
- }
-
- protected function removeCachedFile($path) {
- unset($this->cachedFiles[$path]);
- }
-
- /**
* Check if the storage is an instance of $class or is a wrapper for a storage that is an instance of $class
*
* @param string $class
diff --git a/lib/private/files/storage/localtempfiletrait.php b/lib/private/files/storage/localtempfiletrait.php
new file mode 100644
index 00000000000..444e4e2e89e
--- /dev/null
+++ b/lib/private/files/storage/localtempfiletrait.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Files\Storage;
+
+use OC\Files\Cache\Cache;
+use OC\Files\Cache\Scanner;
+use OC\Files\Filesystem;
+use OC\Files\Cache\Watcher;
+use OCP\Files\FileNameTooLongException;
+use OCP\Files\InvalidCharacterInPathException;
+use OCP\Files\InvalidPathException;
+use OCP\Files\ReservedWordException;
+
+/**
+ * Storage backend class for providing common filesystem operation methods
+ * which are not storage-backend specific.
+ *
+ * \OC\Files\Storage\Common is never used directly; it is extended by all other
+ * storage backends, where its methods may be overridden, and additional
+ * (backend-specific) methods are defined.
+ *
+ * Some \OC\Files\Storage\Common methods call functions which are first defined
+ * in classes which extend it, e.g. $this->stat() .
+ */
+trait LocalTempFileTrait {
+
+ /**
+ * @var string[]
+ */
+ protected $cachedFiles = array();
+
+ /**
+ * @param string $path
+ */
+ protected function getCachedFile($path) {
+ if (!isset($this->cachedFiles[$path])) {
+ $this->cachedFiles[$path] = $this->toTmpFile($path);
+ }
+ return $this->cachedFiles[$path];
+ }
+
+ protected function removeCachedFile($path) {
+ unset($this->cachedFiles[$path]);
+ }
+
+ /**
+ * @param string $path
+ * @return string
+ */
+ protected function toTmpFile($path) { //no longer in the storage api, still useful here
+ $source = $this->fopen($path, 'r');
+ if (!$source) {
+ return false;
+ }
+ if ($pos = strrpos($path, '.')) {
+ $extension = substr($path, $pos);
+ } else {
+ $extension = '';
+ }
+ $tmpFile = \OC_Helper::tmpFile($extension);
+ $target = fopen($tmpFile, 'w');
+ \OC_Helper::streamCopy($source, $target);
+ fclose($target);
+ return $tmpFile;
+ }
+}
diff --git a/lib/private/files/storage/wrapper/encryption.php b/lib/private/files/storage/wrapper/encryption.php
index 0e70c99c8d7..5245fe4cc45 100644
--- a/lib/private/files/storage/wrapper/encryption.php
+++ b/lib/private/files/storage/wrapper/encryption.php
@@ -24,9 +24,13 @@
namespace OC\Files\Storage\Wrapper;
use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
+use OC\Files\Storage\LocalTempFileTrait;
+use OCP\Files\Mount\IMountPoint;
class Encryption extends Wrapper {
+ use LocalTempFileTrait;
+
/** @var string */
private $mountPoint;
@@ -45,11 +49,18 @@ class Encryption extends Wrapper {
/** @var array */
private $unencryptedSize;
+ /** @var \OC\Encryption\File */
+ private $fileHelper;
+
+ /** @var IMountPoint */
+ private $mount;
+
/**
* @param array $parameters
* @param \OC\Encryption\Manager $encryptionManager
* @param \OC\Encryption\Util $util
* @param \OC\Log $logger
+ * @param \OC\Encryption\File $fileHelper
* @param string $uid user who perform the read/write operation (null for public access)
*/
public function __construct(
@@ -57,14 +68,17 @@ class Encryption extends Wrapper {
\OC\Encryption\Manager $encryptionManager = null,
\OC\Encryption\Util $util = null,
\OC\Log $logger = null,
+ \OC\Encryption\File $fileHelper = null,
$uid = null
) {
$this->mountPoint = $parameters['mountPoint'];
+ $this->mount = $parameters['mount'];
$this->encryptionManager = $encryptionManager;
$this->util = $util;
$this->logger = $logger;
$this->uid = $uid;
+ $this->fileHelper = $fileHelper;
$this->unencryptedSize = array();
parent::__construct($parameters);
}
@@ -77,27 +91,18 @@ class Encryption extends Wrapper {
* @return int
*/
public function filesize($path) {
- $size = 0;
$fullPath = $this->getFullPath($path);
-
- $encryptedSize = $this->storage->filesize($path);
+ $size = $this->storage->filesize($path);
$info = $this->getCache()->get($path);
- if($encryptedSize > 0 && $info['encrypted']) {
- $size = $info['unencrypted_size'];
- if ($size <= 0) {
- $encryptionModule = $this->getEncryptionModule($path);
- if ($encryptionModule) {
- $size = $encryptionModule->calculateUnencryptedSize($fullPath);
- $this->getCache()->update($info['fileid'], array('unencrypted_size' => $size));
- }
- }
- } else if (isset($this->unencryptedSize[$fullPath]) && isset($info['fileid'])) {
+ if (isset($this->unencryptedSize[$fullPath])) {
$size = $this->unencryptedSize[$fullPath];
+ }
+
+ if (isset($info['fileid'])) {
$info['encrypted'] = true;
- $info['unencrypted_size'] = $size;
- $info['size'] = $encryptedSize;
+ $info['size'] = $size;
$this->getCache()->put($path, $info);
}
@@ -112,23 +117,18 @@ class Encryption extends Wrapper {
*/
public function file_get_contents($path) {
- $data = null;
$encryptionModule = $this->getEncryptionModule($path);
if ($encryptionModule) {
-
- $handle = $this->fopen($path, 'r');
-
- if (is_resource($handle)) {
- while (!feof($handle)) {
- $data .= fread($handle, $this->util->getBlockSize());
- }
+ $handle = $this->fopen($path, "r");
+ if (!$handle) {
+ return false;
}
- } else {
- $data = $this->storage->file_get_contents($path);
+ $data = stream_get_contents($handle);
+ fclose($handle);
+ return $data;
}
-
- return $data;
+ return $this->storage->file_get_contents($path);
}
/**
@@ -141,8 +141,9 @@ class Encryption extends Wrapper {
public function file_put_contents($path, $data) {
// file put content will always be translated to a stream write
$handle = $this->fopen($path, 'w');
- fwrite($handle, $data);
- return fclose($handle);
+ $written = fwrite($handle, $data);
+ fclose($handle);
+ return $written;
}
/**
@@ -158,8 +159,8 @@ class Encryption extends Wrapper {
$encryptionModule = $this->getEncryptionModule($path);
if ($encryptionModule) {
- $keyStorage = \OC::$server->getEncryptionKeyStorage($encryptionModule->getId());
- $keyStorage->deleteAllFileKeys($this->getFullPath($path));
+ $keyStorage = $this->getKeyStorage($encryptionModule->getId());
+ $keyStorage->deleteAllFileKeys($this->getFullPath($path));
}
return $this->storage->unlink($path);
@@ -177,17 +178,14 @@ class Encryption extends Wrapper {
return $this->storage->rename($path1, $path2);
}
- $fullPath1 = $this->getFullPath($path1);
- list($owner, $source) = $this->util->getUidAndFilename($fullPath1);
+ $source = $this->getFullPath($path1);
$result = $this->storage->rename($path1, $path2);
if ($result) {
- $fullPath2 = $this->getFullPath($path2);
- $systemWide = $this->util->isSystemWideMountPoint($this->mountPoint);
- list(, $target) = $this->util->getUidAndFilename($fullPath2);
+ $target = $this->getFullPath($path2);
$encryptionModule = $this->getEncryptionModule($path2);
if ($encryptionModule) {
- $keyStorage = \OC::$server->getEncryptionKeyStorage($encryptionModule->getId());
- $keyStorage->renameKeys($source, $target, $owner, $systemWide);
+ $keyStorage = $this->getKeyStorage($encryptionModule->getId());
+ $keyStorage->renameKeys($source, $target);
}
}
@@ -202,9 +200,22 @@ class Encryption extends Wrapper {
* @return bool
*/
public function copy($path1, $path2) {
- // todo copy encryption keys, get users with access to the file and reencrypt
- // or is this to encryption module specific? Then we can hand this over
- return $this->storage->copy($path1, $path2);
+ if ($this->util->isExcluded($path1)) {
+ return $this->storage->rename($path1, $path2);
+ }
+
+ $source = $this->getFullPath($path1);
+ $result = $this->storage->copy($path1, $path2);
+ if ($result) {
+ $target = $this->getFullPath($path2);
+ $encryptionModule = $this->getEncryptionModule($path2);
+ if ($encryptionModule) {
+ $keyStorage = $this->getKeyStorage($encryptionModule->getId());
+ $keyStorage->copyKeys($source, $target);
+ }
+ }
+
+ return $result;
}
/**
@@ -223,7 +234,17 @@ class Encryption extends Wrapper {
$encryptionModuleId = $this->util->getEncryptionModuleId($header);
$size = $unencryptedSize = 0;
- if ($this->file_exists($path)) {
+ $targetExists = $this->file_exists($path);
+ $targetIsEncrypted = false;
+ if ($targetExists) {
+ // in case the file exists we require the explicit module as
+ // specified in the file header - otherwise we need to fail hard to
+ // prevent data loss on client side
+ if (!empty($encryptionModuleId)) {
+ $targetIsEncrypted = true;
+ $encryptionModule = $this->encryptionManager->getEncryptionModule($encryptionModuleId);
+ }
+
$size = $this->storage->filesize($path);
$unencryptedSize = $this->filesize($path);
}
@@ -254,10 +275,18 @@ class Encryption extends Wrapper {
'" not found, file will be stored unencrypted');
}
+ // encryption disabled on write of new file and write to existing unencrypted file -> don't encrypt
+ $encEnabled = $this->encryptionManager->isEnabled();
+ if (!$encEnabled || !$this->mount->getOption('encrypt', true)) {
+ if (!$targetExists || !$targetIsEncrypted) {
+ $shouldEncrypt = false;
+ }
+ }
+
if($shouldEncrypt === true && !$this->util->isExcluded($fullPath) && $encryptionModule !== null) {
$source = $this->storage->fopen($path, $mode);
$handle = \OC\Files\Stream\Encryption::wrap($source, $path, $fullPath, $header,
- $this->uid, $encryptionModule, $this->storage, $this, $this->util, $mode,
+ $this->uid, $encryptionModule, $this->storage, $this, $this->util, $this->fileHelper, $mode,
$size, $unencryptedSize);
return $handle;
} else {
@@ -266,6 +295,57 @@ class Encryption extends Wrapper {
}
/**
+ * get the path to a local version of the file.
+ * The local version of the file can be temporary and doesn't have to be persistent across requests
+ *
+ * @param string $path
+ * @return string
+ */
+ public function getLocalFile($path) {
+ return $this->getCachedFile($path);
+ }
+
+ /**
+ * Returns the wrapped storage's value for isLocal()
+ *
+ * @return bool wrapped storage's isLocal() value
+ */
+ public function isLocal() {
+ return false;
+ }
+
+ /**
+ * see http://php.net/manual/en/function.stat.php
+ * only the following keys are required in the result: size and mtime
+ *
+ * @param string $path
+ * @return array
+ */
+ public function stat($path) {
+ $stat = $this->storage->stat($path);
+ $fileSize = $this->filesize($path);
+ $stat['size'] = $fileSize;
+ $stat[7] = $fileSize;
+ return $stat;
+ }
+
+ /**
+ * see http://php.net/manual/en/function.hash.php
+ *
+ * @param string $type
+ * @param string $path
+ * @param bool $raw
+ * @return string
+ */
+ public function hash($type, $path, $raw = false) {
+ $fh = $this->fopen($path, 'rb');
+ $ctx = hash_init($type);
+ hash_update_stream($ctx, $fh);
+ fclose($fh);
+ return hash_final($ctx, $raw);
+ }
+
+ /**
* return full path, including mount point
*
* @param string $path relative to mount point
@@ -295,7 +375,9 @@ class Encryption extends Wrapper {
* read encryption module needed to read/write the file located at $path
*
* @param string $path
- * @return \OCP\Encryption\IEncryptionModule|null
+ * @return null|\OCP\Encryption\IEncryptionModule
+ * @throws ModuleDoesNotExistsException
+ * @throws \Exception
*/
protected function getEncryptionModule($path) {
$encryptionModule = null;
@@ -305,7 +387,7 @@ class Encryption extends Wrapper {
try {
$encryptionModule = $this->encryptionManager->getEncryptionModule($encryptionModuleId);
} catch (ModuleDoesNotExistsException $e) {
- $this->logger->critical('Encryption module defined in "' . $path . '" mot loaded!');
+ $this->logger->critical('Encryption module defined in "' . $path . '" not loaded!');
throw $e;
}
}
@@ -316,4 +398,13 @@ class Encryption extends Wrapper {
$this->unencryptedSize[$path] = $unencryptedSize;
}
+ /**
+ * @param string $encryptionModuleId
+ * @return \OCP\Encryption\Keys\IStorage
+ */
+ protected function getKeyStorage($encryptionModuleId) {
+ $keyStorage = \OC::$server->getEncryptionKeyStorage($encryptionModuleId);
+ return $keyStorage;
+ }
+
}
diff --git a/lib/private/files/storage/wrapper/quota.php b/lib/private/files/storage/wrapper/quota.php
index 34bd2589947..3c0fda98dad 100644
--- a/lib/private/files/storage/wrapper/quota.php
+++ b/lib/private/files/storage/wrapper/quota.php
@@ -60,11 +60,6 @@ class Quota extends Wrapper {
$cache = $this->getCache();
$data = $cache->get($path);
if (is_array($data) and isset($data['size'])) {
- if (isset($data['unencrypted_size'])
- && $data['unencrypted_size'] > 0
- ) {
- return $data['unencrypted_size'];
- }
return $data['size'];
} else {
return \OCP\Files\FileInfo::SPACE_NOT_COMPUTED;
diff --git a/lib/private/files/stream/encryption.php b/lib/private/files/stream/encryption.php
index ddef9067bad..b4e06c99943 100644
--- a/lib/private/files/stream/encryption.php
+++ b/lib/private/files/stream/encryption.php
@@ -31,6 +31,9 @@ class Encryption extends Wrapper {
/** @var \OC\Encryption\Util */
protected $util;
+ /** @var \OC\Encryption\File */
+ protected $file;
+
/** @var \OCP\Encryption\IEncryptionModule */
protected $encryptionModule;
@@ -43,6 +46,9 @@ class Encryption extends Wrapper {
/** @var string */
protected $internalPath;
+ /** @var string */
+ protected $cache;
+
/** @var integer */
protected $size;
@@ -72,13 +78,16 @@ class Encryption extends Wrapper {
/**
* user who perform the read/write operation null for public access
*
- * @var string
+ * @var string
*/
protected $uid;
/** @var bool */
protected $readOnly;
+ /** @var bool */
+ protected $writeFlag;
+
/** @var array */
protected $expectedContextProperties;
@@ -91,6 +100,7 @@ class Encryption extends Wrapper {
'encryptionModule',
'header',
'uid',
+ 'file',
'util',
'size',
'unencryptedSize',
@@ -106,11 +116,12 @@ class Encryption extends Wrapper {
* @param string $internalPath relative to mount point
* @param string $fullPath relative to data/
* @param array $header
- * @param sting $uid
+ * @param string $uid
* @param \OCP\Encryption\IEncryptionModule $encryptionModule
* @param \OC\Files\Storage\Storage $storage
- * @param OC\Files\Storage\Wrapper\Encryption $encStorage
+ * @param \OC\Files\Storage\Wrapper\Encryption $encStorage
* @param \OC\Encryption\Util $util
+ * @param \OC\Encryption\File $file
* @param string $mode
* @param int $size
* @param int $unencryptedSize
@@ -119,9 +130,15 @@ class Encryption extends Wrapper {
* @throws \BadMethodCallException
*/
public static function wrap($source, $internalPath, $fullPath, array $header,
- $uid, \OCP\Encryption\IEncryptionModule $encryptionModule,
- \OC\Files\Storage\Storage $storage, \OC\Files\Storage\Wrapper\Encryption $encStorage,
- \OC\Encryption\Util $util, $mode, $size, $unencryptedSize) {
+ $uid,
+ \OCP\Encryption\IEncryptionModule $encryptionModule,
+ \OC\Files\Storage\Storage $storage,
+ \OC\Files\Storage\Wrapper\Encryption $encStorage,
+ \OC\Encryption\Util $util,
+ \OC\Encryption\File $file,
+ $mode,
+ $size,
+ $unencryptedSize) {
$context = stream_context_create(array(
'ocencryption' => array(
@@ -133,6 +150,7 @@ class Encryption extends Wrapper {
'header' => $header,
'uid' => $uid,
'util' => $util,
+ 'file' => $file,
'size' => $size,
'unencryptedSize' => $unencryptedSize,
'encryptionStorage' => $encStorage
@@ -180,7 +198,7 @@ class Encryption extends Wrapper {
$context = parent::loadContext($name);
foreach ($this->expectedContextProperties as $property) {
- if (isset($context[$property])) {
+ if (array_key_exists($property, $context)) {
$this->{$property} = $context[$property];
} else {
throw new \BadMethodCallException('Invalid context, "' . $property . '" options not set');
@@ -194,6 +212,8 @@ class Encryption extends Wrapper {
$this->loadContext('ocencryption');
$this->position = 0;
+ $this->cache = '';
+ $this->writeFlag = false;
$this->unencryptedBlockSize = $this->encryptionModule->getUnencryptedBlockSize();
if (
@@ -216,7 +236,7 @@ class Encryption extends Wrapper {
$sharePath = dirname($path);
}
- $accessList = $this->util->getSharingUsersArray($sharePath);
+ $accessList = $this->file->getAccessList($sharePath);
$this->newHeader = $this->encryptionModule->begin($this->fullPath, $this->uid, $this->header, $accessList);
return true;
@@ -228,25 +248,26 @@ class Encryption extends Wrapper {
$result = '';
// skip the header if we read the file from the beginning
- if ($this->position === 0 && !empty($this->header)) {
- parent::stream_read($this->util->getBlockSize());
+ if ($this->position === 0) {
+ parent::stream_read($this->util->getHeaderSize());
}
+// $count = min($count, $this->unencryptedSize - $this->position);
while ($count > 0) {
$remainingLength = $count;
// update the cache of the current block
- $data = parent::stream_read($this->util->getBlockSize());
- $decrypted = $this->encryptionModule->decrypt($data);
+ $this->readCache();
// determine the relative position in the current block
$blockPosition = ($this->position % $this->unencryptedBlockSize);
// if entire read inside current block then only position needs to be updated
if ($remainingLength < ($this->unencryptedBlockSize - $blockPosition)) {
- $result .= substr($decrypted, $blockPosition, $remainingLength);
+ $result .= substr($this->cache, $blockPosition, $remainingLength);
$this->position += $remainingLength;
$count = 0;
- // otherwise remainder of current block is fetched, the block is flushed and the position updated
+ // otherwise remainder of current block is fetched, the block is flushed and the position updated
} else {
- $result .= substr($decrypted, $blockPosition);
+ $result .= substr($this->cache, $blockPosition);
+ $this->flush();
$this->position += ($this->unencryptedBlockSize - $blockPosition);
$count -= ($this->unencryptedBlockSize - $blockPosition);
}
@@ -259,6 +280,7 @@ class Encryption extends Wrapper {
if ($this->position === 0) {
$this->writeHeader();
+ $this->size+=$this->util->getHeaderSize();
}
$length = 0;
@@ -266,9 +288,8 @@ class Encryption extends Wrapper {
while (strlen($data) > 0) {
$remainingLength = strlen($data);
- // read current block
- $currentBlock = parent::stream_read($this->util->getBlockSize());
- $decrypted = $this->encryptionModule->decrypt($currentBlock, $this->uid);
+ // set the cache to the current 6126 block
+ $this->readCache();
// for seekable streams the pointer is moved back to the beginning of the encrypted block
// flush will start writing there when the position moves to another block
@@ -277,7 +298,10 @@ class Encryption extends Wrapper {
$resultFseek = parent::stream_seek($positionInFile);
// only allow writes on seekable streams, or at the end of the encrypted stream
- if ($resultFseek || $positionInFile === $this->size) {
+ if (!($this->readOnly) && ($resultFseek || $positionInFile === $this->size)) {
+
+ // switch the writeFlag so flush() will write the block
+ $this->writeFlag = true;
// determine the relative position in the current block
$blockPosition = ($this->position % $this->unencryptedBlockSize);
@@ -285,28 +309,22 @@ class Encryption extends Wrapper {
// if so, overwrite existing data (if any)
// update position and liberate $data
if ($remainingLength < ($this->unencryptedBlockSize - $blockPosition)) {
- $decrypted = substr($decrypted, 0, $blockPosition)
- . $data . substr($decrypted, $blockPosition + $remainingLength);
- $encrypted = $this->encryptionModule->encrypt($decrypted);
- parent::stream_write($encrypted);
+ $this->cache = substr($this->cache, 0, $blockPosition)
+ . $data . substr($this->cache, $blockPosition + $remainingLength);
$this->position += $remainingLength;
$length += $remainingLength;
$data = '';
- // if $data doens't fit the current block, the fill the current block and reiterate
- // after the block is filled, it is flushed and $data is updatedxxx
+ // if $data doesn't fit the current block, the fill the current block and reiterate
+ // after the block is filled, it is flushed and $data is updatedxxx
} else {
- $decrypted = substr($decrypted, 0, $blockPosition) .
+ $this->cache = substr($this->cache, 0, $blockPosition) .
substr($data, 0, $this->unencryptedBlockSize - $blockPosition);
- $encrypted = $this->encryptionModule->encrypt($decrypted);
- parent::stream_write($encrypted);
+ $this->flush();
$this->position += ($this->unencryptedBlockSize - $blockPosition);
- $this->size = max($this->size, $this->stream_tell());
$length += ($this->unencryptedBlockSize - $blockPosition);
$data = substr($data, $this->unencryptedBlockSize - $blockPosition);
}
} else {
- $encrypted = $this->encryptionModule->encrypt($data);
- parent::stream_write($encrypted);
$data = '';
}
}
@@ -345,7 +363,11 @@ class Encryption extends Wrapper {
$newFilePosition = floor($newPosition / $this->unencryptedBlockSize)
* $this->util->getBlockSize() + $this->util->getHeaderSize();
+ $oldFilePosition = parent::stream_tell();
if (parent::stream_seek($newFilePosition)) {
+ parent::stream_seek($oldFilePosition);
+ $this->flush();
+ parent::stream_seek($newFilePosition);
$this->position = $newPosition;
$return = true;
}
@@ -355,13 +377,6 @@ class Encryption extends Wrapper {
public function stream_close() {
$this->flush();
- return parent::stream_close();
- }
-
- /**
- * tell encryption module that we are done and write remaining data to the file
- */
- protected function flush() {
$remainingData = $this->encryptionModule->end($this->fullPath);
if ($this->readOnly === false) {
if(!empty($remainingData)) {
@@ -369,17 +384,50 @@ class Encryption extends Wrapper {
}
$this->encryptionStorage->updateUnencryptedSize($this->fullPath, $this->unencryptedSize);
}
+ return parent::stream_close();
}
+ /**
+ * write block to file
+ */
+ protected function flush() {
+ // write to disk only when writeFlag was set to 1
+ if ($this->writeFlag) {
+ // Disable the file proxies so that encryption is not
+ // automatically attempted when the file is written to disk -
+ // we are handling that separately here and we don't want to
+ // get into an infinite loop
+ $encrypted = $this->encryptionModule->encrypt($this->cache);
+ parent::stream_write($encrypted);
+ $this->writeFlag = false;
+ $this->size = max($this->size, parent::stream_tell());
+ }
+ // always empty the cache (otherwise readCache() will not fill it with the new block)
+ $this->cache = '';
+ }
+
+ /**
+ * read block to file
+ */
+ protected function readCache() {
+ // cache should always be empty string when this function is called
+ // don't try to fill the cache when trying to write at the end of the unencrypted file when it coincides with new block
+ if ($this->cache === '' && !($this->position === $this->unencryptedSize && ($this->position % $this->unencryptedBlockSize) === 0)) {
+ // Get the data from the file handle
+ $data = parent::stream_read($this->util->getBlockSize());
+ $this->cache = $this->encryptionModule->decrypt($data);
+ }
+ }
/**
* write header at beginning of encrypted file
*
+ * @return integer
* @throws EncryptionHeaderKeyExistsException if header key is already in use
*/
private function writeHeader() {
$header = $this->util->createHeader($this->newHeader, $this->encryptionModule);
- parent::stream_write($header);
+ return parent::stream_write($header);
}
}
diff --git a/lib/private/files/view.php b/lib/private/files/view.php
index f8ec4a0eb43..0f371bbc5ea 100644
--- a/lib/private/files/view.php
+++ b/lib/private/files/view.php
@@ -515,8 +515,7 @@ class View {
public function file_put_contents($path, $data) {
if (is_resource($data)) { //not having to deal with streams in file_put_contents makes life easier
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
- if (\OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data)
- and Filesystem::isValidPath($path)
+ if (Filesystem::isValidPath($path)
and !Filesystem::isFileBlacklisted($path)
) {
$path = $this->getRelativePath($absolutePath);
@@ -537,7 +536,6 @@ class View {
if ($this->shouldEmitHooks($path) && $result !== false) {
$this->emit_file_hooks_post($exists, $path);
}
- \OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count);
return $result;
} else {
return false;
@@ -591,8 +589,7 @@ class View {
$absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1));
$absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2));
if (
- \OC_FileProxy::runPreProxies('rename', $absolutePath1, $absolutePath2)
- and Filesystem::isValidPath($path2)
+ Filesystem::isValidPath($path2)
and Filesystem::isValidPath($path1)
and !Filesystem::isFileBlacklisted($path2)
) {
@@ -635,14 +632,12 @@ class View {
$sourceMountPoint = $mount->getMountPoint();
$result = $mount->moveMount($absolutePath2);
$manager->moveMount($sourceMountPoint, $mount->getMountPoint());
- \OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2);
} else {
$result = false;
}
} elseif ($mp1 == $mp2) {
if ($storage1) {
$result = $storage1->rename($internalPath1, $internalPath2);
- \OC_FileProxy::runPostProxies('rename', $absolutePath1, $absolutePath2);
} else {
$result = false;
}
@@ -718,8 +713,7 @@ class View {
$absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1));
$absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2));
if (
- \OC_FileProxy::runPreProxies('copy', $absolutePath1, $absolutePath2)
- and Filesystem::isValidPath($path2)
+ Filesystem::isValidPath($path2)
and Filesystem::isValidPath($path1)
and !Filesystem::isFileBlacklisted($path2)
) {
@@ -927,7 +921,7 @@ class View {
public function hash($type, $path, $raw = false) {
$postFix = (substr($path, -1, 1) === '/') ? '/' : '';
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
- if (\OC_FileProxy::runPreProxies('hash', $absolutePath) && Filesystem::isValidPath($path)) {
+ if (Filesystem::isValidPath($path)) {
$path = $this->getRelativePath($absolutePath);
if ($path == null) {
return false;
@@ -942,7 +936,6 @@ class View {
list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
if ($storage) {
$result = $storage->hash($type, $internalPath, $raw);
- $result = \OC_FileProxy::runPostProxies('hash', $absolutePath, $result);
return $result;
}
}
@@ -975,8 +968,7 @@ class View {
private function basicOperation($operation, $path, $hooks = array(), $extraParam = null) {
$postFix = (substr($path, -1, 1) === '/') ? '/' : '';
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
- if (\OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam)
- and Filesystem::isValidPath($path)
+ if (Filesystem::isValidPath($path)
and !Filesystem::isFileBlacklisted($path)
) {
$path = $this->getRelativePath($absolutePath);
@@ -993,8 +985,6 @@ class View {
$result = $storage->$operation($internalPath);
}
- $result = \OC_FileProxy::runPostProxies($operation, $this->getAbsolutePath($path), $result);
-
if (in_array('delete', $hooks) and $result) {
$this->updater->remove($path);
}
@@ -1168,8 +1158,6 @@ class View {
$data['permissions'] |= \OCP\Constants::PERMISSION_DELETE;
}
- $data = \OC_FileProxy::runPostProxies('getFileInfo', $path, $data);
-
return new FileInfo($path, $storage, $internalPath, $data, $mount);
}