summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/base.php27
-rw-r--r--lib/private/app.php2
-rw-r--r--lib/private/cache/file.php9
-rw-r--r--lib/private/connector/sabre/file.php140
-rw-r--r--lib/private/encryption/exceptions/decryptionfailedexception.php29
-rw-r--r--lib/private/encryption/exceptions/emptyencryptiondataexception.php29
-rw-r--r--lib/private/encryption/exceptions/encryptionfailedexception.php29
-rw-r--r--lib/private/encryption/exceptions/encryptionheaderkeyexistsexception.php11
-rw-r--r--lib/private/encryption/exceptions/encryptionheadertolargeexception.php33
-rw-r--r--lib/private/encryption/exceptions/modulealreadyexistsexception.php12
-rw-r--r--lib/private/encryption/exceptions/moduledoesnotexistsexception.php4
-rw-r--r--lib/private/encryption/exceptions/unknowncipherexception.php29
-rw-r--r--lib/private/encryption/file.php79
-rw-r--r--lib/private/encryption/keys/storage.php43
-rw-r--r--lib/private/encryption/manager.php53
-rw-r--r--lib/private/encryption/update.php46
-rw-r--r--lib/private/encryption/util.php149
-rw-r--r--lib/private/filechunking.php4
-rw-r--r--lib/private/fileproxy.php138
-rw-r--r--lib/private/files.php2
-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
-rw-r--r--lib/private/hook.php52
-rw-r--r--lib/private/server.php26
-rw-r--r--lib/private/share/share.php2
-rw-r--r--lib/private/util.php45
-rw-r--r--lib/public/encryption/exceptions/genericencryptionexception.php34
-rw-r--r--lib/public/encryption/ifile.php36
-rw-r--r--lib/public/encryption/imanager.php4
-rw-r--r--lib/public/encryption/keys/istorage.php16
-rw-r--r--lib/public/iservercontainer.php25
-rw-r--r--lib/public/util.php17
39 files changed, 979 insertions, 658 deletions
diff --git a/lib/base.php b/lib/base.php
index 98da75b61a8..be397e52449 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -701,23 +701,7 @@ class OC {
}
private static function registerEncryptionWrapper() {
- $enabled = self::$server->getEncryptionManager()->isEnabled();
- if ($enabled) {
- \OC\Files\Filesystem::addStorageWrapper('oc_encryption', function ($mountPoint, $storage, \OCP\Files\Mount\IMountPoint $mount) {
- if($mount->getOption('encrypt', true)) {
- $parameters = array('storage' => $storage, 'mountPoint' => $mountPoint);
- $manager = \OC::$server->getEncryptionManager();
- $util = new \OC\Encryption\Util(new \OC\Files\View(), \OC::$server->getUserManager());
- $user = \OC::$server->getUserSession()->getUser();
- $logger = \OC::$server->getLogger();
- $uid = $user ? $user->getUID() : null;
- return new \OC\Files\Storage\Wrapper\Encryption($parameters, $manager, $util, $logger, $uid);
- } else {
- return $storage;
- }
- });
- }
-
+ \OCP\Util::connectHook('OC_Filesystem', 'setup', 'OC\Encryption\Manager', 'setupStorage');
}
private static function registerEncryptionHooks() {
@@ -730,16 +714,17 @@ class OC {
}
$updater = new \OC\Encryption\Update(
new \OC\Files\View(),
- new \OC\Encryption\Util(new \OC\Files\View(), \OC::$server->getUserManager()),
+ new \OC\Encryption\Util(
+ new \OC\Files\View(),
+ \OC::$server->getUserManager(),
+ \OC::$server->getConfig()),
\OC\Files\Filesystem::getMountManager(),
\OC::$server->getEncryptionManager(),
+ \OC::$server->getEncryptionFilesHelper(),
$uid
);
\OCP\Util::connectHook('OCP\Share', 'post_shared', $updater, 'postShared');
\OCP\Util::connectHook('OCP\Share', 'post_unshare', $updater, 'postUnshared');
-
- //\OCP\Util::connectHook('OC_Filesystem', 'post_umount', 'OCA\Files_Encryption\Hooks', 'postUnmount');
- //\OCP\Util::connectHook('OC_Filesystem', 'umount', 'OCA\Files_Encryption\Hooks', 'preUnmount');
}
}
diff --git a/lib/private/app.php b/lib/private/app.php
index 84bc23608fb..4b3d4b82b82 100644
--- a/lib/private/app.php
+++ b/lib/private/app.php
@@ -207,7 +207,7 @@ class OC_App {
self::$shippedApps = json_decode(file_get_contents($shippedJson), true);
self::$shippedApps = self::$shippedApps['shippedApps'];
} else {
- self::$shippedApps = ['files', 'files_encryption', 'files_external',
+ self::$shippedApps = ['files', 'encryption', 'files_external',
'files_sharing', 'files_trashbin', 'files_versions', 'provisioning_api',
'user_ldap', 'user_webdavauth'];
}
diff --git a/lib/private/cache/file.php b/lib/private/cache/file.php
index 8874acbb1e5..c70698eb7f8 100644
--- a/lib/private/cache/file.php
+++ b/lib/private/cache/file.php
@@ -67,13 +67,10 @@ class File {
*/
public function get($key) {
$result = null;
- $proxyStatus = \OC_FileProxy::$enabled;
- \OC_FileProxy::$enabled = false;
if ($this->hasKey($key)) {
$storage = $this->getStorage();
$result = $storage->file_get_contents($key);
}
- \OC_FileProxy::$enabled = $proxyStatus;
return $result;
}
@@ -85,13 +82,10 @@ class File {
*/
public function size($key) {
$result = 0;
- $proxyStatus = \OC_FileProxy::$enabled;
- \OC_FileProxy::$enabled = false;
if ($this->hasKey($key)) {
$storage = $this->getStorage();
$result = $storage->filesize($key);
}
- \OC_FileProxy::$enabled = $proxyStatus;
return $result;
}
@@ -101,7 +95,6 @@ class File {
public function set($key, $value, $ttl = 0) {
$storage = $this->getStorage();
$result = false;
- $proxyStatus = \OC_FileProxy::$enabled;
// unique id to avoid chunk collision, just in case
$uniqueId = \OC::$server->getSecureRandom()->getLowStrengthGenerator()->generate(
16,
@@ -111,7 +104,6 @@ class File {
// use part file to prevent hasKey() to find the key
// while it is being written
$keyPart = $key . '.' . $uniqueId . '.part';
- \OC_FileProxy::$enabled = false;
if ($storage and $storage->file_put_contents($keyPart, $value)) {
if ($ttl === 0) {
$ttl = 86400; // 60*60*24
@@ -119,7 +111,6 @@ class File {
$result = $storage->touch($keyPart, time() + $ttl);
$result &= $storage->rename($keyPart, $key);
}
- \OC_FileProxy::$enabled = $proxyStatus;
return $result;
}
diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php
index 4fbcb732688..b4acaa15073 100644
--- a/lib/private/connector/sabre/file.php
+++ b/lib/private/connector/sabre/file.php
@@ -35,7 +35,24 @@
namespace OC\Connector\Sabre;
-class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
+use OC\Connector\Sabre\Exception\EntityTooLarge;
+use OC\Connector\Sabre\Exception\FileLocked;
+use OC\Connector\Sabre\Exception\UnsupportedMediaType;
+use OCP\Encryption\Exceptions\GenericEncryptionException;
+use OCP\Files\EntityTooLargeException;
+use OCP\Files\InvalidContentException;
+use OCP\Files\InvalidPathException;
+use OCP\Files\LockNotAcquiredException;
+use OCP\Files\NotPermittedException;
+use OCP\Files\StorageNotAvailableException;
+use Sabre\DAV\Exception;
+use Sabre\DAV\Exception\BadRequest;
+use Sabre\DAV\Exception\Forbidden;
+use Sabre\DAV\Exception\NotImplemented;
+use Sabre\DAV\Exception\ServiceUnavailable;
+use Sabre\DAV\IFile;
+
+class File extends Node implements IFile {
/**
* Updates the data
@@ -56,27 +73,22 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
*
* @param resource $data
*
- * @throws \Sabre\DAV\Exception\Forbidden
- * @throws \OC\Connector\Sabre\Exception\UnsupportedMediaType
- * @throws \Sabre\DAV\Exception\BadRequest
- * @throws \Sabre\DAV\Exception
- * @throws \OC\Connector\Sabre\Exception\EntityTooLarge
- * @throws \Sabre\DAV\Exception\ServiceUnavailable
+ * @throws Forbidden
+ * @throws UnsupportedMediaType
+ * @throws BadRequest
+ * @throws Exception
+ * @throws EntityTooLarge
+ * @throws ServiceUnavailable
* @return string|null
*/
public function put($data) {
try {
if ($this->info && $this->fileView->file_exists($this->path) &&
!$this->info->isUpdateable()) {
- throw new \Sabre\DAV\Exception\Forbidden();
+ throw new Forbidden();
}
- } catch (\OCP\Files\StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable("File is not updatable: ".$e->getMessage());
- }
-
- // throw an exception if encryption was disabled but the files are still encrypted
- if (\OC_Util::encryptedFiles()) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable("Encryption is disabled");
+ } catch (StorageNotAvailableException $e) {
+ throw new ServiceUnavailable("File is not updatable: ".$e->getMessage());
}
// verify path of the target
@@ -104,31 +116,29 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
\OC_Log::write('webdav', '\OC\Files\Filesystem::file_put_contents() failed', \OC_Log::ERROR);
$this->fileView->unlink($partFilePath);
// because we have no clue about the cause we can only throw back a 500/Internal Server Error
- throw new \Sabre\DAV\Exception('Could not write file contents');
+ throw new Exception('Could not write file contents');
}
- } catch (\OCP\Files\NotPermittedException $e) {
+ } catch (NotPermittedException $e) {
// a more general case - due to whatever reason the content could not be written
- throw new \Sabre\DAV\Exception\Forbidden($e->getMessage());
-
- } catch (\OCP\Files\EntityTooLargeException $e) {
+ throw new Forbidden($e->getMessage());
+ } catch (EntityTooLargeException $e) {
// the file is too big to be stored
- throw new \OC\Connector\Sabre\Exception\EntityTooLarge($e->getMessage());
-
- } catch (\OCP\Files\InvalidContentException $e) {
+ throw new EntityTooLarge($e->getMessage());
+ } catch (InvalidContentException $e) {
// the file content is not permitted
- throw new \OC\Connector\Sabre\Exception\UnsupportedMediaType($e->getMessage());
-
- } catch (\OCP\Files\InvalidPathException $e) {
+ throw new UnsupportedMediaType($e->getMessage());
+ } catch (InvalidPathException $e) {
// the path for the file was not valid
// TODO: find proper http status code for this case
- throw new \Sabre\DAV\Exception\Forbidden($e->getMessage());
- } catch (\OCP\Files\LockNotAcquiredException $e) {
+ throw new Forbidden($e->getMessage());
+ } catch (LockNotAcquiredException $e) {
// the file is currently being written to by another process
- throw new \OC\Connector\Sabre\Exception\FileLocked($e->getMessage(), $e->getCode(), $e);
- } catch (\OCA\Files_Encryption\Exception\EncryptionException $e) {
- throw new \Sabre\DAV\Exception\Forbidden($e->getMessage());
- } catch (\OCP\Files\StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable("Failed to write file contents: ".$e->getMessage());
+ throw new FileLocked($e->getMessage(), $e->getCode(), $e);
+ } catch (GenericEncryptionException $e) {
+ // returning 503 will allow retry of the operation at a later point in time
+ throw new ServiceUnavailable("Encryption not ready: " . $e->getMessage());
+ } catch (StorageNotAvailableException $e) {
+ throw new ServiceUnavailable("Failed to write file contents: ".$e->getMessage());
}
try {
@@ -140,7 +150,7 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
$actual = $this->fileView->filesize($partFilePath);
if ($actual != $expected) {
$this->fileView->unlink($partFilePath);
- throw new \Sabre\DAV\Exception\BadRequest('expected filesize ' . $expected . ' got ' . $actual);
+ throw new BadRequest('expected filesize ' . $expected . ' got ' . $actual);
}
}
@@ -152,12 +162,12 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
if ($renameOkay === false || $fileExists === false) {
\OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
$this->fileView->unlink($partFilePath);
- throw new \Sabre\DAV\Exception('Could not rename part file to final file');
+ throw new Exception('Could not rename part file to final file');
}
}
- catch (\OCP\Files\LockNotAcquiredException $e) {
+ catch (LockNotAcquiredException $e) {
// the file is currently being written to by another process
- throw new \OC\Connector\Sabre\Exception\FileLocked($e->getMessage(), $e->getCode(), $e);
+ throw new FileLocked($e->getMessage(), $e->getCode(), $e);
}
}
@@ -169,8 +179,8 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
}
}
$this->refreshInfo();
- } catch (\OCP\Files\StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable("Failed to check file size: ".$e->getMessage());
+ } catch (StorageNotAvailableException $e) {
+ throw new ServiceUnavailable("Failed to check file size: ".$e->getMessage());
}
return '"' . $this->info->getEtag() . '"';
@@ -179,43 +189,39 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
/**
* Returns the data
* @return string|resource
- * @throws \Sabre\DAV\Exception\Forbidden
- * @throws \Sabre\DAV\Exception\ServiceUnavailable
+ * @throws Forbidden
+ * @throws ServiceUnavailable
*/
public function get() {
//throw exception if encryption is disabled but files are still encrypted
- if (\OC_Util::encryptedFiles()) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable("Encryption is disabled");
- } else {
- try {
- return $this->fileView->fopen(ltrim($this->path, '/'), 'rb');
- } catch (\OCA\Files_Encryption\Exception\EncryptionException $e) {
- throw new \Sabre\DAV\Exception\Forbidden($e->getMessage());
- } catch (\OCP\Files\StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable("Failed to open file: ".$e->getMessage());
- }
+ try {
+ return $this->fileView->fopen(ltrim($this->path, '/'), 'rb');
+ } catch (GenericEncryptionException $e) {
+ // returning 503 will allow retry of the operation at a later point in time
+ throw new ServiceUnavailable("Encryption not ready: " . $e->getMessage());
+ } catch (StorageNotAvailableException $e) {
+ throw new ServiceUnavailable("Failed to open file: ".$e->getMessage());
}
-
}
/**
* Delete the current file
- * @throws \Sabre\DAV\Exception\Forbidden
- * @throws \Sabre\DAV\Exception\ServiceUnavailable
+ * @throws Forbidden
+ * @throws ServiceUnavailable
*/
public function delete() {
if (!$this->info->isDeletable()) {
- throw new \Sabre\DAV\Exception\Forbidden();
+ throw new Forbidden();
}
try {
if (!$this->fileView->unlink($this->path)) {
// assume it wasn't possible to delete due to permissions
- throw new \Sabre\DAV\Exception\Forbidden();
+ throw new Forbidden();
}
- } catch (\OCP\Files\StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable("Failed to unlink: ".$e->getMessage());
+ } catch (StorageNotAvailableException $e) {
+ throw new ServiceUnavailable("Failed to unlink: ".$e->getMessage());
}
}
@@ -255,10 +261,10 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
/**
* @param resource $data
* @return null|string
- * @throws \Sabre\DAV\Exception
- * @throws \Sabre\DAV\Exception\BadRequest
- * @throws \Sabre\DAV\Exception\NotImplemented
- * @throws \Sabre\DAV\Exception\ServiceUnavailable
+ * @throws Exception
+ * @throws BadRequest
+ * @throws NotImplemented
+ * @throws ServiceUnavailable
*/
private function createFileChunked($data)
{
@@ -266,7 +272,7 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
$info = \OC_FileChunking::decodeName($name);
if (empty($info)) {
- throw new \Sabre\DAV\Exception\NotImplemented();
+ throw new NotImplemented();
}
$chunk_handler = new \OC_FileChunking($info);
$bytesWritten = $chunk_handler->store($info['index'], $data);
@@ -277,7 +283,7 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
$expected = $_SERVER['CONTENT_LENGTH'];
if ($bytesWritten != $expected) {
$chunk_handler->remove($info['index']);
- throw new \Sabre\DAV\Exception\BadRequest(
+ throw new BadRequest(
'expected filesize ' . $expected . ' got ' . $bytesWritten);
}
}
@@ -303,7 +309,7 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
if ($fileExists) {
$this->fileView->unlink($targetPath);
}
- throw new \Sabre\DAV\Exception('Could not rename part file assembled from chunks');
+ throw new Exception('Could not rename part file assembled from chunks');
}
} else {
// assemble directly into the final file
@@ -320,8 +326,8 @@ class File extends \OC\Connector\Sabre\Node implements \Sabre\DAV\IFile {
$info = $this->fileView->getFileInfo($targetPath);
return $info->getEtag();
- } catch (\OCP\Files\StorageNotAvailableException $e) {
- throw new \Sabre\DAV\Exception\ServiceUnavailable("Failed to put file: ".$e->getMessage());
+ } catch (StorageNotAvailableException $e) {
+ throw new ServiceUnavailable("Failed to put file: ".$e->getMessage());
}
}
diff --git a/lib/private/encryption/exceptions/decryptionfailedexception.php b/lib/private/encryption/exceptions/decryptionfailedexception.php
new file mode 100644
index 00000000000..f8b4fdf07fa
--- /dev/null
+++ b/lib/private/encryption/exceptions/decryptionfailedexception.php
@@ -0,0 +1,29 @@
+<?php
+ /**
+ * @author Clark Tomlinson <clark@owncloud.com>
+ * @since 2/25/15, 9:38 AM
+ * @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\Encryption\Exceptions;
+
+use OCP\Encryption\Exceptions\GenericEncryptionException;
+
+class DecryptionFailedException extends GenericEncryptionException {
+
+}
diff --git a/lib/private/encryption/exceptions/emptyencryptiondataexception.php b/lib/private/encryption/exceptions/emptyencryptiondataexception.php
new file mode 100644
index 00000000000..d3dc9230047
--- /dev/null
+++ b/lib/private/encryption/exceptions/emptyencryptiondataexception.php
@@ -0,0 +1,29 @@
+<?php
+ /**
+ * @author Clark Tomlinson <clark@owncloud.com>
+ * @since 2/25/15, 9:38 AM
+ * @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\Encryption\Exceptions;
+
+use OCP\Encryption\Exceptions\GenericEncryptionException;
+
+class EmptyEncryptionDataException extends GenericEncryptionException{
+
+}
diff --git a/lib/private/encryption/exceptions/encryptionfailedexception.php b/lib/private/encryption/exceptions/encryptionfailedexception.php
new file mode 100644
index 00000000000..ac489c73254
--- /dev/null
+++ b/lib/private/encryption/exceptions/encryptionfailedexception.php
@@ -0,0 +1,29 @@
+<?php
+ /**
+ * @author Clark Tomlinson <clark@owncloud.com>
+ * @since 2/25/15, 9:37 AM
+ * @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\Encryption\Exceptions;
+
+use OCP\Encryption\Exceptions\GenericEncryptionException;
+
+class EncryptionFailedException extends GenericEncryptionException{
+
+}
diff --git a/lib/private/encryption/exceptions/encryptionheaderkeyexistsexception.php b/lib/private/encryption/exceptions/encryptionheaderkeyexistsexception.php
index d401f0323ba..5e8e48efd78 100644
--- a/lib/private/encryption/exceptions/encryptionheaderkeyexistsexception.php
+++ b/lib/private/encryption/exceptions/encryptionheaderkeyexistsexception.php
@@ -23,7 +23,14 @@
namespace OC\Encryption\Exceptions;
+use OCP\Encryption\Exceptions\GenericEncryptionException;
-class EncryptionHeaderKeyExistsException extends \Exception {
+class EncryptionHeaderKeyExistsException extends GenericEncryptionException {
-} \ No newline at end of file
+ /**
+ * @param string $key
+ */
+ public function __construct($key) {
+ parent::__construct('header key "'. $key . '" already reserved by ownCloud');
+ }
+}
diff --git a/lib/private/encryption/exceptions/encryptionheadertolargeexception.php b/lib/private/encryption/exceptions/encryptionheadertolargeexception.php
new file mode 100644
index 00000000000..cdb5f940800
--- /dev/null
+++ b/lib/private/encryption/exceptions/encryptionheadertolargeexception.php
@@ -0,0 +1,33 @@
+<?php
+ /**
+ * @author Clark Tomlinson <clark@owncloud.com>
+ * @since 2/25/15, 9:35 AM
+ * @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\Encryption\Exceptions;
+
+use OCP\Encryption\Exceptions\GenericEncryptionException;
+
+class EncryptionHeaderToLargeException extends GenericEncryptionException {
+
+ public function __construct() {
+ parent::__construct('max header size exceeded');
+ }
+
+}
diff --git a/lib/private/encryption/exceptions/modulealreadyexistsexception.php b/lib/private/encryption/exceptions/modulealreadyexistsexception.php
index 41fc0188e24..fa1e70a5c36 100644
--- a/lib/private/encryption/exceptions/modulealreadyexistsexception.php
+++ b/lib/private/encryption/exceptions/modulealreadyexistsexception.php
@@ -23,6 +23,16 @@
namespace OC\Encryption\Exceptions;
-class ModuleAlreadyExistsException extends \Exception {
+use OCP\Encryption\Exceptions\GenericEncryptionException;
+
+class ModuleAlreadyExistsException extends GenericEncryptionException {
+
+ /**
+ * @param string $id
+ * @param string $name
+ */
+ public function __construct($id, $name) {
+ parent::__construct('Id "' . $id . '" already used by encryption module "' . $name . '"');
+ }
}
diff --git a/lib/private/encryption/exceptions/moduledoesnotexistsexception.php b/lib/private/encryption/exceptions/moduledoesnotexistsexception.php
index 5507bd03dab..2c699e8dc2d 100644
--- a/lib/private/encryption/exceptions/moduledoesnotexistsexception.php
+++ b/lib/private/encryption/exceptions/moduledoesnotexistsexception.php
@@ -23,6 +23,8 @@
namespace OC\Encryption\Exceptions;
-class ModuleDoesNotExistsException extends \Exception {
+use OCP\Encryption\Exceptions\GenericEncryptionException;
+
+class ModuleDoesNotExistsException extends GenericEncryptionException {
}
diff --git a/lib/private/encryption/exceptions/unknowncipherexception.php b/lib/private/encryption/exceptions/unknowncipherexception.php
new file mode 100644
index 00000000000..188f7403848
--- /dev/null
+++ b/lib/private/encryption/exceptions/unknowncipherexception.php
@@ -0,0 +1,29 @@
+<?php
+ /**
+ * @author Clark Tomlinson <clark@owncloud.com>
+ * @since 2/25/15, 9:36 AM
+ * @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\Encryption\Exceptions;
+
+use OCP\Encryption\Exceptions\GenericEncryptionException;
+
+class UnknownCipherException extends GenericEncryptionException {
+
+}
diff --git a/lib/private/encryption/file.php b/lib/private/encryption/file.php
new file mode 100644
index 00000000000..3600936ed0e
--- /dev/null
+++ b/lib/private/encryption/file.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * ownCloud
+ *
+ * @copyright (C) 2015 ownCloud, Inc.
+ *
+ * @author 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
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OC\Encryption;
+
+class File implements \OCP\Encryption\IFile {
+
+ /** @var Util */
+ protected $util;
+
+ public function __construct(Util $util) {
+ $this->util = $util;
+ }
+
+
+ /**
+ * get list of users with access to the file
+ *
+ * @param string $path to the file
+ * @return array
+ */
+ public function getAccessList($path) {
+
+ // Make sure that a share key is generated for the owner too
+ list($owner, $ownerPath) = $this->util->getUidAndFilename($path);
+
+ // always add owner to the list of users with access to the file
+ $userIds = array($owner);
+
+ if (!$this->util->isFile($ownerPath)) {
+ return array('users' => $userIds, 'public' => false);
+ }
+
+ $ownerPath = substr($ownerPath, strlen('/files'));
+ $ownerPath = $this->util->stripPartialFileExtension($ownerPath);
+
+ // Find out who, if anyone, is sharing the file
+ $result = \OCP\Share::getUsersSharingFile($ownerPath, $owner);
+ $userIds = \array_merge($userIds, $result['users']);
+ $public = $result['public'] || $result['remote'];
+
+ // check if it is a group mount
+ if (\OCP\App::isEnabled("files_external")) {
+ $mounts = \OC_Mount_Config::getSystemMountPoints();
+ foreach ($mounts as $mount) {
+ if ($mount['mountpoint'] == substr($ownerPath, 1, strlen($mount['mountpoint']))) {
+ $mountedFor = $this->util->getUserWithAccessToMountPoint($mount['applicable']['users'], $mount['applicable']['groups']);
+ $userIds = array_merge($userIds, $mountedFor);
+ }
+ }
+ }
+
+ // Remove duplicate UIDs
+ $uniqueUserIds = array_unique($userIds);
+
+ return array('users' => $uniqueUserIds, 'public' => $public);
+ }
+
+}
diff --git a/lib/private/encryption/keys/storage.php b/lib/private/encryption/keys/storage.php
index 041db2a2cb8..42610bd0b41 100644
--- a/lib/private/encryption/keys/storage.php
+++ b/lib/private/encryption/keys/storage.php
@@ -25,7 +25,7 @@ namespace OC\Encryption\Keys;
use OC\Encryption\Util;
use OC\Files\View;
-use OCA\Files_Encryption\Exception\EncryptionException;
+use OCP\Encryption\Exceptions\GenericEncryptionException;
class Storage implements \OCP\Encryption\Keys\IStorage {
@@ -253,13 +253,13 @@ class Storage implements \OCP\Encryption\Keys\IStorage {
*
* @param string $path path to the file, relative to data/
* @return string
- * @throws EncryptionException
+ * @throws GenericEncryptionException
* @internal param string $keyId
*/
private function getFileKeyDir($path) {
if ($this->view->is_dir($path)) {
- throw new EncryptionException('file was expected but directory was given', EncryptionException::GENERIC);
+ throw new GenericEncryptionException("file was expected but directory was given: $path");
}
list($owner, $filename) = $this->util->getUidAndFilename($path);
@@ -283,7 +283,12 @@ class Storage implements \OCP\Encryption\Keys\IStorage {
* @param string $owner
* @param bool $systemWide
*/
- public function renameKeys($source, $target, $owner, $systemWide) {
+ public function renameKeys($source, $target) {
+
+ list($owner, $source) = $this->util->getUidAndFilename($source);
+ list(, $target) = $this->util->getUidAndFilename($target);
+ $systemWide = $this->util->isSystemWideMountPoint($target);
+
if ($systemWide) {
$sourcePath = $this->keys_base_dir . $source . '/';
$targetPath = $this->keys_base_dir . $target . '/';
@@ -299,6 +304,34 @@ class Storage implements \OCP\Encryption\Keys\IStorage {
}
/**
+ * copy keys if a file was renamed
+ *
+ * @param string $source
+ * @param string $target
+ * @param string $owner
+ * @param bool $systemWide
+ */
+ public function copyKeys($source, $target) {
+
+ list($owner, $source) = $this->util->getUidAndFilename($source);
+ list(, $target) = $this->util->getUidAndFilename($target);
+ $systemWide = $this->util->isSystemWideMountPoint($target);
+
+ if ($systemWide) {
+ $sourcePath = $this->keys_base_dir . $source . '/';
+ $targetPath = $this->keys_base_dir . $target . '/';
+ } else {
+ $sourcePath = '/' . $owner . $this->keys_base_dir . $source . '/';
+ $targetPath = '/' . $owner . $this->keys_base_dir . $target . '/';
+ }
+
+ if ($this->view->file_exists($sourcePath)) {
+ $this->keySetPreparation(dirname($targetPath));
+ $this->view->copy($sourcePath, $targetPath);
+ }
+ }
+
+ /**
* Make preparations to filesystem for saving a keyfile
*
* @param string $path relative to the views root
@@ -306,7 +339,7 @@ class Storage implements \OCP\Encryption\Keys\IStorage {
protected function keySetPreparation($path) {
// If the file resides within a subdirectory, create it
if (!$this->view->file_exists($path)) {
- $sub_dirs = explode('/', $path);
+ $sub_dirs = explode('/', ltrim($path, '/'));
$dir = '';
foreach ($sub_dirs as $sub_dir) {
$dir .= '/' . $sub_dir;
diff --git a/lib/private/encryption/manager.php b/lib/private/encryption/manager.php
index 5164025239c..484e0f540b2 100644
--- a/lib/private/encryption/manager.php
+++ b/lib/private/encryption/manager.php
@@ -23,7 +23,9 @@
namespace OC\Encryption;
+use OC\Files\Storage\Wrapper\Encryption;
use OCP\Encryption\IEncryptionModule;
+use OCP\Files\Mount\IMountPoint;
class Manager implements \OCP\Encryption\IManager {
@@ -66,10 +68,9 @@ class Manager implements \OCP\Encryption\IManager {
public function registerEncryptionModule(IEncryptionModule $module) {
$id = $module->getId();
$name = $module->getDisplayName();
- if (isset($this->encryptionModules[$id])) {
- $message = 'Id "' . $id . '" already used by encryption module "' . $name . '"';
- throw new Exceptions\ModuleAlreadyExistsException($message);
+ if (isset($this->encryptionModules[$id])) {
+ throw new Exceptions\ModuleAlreadyExistsException($id, $name);
}
$defaultEncryptionModuleId = $this->getDefaultEncryptionModuleId();
@@ -106,12 +107,24 @@ class Manager implements \OCP\Encryption\IManager {
* @return IEncryptionModule
* @throws Exceptions\ModuleDoesNotExistsException
*/
- public function getEncryptionModule($moduleId) {
- if (isset($this->encryptionModules[$moduleId])) {
- return $this->encryptionModules[$moduleId];
- } else {
- $message = "Module with id: $moduleId does not exists.";
- throw new Exceptions\ModuleDoesNotExistsException($message);
+ public function getEncryptionModule($moduleId = '') {
+ if (!empty($moduleId)) {
+ if (isset($this->encryptionModules[$moduleId])) {
+ return $this->encryptionModules[$moduleId];
+ } else {
+ $message = "Module with id: $moduleId does not exists.";
+ throw new Exceptions\ModuleDoesNotExistsException($message);
+ }
+ } else { // get default module and return this
+ // For now we simply return the first module until we have a way
+ // to enable multiple modules and define a default module
+ $module = reset($this->encryptionModules);
+ if ($module) {
+ return $module;
+ } else {
+ $message = 'No encryption module registered';
+ throw new Exceptions\ModuleDoesNotExistsException($message);
+ }
}
}
@@ -166,5 +179,25 @@ class Manager implements \OCP\Encryption\IManager {
}
}
-
+ public static function setupStorage() {
+ \OC\Files\Filesystem::addStorageWrapper('oc_encryption', function ($mountPoint, $storage, IMountPoint $mount) {
+ $parameters = [
+ 'storage' => $storage,
+ 'mountPoint' => $mountPoint,
+ 'mount' => $mount];
+
+ if (!($storage instanceof \OC\Files\Storage\Shared)) {
+ $manager = \OC::$server->getEncryptionManager();
+ $util = new \OC\Encryption\Util(
+ new \OC\Files\View(), \OC::$server->getUserManager(), \OC::$server->getConfig());
+ $user = \OC::$server->getUserSession()->getUser();
+ $logger = \OC::$server->getLogger();
+ $uid = $user ? $user->getUID() : null;
+ $fileHelper = \OC::$server->getEncryptionFilesHelper();
+ return new Encryption($parameters, $manager, $util, $logger, $fileHelper, $uid);
+ } else {
+ return $storage;
+ }
+ }, 2);
+ }
}
diff --git a/lib/private/encryption/update.php b/lib/private/encryption/update.php
index 06dc330151e..1cfe935e584 100644
--- a/lib/private/encryption/update.php
+++ b/lib/private/encryption/update.php
@@ -46,12 +46,16 @@ class Update {
/** @var string */
protected $uid;
+ /** @var \OC\Encryption\File */
+ protected $file;
+
/**
*
* @param \OC\Files\View $view
* @param \OC\Encryption\Util $util
* @param \OC\Files\Mount\Manager $mountManager
* @param \OC\Encryption\Manager $encryptionManager
+ * @param \OC\Encryption\File $file
* @param string $uid
*/
public function __construct(
@@ -59,6 +63,7 @@ class Update {
Util $util,
Mount\Manager $mountManager,
Manager $encryptionManager,
+ File $file,
$uid
) {
@@ -66,6 +71,7 @@ class Update {
$this->util = $util;
$this->mountManager = $mountManager;
$this->encryptionManager = $encryptionManager;
+ $this->file = $file;
$this->uid = $uid;
}
@@ -87,25 +93,29 @@ class Update {
* @param int $fileSource file source id
*/
private function update($fileSource) {
- $path = \OC\Files\Filesystem::getPath($fileSource);
- $absPath = '/' . $this->uid . '/files' . $path;
-
- $mount = $this->mountManager->find($path);
- $mountPoint = $mount->getMountPoint();
-
- // if a folder was shared, get a list of all (sub-)folders
- if ($this->view->is_dir($absPath)) {
- $allFiles = $this->util->getAllFiles($absPath, $mountPoint);
- } else {
- $allFiles = array($absPath);
- }
+ $path = \OC\Files\Filesystem::getPath($fileSource);
+ $info = \OC\Files\Filesystem::getFileInfo($path);
+ $owner = \OC\Files\Filesystem::getOwner($path);
+ $view = new \OC\Files\View('/' . $owner . '/files');
+ $ownerPath = $view->getPath($info->getId());
+ $absPath = '/' . $owner . '/files' . $ownerPath;
+
+ $mount = $this->mountManager->find($path);
+ $mountPoint = $mount->getMountPoint();
+
+ // if a folder was shared, get a list of all (sub-)folders
+ if ($this->view->is_dir($absPath)) {
+ $allFiles = $this->util->getAllFiles($absPath, $mountPoint);
+ } else {
+ $allFiles = array($absPath);
+ }
- $encryptionModule = $this->encryptionManager->getDefaultEncryptionModule();
+ $encryptionModule = $this->encryptionManager->getDefaultEncryptionModule();
- foreach ($allFiles as $path) {
- $usersSharing = $this->util->getSharingUsersArray($path);
- $encryptionModule->update($absPath, $this->uid, $usersSharing);
- }
+ foreach ($allFiles as $path) {
+ $usersSharing = $this->file->getAccessList($path);
+ $encryptionModule->update($path, $this->uid, $usersSharing);
+ }
}
-} \ No newline at end of file
+}
diff --git a/lib/private/encryption/util.php b/lib/private/encryption/util.php
index 85e852ec2c9..6312d8813e3 100644
--- a/lib/private/encryption/util.php
+++ b/lib/private/encryption/util.php
@@ -23,9 +23,11 @@
namespace OC\Encryption;
-use OC\Encryption\Exceptions\EncryptionHeaderToLargeException;
use OC\Encryption\Exceptions\EncryptionHeaderKeyExistsException;
+use OC\Encryption\Exceptions\EncryptionHeaderToLargeException;
+use OC\Files\View;
use OCP\Encryption\IEncryptionModule;
+use OCP\IConfig;
class Util {
@@ -49,7 +51,7 @@ class Util {
*/
protected $blockSize = 8192;
- /** @var \OC\Files\View */
+ /** @var View */
protected $view;
/** @var array */
@@ -58,19 +60,30 @@ class Util {
/** @var \OC\User\Manager */
protected $userManager;
+ /** @var IConfig */
+ protected $config;
+
/** @var array paths excluded from encryption */
protected $excludedPaths;
/**
- * @param \OC\Files\View $view root view
+ *
+ * @param \OC\Files\View $view
+ * @param \OC\User\Manager $userManager
+ * @param IConfig $config
*/
- public function __construct(\OC\Files\View $view, \OC\User\Manager $userManager) {
+ public function __construct(
+ \OC\Files\View $view,
+ \OC\User\Manager $userManager,
+ IConfig $config) {
+
$this->ocHeaderKeys = [
self::HEADER_ENCRYPTION_MODULE_KEY
];
$this->view = $view;
$this->userManager = $userManager;
+ $this->config = $config;
$this->excludedPaths[] = 'files_encryption';
}
@@ -81,7 +94,7 @@ class Util {
* @param array $header
* @return string
*/
- public function getEncryptionModuleId(array $header) {
+ public function getEncryptionModuleId(array $header = null) {
$id = '';
$encryptionModuleKey = self::HEADER_ENCRYPTION_MODULE_KEY;
@@ -134,14 +147,14 @@ class Util {
$header = self::HEADER_START . ':' . self::HEADER_ENCRYPTION_MODULE_KEY . ':' . $encryptionModule->getId() . ':';
foreach ($headerData as $key => $value) {
if (in_array($key, $this->ocHeaderKeys)) {
- throw new EncryptionHeaderKeyExistsException('header key "'. $key . '" already reserved by ownCloud');
+ throw new EncryptionHeaderKeyExistsException($key);
}
$header .= $key . ':' . $value . ':';
}
$header .= self::HEADER_END;
if (strlen($header) > $this->getHeaderSize()) {
- throw new EncryptionHeaderToLargeException('max header size exceeded', EncryptionException::ENCRYPTION_HEADER_TO_LARGE);
+ throw new EncryptionHeaderToLargeException();
}
$paddedHeader = str_pad($header, $this->headerSize, self::HEADER_PADDING_CHAR, STR_PAD_RIGHT);
@@ -150,53 +163,10 @@ class Util {
}
/**
- * Find, sanitise and format users sharing a file
- * @note This wraps other methods into a portable bundle
- * @param string $path path relative to current users files folder
- * @return array
- */
- public function getSharingUsersArray($path) {
-
- // Make sure that a share key is generated for the owner too
- list($owner, $ownerPath) = $this->getUidAndFilename($path);
-
- // always add owner to the list of users with access to the file
- $userIds = array($owner);
-
- if (!$this->isFile($ownerPath)) {
- return array('users' => $userIds, 'public' => false);
- }
-
- $ownerPath = substr($ownerPath, strlen('/files'));
- $ownerPath = $this->stripPartialFileExtension($ownerPath);
-
- // Find out who, if anyone, is sharing the file
- $result = \OCP\Share::getUsersSharingFile($ownerPath, $owner);
- $userIds = \array_merge($userIds, $result['users']);
- $public = $result['public'] || $result['remote'];
-
- // check if it is a group mount
- if (\OCP\App::isEnabled("files_external")) {
- $mounts = \OC_Mount_Config::getSystemMountPoints();
- foreach ($mounts as $mount) {
- if ($mount['mountpoint'] == substr($ownerPath, 1, strlen($mount['mountpoint']))) {
- $mountedFor = $this->getUserWithAccessToMountPoint($mount['applicable']['users'], $mount['applicable']['groups']);
- $userIds = array_merge($userIds, $mountedFor);
- }
- }
- }
-
- // Remove duplicate UIDs
- $uniqueUserIds = array_unique($userIds);
-
- return array('users' => $uniqueUserIds, 'public' => $public);
- }
-
- /**
* go recursively through a dir and collect all files and sub files.
*
* @param string $dir relative to the users files folder
- * @param strinf $mountPoint
+ * @param string $mountPoint
* @return array with list of files relative to the users files folder
*/
public function getAllFiles($dir, $mountPoint = '') {
@@ -210,11 +180,11 @@ class Util {
foreach ($content as $c) {
// getDirectoryContent() returns the paths relative to the mount points, so we need
// to re-construct the complete path
- $path = ($mountPoint !== '') ? $mountPoint . '/' . $c['path'] : $c['path'];
+ $path = ($mountPoint !== '') ? $mountPoint . '/' . $c->getPath() : $c->getPath();
if ($c['type'] === 'dir') {
- $dirList[] = $path;
+ $dirList[] = \OC\Files\Filesystem::normalizePath($path);
} else {
- $result[] = $path;
+ $result[] = \OC\Files\Filesystem::normalizePath($path);
}
}
@@ -230,7 +200,7 @@ class Util {
* @param string $path
* @return boolean
*/
- protected function isFile($path) {
+ public function isFile($path) {
if (substr($path, 0, strlen('/files/')) === '/files/') {
return true;
}
@@ -256,7 +226,7 @@ class Util {
}
/**
- * get the owner and the path for the owner
+ * get the owner and the path for the file relative to the owners files folder
*
* @param string $path
* @return array
@@ -270,55 +240,15 @@ class Util {
$uid = $parts[1];
}
if (!$this->userManager->userExists($uid)) {
- throw new \BadMethodCallException('path needs to be relative to the system wide data folder and point to a user specific file');
- }
-
- $pathinfo = pathinfo($path);
- $partfile = false;
- $parentFolder = false;
- if (array_key_exists('extension', $pathinfo) && $pathinfo['extension'] === 'part') {
- // if the real file exists we check this file
- $filePath = $pathinfo['dirname'] . '/' . $pathinfo['filename'];
- if ($this->view->file_exists($filePath)) {
- $pathToCheck = $pathinfo['dirname'] . '/' . $pathinfo['filename'];
- } else { // otherwise we look for the parent
- $pathToCheck = $pathinfo['dirname'];
- $parentFolder = true;
- }
- $partfile = true;
- } else {
- $pathToCheck = $path;
+ throw new \BadMethodCallException(
+ 'path needs to be relative to the system wide data folder and point to a user specific file'
+ );
}
- $pathToCheck = substr($pathToCheck, strlen('/' . $uid));
-
- $this->view->chroot('/' . $uid);
- $owner = $this->view->getOwner($pathToCheck);
-
- // Check that UID is valid
- if (!$this->userManager->userExists($owner)) {
- throw new \BadMethodCallException('path needs to be relative to the system wide data folder and point to a user specific file');
- }
-
- \OC\Files\Filesystem::initMountPoints($owner);
-
- $info = $this->view->getFileInfo($pathToCheck);
- $this->view->chroot('/' . $owner);
- $ownerPath = $this->view->getPath($info->getId());
- $this->view->chroot('/');
+ $ownerPath = implode('/', array_slice($parts, 2));
- if ($parentFolder) {
- $ownerPath = $ownerPath . '/'. $pathinfo['filename'];
- }
-
- if ($partfile) {
- $ownerPath = $ownerPath . '.' . $pathinfo['extension'];
- }
+ return array($uid, \OC\Files\Filesystem::normalizePath($ownerPath));
- return array(
- $owner,
- \OC\Files\Filesystem::normalizePath($ownerPath)
- );
}
/**
@@ -348,7 +278,7 @@ class Util {
}
}
- protected function getUserWithAccessToMountPoint($users, $groups) {
+ public function getUserWithAccessToMountPoint($users, $groups) {
$result = array();
if (in_array('all', $users)) {
$result = \OCP\User::getUsers();
@@ -398,9 +328,6 @@ class Util {
return true;
}
- $v1 = $this->userManager->userExists($root[1]);
- $v2 = in_array($root[2], $this->excludedPaths);
-
// detect user specific folders
if ($this->userManager->userExists($root[1])
&& in_array($root[2], $this->excludedPaths)) {
@@ -411,4 +338,16 @@ class Util {
return false;
}
+ /**
+ * check if recovery key is enabled for user
+ *
+ * @param string $uid
+ * @return boolean
+ */
+ public function recoveryEnabled($uid) {
+ $enabled = $this->config->getUserValue($uid, 'encryption', 'recovery_enabled', '0');
+
+ return ($enabled === '1') ? true : false;
+ }
+
}
diff --git a/lib/private/filechunking.php b/lib/private/filechunking.php
index e8a58b2538d..82bf61fa7b1 100644
--- a/lib/private/filechunking.php
+++ b/lib/private/filechunking.php
@@ -189,8 +189,7 @@ class OC_FileChunking {
$absolutePath = \OC\Files\Filesystem::normalizePath(\OC\Files\Filesystem::getView()->getAbsolutePath($path));
$data = '';
// use file_put_contents as method because that best matches what this function does
- if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data)
- && \OC\Files\Filesystem::isValidPath($path)) {
+ if (\OC\Files\Filesystem::isValidPath($path)) {
$path = \OC\Files\Filesystem::getView()->getRelativePath($absolutePath);
$exists = \OC\Files\Filesystem::file_exists($path);
$run = true;
@@ -231,7 +230,6 @@ class OC_FileChunking {
\OC\Files\Filesystem::signal_post_write,
array( \OC\Files\Filesystem::signal_param_path => $path)
);
- OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count);
return $count > 0;
}else{
return false;
diff --git a/lib/private/fileproxy.php b/lib/private/fileproxy.php
deleted file mode 100644
index 8b28e866ac2..00000000000
--- a/lib/private/fileproxy.php
+++ /dev/null
@@ -1,138 +0,0 @@
-<?php
-/**
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Felix Moeller <mail@felixmoeller.de>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <icewind@owncloud.com>
- * @author Robin McCorkell <rmccorkell@karoshi.org.uk>
- * @author Scrutinizer Auto-Fixer <auto-fixer@scrutinizer-ci.com>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <pvince81@owncloud.com>
- *
- * @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/>
- *
- */
-
-/**
- * Class for manipulating filesystem requests
- *
- * Manipulation happens by using 2 kind of proxy operations, pre and post proxies
- * that manipulate the filesystem call and the result of the call respectively
- *
- * A pre-proxy recieves the filepath as arugments (or 2 filespaths in case of
- * operations like copy or move) and return a boolean
- * If a pre-proxy returns false the file operation will be canceled
- * All filesystem operations have a pre-proxy
- *
- * A post-proxy recieves 2 arguments, the filepath and the result of the operation.
- * The return value of the post-proxy will be used as the new result of the operation
- * The operations that have a post-proxy are:
- * file_get_contents, is_file, is_dir, file_exists, stat, is_readable,
- * is_writable, filemtime, filectime, file_get_contents,
- * getMimeType, hash, fopen, free_space and search
- */
-
-class OC_FileProxy{
- private static $proxies=array();
- public static $enabled=true;
-
- /**
- * fallback function when a proxy operation is not implemented
- * @param string $function the name of the proxy operation
- * @param mixed $arguments
- *
- * this implements a dummy proxy for all operations
- */
- public function __call($function, $arguments) {
- if(substr($function, 0, 3)=='pre') {
- return true;
- }else{
- return $arguments[1];
- }
- }
-
- /**
- * register a proxy to be used
- * @param OC_FileProxy $proxy
- */
- public static function register($proxy) {
- self::$proxies[]=$proxy;
- }
-
- /**
- * @param string $operation
- */
- public static function getProxies($operation = null) {
- if ($operation === null) {
- // return all
- return self::$proxies;
- }
- $proxies=array();
- foreach(self::$proxies as $proxy) {
- if(method_exists($proxy, $operation)) {
- $proxies[]=$proxy;
- }
- }
- return $proxies;
- }
-
- /**
- * @param string $operation
- * @param string|boolean $filepath
- */
- public static function runPreProxies($operation,&$filepath,&$filepath2=null) {
- if(!self::$enabled) {
- return true;
- }
- $operation='pre'.$operation;
- $proxies=self::getProxies($operation);
- foreach($proxies as $proxy) {
- if(!is_null($filepath2)) {
- if($proxy->$operation($filepath, $filepath2)===false) {
- return false;
- }
- }else{
- if($proxy->$operation($filepath)===false) {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * @param string $operation
- * @param string|boolean $path
- *
- * @return string
- */
- public static function runPostProxies($operation, $path, $result) {
- if(!self::$enabled) {
- return $result;
- }
- $operation='post'.$operation;
- $proxies=self::getProxies($operation);
- foreach($proxies as $proxy) {
- $result=$proxy->$operation($path, $result);
- }
- return $result;
- }
-
- public static function clearProxies() {
- self::$proxies=array();
- }
-}
diff --git a/lib/private/files.php b/lib/private/files.php
index d0c1baa0c1e..97f9d8163b1 100644
--- a/lib/private/files.php
+++ b/lib/private/files.php
@@ -122,7 +122,7 @@ class OC_Files {
if ($get_type === self::FILE) {
$zip = false;
- if ($xsendfile && OC_App::isEnabled('files_encryption')) {
+ if ($xsendfile && \OC::$server->getEncryptionManager()->isEnabled()) {
$xsendfile = false;
}
} else {
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);
}
diff --git a/lib/private/hook.php b/lib/private/hook.php
index d2a0fa898dd..c4ea1999b09 100644
--- a/lib/private/hook.php
+++ b/lib/private/hook.php
@@ -32,38 +32,39 @@ class OC_Hook{
/**
* connects a function to a hook
- * @param string $signalclass class name of emitter
- * @param string $signalname name of signal
- * @param string $slotclass class name of slot
- * @param string $slotname name of slot
+ *
+ * @param string $signalClass class name of emitter
+ * @param string $signalName name of signal
+ * @param string|object $slotClass class name of slot
+ * @param string $slotName name of slot
* @return bool
*
* This function makes it very easy to connect to use hooks.
*
* TODO: write example
*/
- static public function connect( $signalclass, $signalname, $slotclass, $slotname ) {
+ static public function connect($signalClass, $signalName, $slotClass, $slotName ) {
// If we're trying to connect to an emitting class that isn't
// yet registered, register it
- if( !array_key_exists( $signalclass, self::$registered )) {
- self::$registered[$signalclass] = array();
+ if( !array_key_exists($signalClass, self::$registered )) {
+ self::$registered[$signalClass] = array();
}
// If we're trying to connect to an emitting method that isn't
// yet registered, register it with the emitting class
- if( !array_key_exists( $signalname, self::$registered[$signalclass] )) {
- self::$registered[$signalclass][$signalname] = array();
+ if( !array_key_exists( $signalName, self::$registered[$signalClass] )) {
+ self::$registered[$signalClass][$signalName] = array();
}
// dont connect hooks twice
- foreach (self::$registered[$signalclass][$signalname] as $hook) {
- if ($hook['class'] === $slotclass and $hook['name'] === $slotname) {
+ foreach (self::$registered[$signalClass][$signalName] as $hook) {
+ if ($hook['class'] === $slotClass and $hook['name'] === $slotName) {
return false;
}
}
// Connect the hook handler to the requested emitter
- self::$registered[$signalclass][$signalname][] = array(
- "class" => $slotclass,
- "name" => $slotname
+ self::$registered[$signalClass][$signalName][] = array(
+ "class" => $slotClass,
+ "name" => $slotName
);
// No chance for failure ;-)
@@ -72,8 +73,9 @@ class OC_Hook{
/**
* emits a signal
- * @param string $signalclass class name of emitter
- * @param string $signalname name of signal
+ *
+ * @param string $signalClass class name of emitter
+ * @param string $signalName name of signal
* @param mixed $params default: array() array with additional data
* @return bool true if slots exists or false if not
*
@@ -81,28 +83,36 @@ class OC_Hook{
*
* TODO: write example
*/
- static public function emit( $signalclass, $signalname, $params = array()) {
+ static public function emit($signalClass, $signalName, $params = array()) {
// Return false if no hook handlers are listening to this
// emitting class
- if( !array_key_exists( $signalclass, self::$registered )) {
+ if( !array_key_exists($signalClass, self::$registered )) {
return false;
}
// Return false if no hook handlers are listening to this
// emitting method
- if( !array_key_exists( $signalname, self::$registered[$signalclass] )) {
+ if( !array_key_exists( $signalName, self::$registered[$signalClass] )) {
return false;
}
// Call all slots
- foreach( self::$registered[$signalclass][$signalname] as $i ) {
+ foreach( self::$registered[$signalClass][$signalName] as $i ) {
try {
call_user_func( array( $i["class"], $i["name"] ), $params );
} catch (Exception $e){
self::$thrownExceptions[] = $e;
+ $class = $i["class"];
+ if (is_object($i["class"])) {
+ $class = get_class($i["class"]);
+ }
+ $message = $e->getMessage();
+ if (empty($message)) {
+ $message = get_class($e);
+ }
OC_Log::write('hook',
- 'error while running hook (' . $i["class"] . '::' . $i["name"] . '): '.$e->getMessage(),
+ 'error while running hook (' . $class . '::' . $i["name"] . '): ' . $message,
OC_Log::ERROR);
}
}
diff --git a/lib/private/server.php b/lib/private/server.php
index 8c5169f229e..661aaf6786d 100644
--- a/lib/private/server.php
+++ b/lib/private/server.php
@@ -87,6 +87,11 @@ class Server extends SimpleContainer implements IServerContainer {
return new Encryption\Manager($c->getConfig());
});
+ $this->registerService('EncryptionFileHelper', function (Server $c) {
+ $util = new \OC\Encryption\Util(new \OC\Files\View(), $c->getUserManager(), $c->getConfig());
+ return new Encryption\File($util);
+ });
+
$this->registerService('EncryptionKeyStorageFactory', function ($c) {
return new Encryption\Keys\Factory();
});
@@ -408,13 +413,20 @@ class Server extends SimpleContainer implements IServerContainer {
}
/**
+ * @return \OC\Encryption\File
+ */
+ function getEncryptionFilesHelper() {
+ return $this->query('EncryptionFileHelper');
+ }
+
+ /**
* @param string $encryptionModuleId encryption module ID
*
* @return \OCP\Encryption\Keys\IStorage
*/
function getEncryptionKeyStorage($encryptionModuleId) {
$view = new \OC\Files\View();
- $util = new \OC\Encryption\Util($view, \OC::$server->getUserManager());
+ $util = new \OC\Encryption\Util($view, \OC::$server->getUserManager(), \OC::$server->getConfig());
return $this->query('EncryptionKeyStorageFactory')->get($encryptionModuleId, $view, $util);
}
@@ -496,19 +508,7 @@ class Server extends SimpleContainer implements IServerContainer {
$dir = '/files';
if (!$folder->nodeExists($dir)) {
$folder = $folder->newFolder($dir);
-
- if (\OCP\App::isEnabled('files_encryption')) {
- // disable encryption proxy to prevent recursive calls
- $proxyStatus = \OC_FileProxy::$enabled;
- \OC_FileProxy::$enabled = false;
- }
-
\OC_Util::copySkeleton($user, $folder);
-
- if (\OCP\App::isEnabled('files_encryption')) {
- // re-enable proxy - our work is done
- \OC_FileProxy::$enabled = $proxyStatus;
- }
} else {
$folder = $folder->get($dir);
}
diff --git a/lib/private/share/share.php b/lib/private/share/share.php
index 90f3f28f2ee..98c612d5eb6 100644
--- a/lib/private/share/share.php
+++ b/lib/private/share/share.php
@@ -2214,7 +2214,7 @@ class Share extends \OC\Share\Constants {
$select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`, `uid_owner`, '
. '`share_type`, `share_with`, `file_source`, `path`, `file_target`, `stime`, '
. '`*PREFIX*share`.`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, '
- . '`name`, `mtime`, `mimetype`, `mimepart`, `size`, `unencrypted_size`, `encrypted`, `etag`, `mail_send`';
+ . '`name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`, `etag`, `mail_send`';
} else {
$select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`,'
. '`*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`,'
diff --git a/lib/private/util.php b/lib/private/util.php
index e6dd307faea..3fd0f844684 100644
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -812,51 +812,6 @@ class OC_Util {
return $errors;
}
-
- /**
- * check if there are still some encrypted files stored
- *
- * @return boolean
- */
- public static function encryptedFiles() {
- //check if encryption was enabled in the past
- $encryptedFiles = false;
- if (OC_App::isEnabled('files_encryption') === false) {
- $view = new OC\Files\View('/' . OCP\User::getUser());
- $keysPath = '/files_encryption/keys';
- if ($view->is_dir($keysPath)) {
- $dircontent = $view->getDirectoryContent($keysPath);
- if (!empty($dircontent)) {
- $encryptedFiles = true;
- }
- }
- }
-
- return $encryptedFiles;
- }
-
- /**
- * check if a backup from the encryption keys exists
- *
- * @return boolean
- */
- public static function backupKeysExists() {
- //check if encryption was enabled in the past
- $backupExists = false;
- if (OC_App::isEnabled('files_encryption') === false) {
- $view = new OC\Files\View('/' . OCP\User::getUser());
- $backupPath = '/files_encryption/backup.decryptAll';
- if ($view->is_dir($backupPath)) {
- $dircontent = $view->getDirectoryContent($backupPath);
- if (!empty($dircontent)) {
- $backupExists = true;
- }
- }
- }
-
- return $backupExists;
- }
-
/**
* Check for correct file permissions of data directory
*
diff --git a/lib/public/encryption/exceptions/genericencryptionexception.php b/lib/public/encryption/exceptions/genericencryptionexception.php
new file mode 100644
index 00000000000..b7addd3b0c1
--- /dev/null
+++ b/lib/public/encryption/exceptions/genericencryptionexception.php
@@ -0,0 +1,34 @@
+<?php
+ /**
+ * @author Clark Tomlinson <clark@owncloud.com>
+ * @since 2/25/15, 9:30 AM
+ * @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 OCP\Encryption\Exceptions;
+
+
+class GenericEncryptionException extends \Exception {
+
+ public function __construct($message = "", $code = 0, \Exception $previous = null) {
+ if (empty($message)) {
+ $message = 'Unspecified encryption exception';
+ }
+ parent::__construct($message, $code, $previous);
+ }
+
+}
diff --git a/lib/public/encryption/ifile.php b/lib/public/encryption/ifile.php
new file mode 100644
index 00000000000..464f41509d2
--- /dev/null
+++ b/lib/public/encryption/ifile.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * ownCloud
+ *
+ * @copyright (C) 2015 ownCloud, Inc.
+ *
+ * @author 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
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OCP\Encryption;
+
+interface IFile {
+
+ /**
+ * get list of users with access to the file
+ *
+ * @param string $path to the file
+ * @return array
+ */
+ public function getAccessList($path);
+
+}
diff --git a/lib/public/encryption/imanager.php b/lib/public/encryption/imanager.php
index 9a12e401593..2691604ac37 100644
--- a/lib/public/encryption/imanager.php
+++ b/lib/public/encryption/imanager.php
@@ -22,9 +22,7 @@
*/
namespace OCP\Encryption;
-//
-// TODO: move exceptions to OCP
-//
+
use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
use OC\Encryption\Exceptions\ModuleAlreadyExistsException;
diff --git a/lib/public/encryption/keys/istorage.php b/lib/public/encryption/keys/istorage.php
index 4c2b01f4ad0..2d1672face5 100644
--- a/lib/public/encryption/keys/istorage.php
+++ b/lib/public/encryption/keys/istorage.php
@@ -122,4 +122,20 @@ interface IStorage {
*/
public function deleteSystemUserKey($keyId);
+ /**
+ * copy keys if a file was renamed
+ *
+ * @param string $source
+ * @param string $target
+ */
+ public function renameKeys($source, $target);
+
+ /**
+ * move keys if a file was renamed
+ *
+ * @param string $source
+ * @param string $target
+ */
+ public function copyKeys($source, $target);
+
}
diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php
index d7df884adf8..509e5894d47 100644
--- a/lib/public/iservercontainer.php
+++ b/lib/public/iservercontainer.php
@@ -150,13 +150,19 @@ interface IServerContainer {
function getHasher();
/**
+ * Returns a SecureRandom instance
+ *
+ * @return \OCP\Security\ISecureRandom
+ */
+ function getSecureRandom();
+
+ /**
* Returns an instance of the db facade
* @deprecated use getDatabaseConnection, will be removed in ownCloud 10
* @return \OCP\IDb
*/
function getDb();
-
/**
* Returns the app config manager
*
@@ -173,6 +179,23 @@ interface IServerContainer {
function getL10N($app, $lang = null);
/**
+ * @return \OC\Encryption\Manager
+ */
+ function getEncryptionManager();
+
+ /**
+ * @return \OC\Encryption\File
+ */
+ function getEncryptionFilesHelper();
+
+ /**
+ * @param string $encryptionModuleId encryption module ID
+ *
+ * @return \OCP\Encryption\Keys\IStorage
+ */
+ function getEncryptionKeyStorage($encryptionModuleId);
+
+ /**
* Returns the URL generator
*
* @return \OCP\IURLGenerator
diff --git a/lib/public/util.php b/lib/public/util.php
index b50ce54839b..721bcaadb62 100644
--- a/lib/public/util.php
+++ b/lib/public/util.php
@@ -219,9 +219,11 @@ class Util {
/**
* check if some encrypted files are stored
* @return bool
+ *
+ * @deprecated No longer required
*/
public static function encryptedFiles() {
- return \OC_Util::encryptedFiles();
+ return false;
}
/**
@@ -392,18 +394,19 @@ class Util {
/**
* connects a function to a hook
- * @param string $signalclass class name of emitter
- * @param string $signalname name of signal
- * @param string $slotclass class name of slot
- * @param string $slotname name of slot
+ *
+ * @param string $signalClass class name of emitter
+ * @param string $signalName name of signal
+ * @param string|object $slotClass class name of slot
+ * @param string $slotName name of slot
* @return bool
*
* This function makes it very easy to connect to use hooks.
*
* TODO: write example
*/
- static public function connectHook( $signalclass, $signalname, $slotclass, $slotname ) {
- return(\OC_Hook::connect( $signalclass, $signalname, $slotclass, $slotname ));
+ static public function connectHook($signalClass, $signalName, $slotClass, $slotName ) {
+ return(\OC_Hook::connect($signalClass, $signalName, $slotClass, $slotName ));
}
/**