aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private
diff options
context:
space:
mode:
authorBjörn Schießle <bjoern@schiessle.org>2015-05-06 15:03:59 +0200
committerBjörn Schießle <bjoern@schiessle.org>2015-05-06 15:03:59 +0200
commit6633514a980b3246bdd4c26a1b890d12306f47f8 (patch)
tree46473391e6e267deb7fde570dac60e5612acb7de /lib/private
parent892e2a3321fa08f0ddad568c233eb38eeffa9486 (diff)
parentaea734aaf15d38f8b1f819fc2f693ec24236cad3 (diff)
downloadnextcloud-server-6633514a980b3246bdd4c26a1b890d12306f47f8.tar.gz
nextcloud-server-6633514a980b3246bdd4c26a1b890d12306f47f8.zip
Merge pull request #15628 from owncloud/enc_fix_rename
Encryption - fix moving/copying files between storages
Diffstat (limited to 'lib/private')
-rw-r--r--lib/private/files/storage/common.php5
-rw-r--r--lib/private/files/storage/wrapper/encryption.php110
2 files changed, 108 insertions, 7 deletions
diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php
index 06c61fe6931..fc30b385e2e 100644
--- a/lib/private/files/storage/common.php
+++ b/lib/private/files/storage/common.php
@@ -545,6 +545,11 @@ abstract class Common implements Storage {
}
} else {
$source = $sourceStorage->fopen($sourceInternalPath, 'r');
+ // TODO: call fopen in a way that we execute again all storage wrappers
+ // to avoid that we bypass storage wrappers which perform important actions
+ // for this operation. Same is true for all other operations which
+ // are not the same as the original one.Once this is fixed we also
+ // need to adjust the encryption wrapper.
$target = $this->fopen($targetInternalPath, 'w');
list(, $result) = \OC_Helper::streamCopy($source, $target);
if ($result and $preserveMtime) {
diff --git a/lib/private/files/storage/wrapper/encryption.php b/lib/private/files/storage/wrapper/encryption.php
index 24bbef9b93c..c0c4c6979c2 100644
--- a/lib/private/files/storage/wrapper/encryption.php
+++ b/lib/private/files/storage/wrapper/encryption.php
@@ -61,19 +61,20 @@ class Encryption extends Wrapper {
/** @var IMountPoint */
private $mount;
- /** @var \OCP\Encryption\Keys\IStorage */
+
+ /** @var IStorage */
private $keyStorage;
- /** @var \OC\Encryption\Update */
+ /** @var Update */
private $update;
/**
* @param array $parameters
- * @param \OCP\Encryption\IManager $encryptionManager
- * @param \OC\Encryption\Util $util
- * @param \OCP\ILogger $logger
- * @param \OCP\Encryption\IFile $fileHelper
- * @param string $uid user who perform the read/write operation (null for public access)
+ * @param IManager $encryptionManager
+ * @param Util $util
+ * @param ILogger $logger
+ * @param IFile $fileHelper
+ * @param string $uid
* @param IStorage $keyStorage
* @param Update $update
*/
@@ -366,6 +367,101 @@ class Encryption extends Wrapper {
}
/**
+ * @param \OCP\Files\Storage $sourceStorage
+ * @param string $sourceInternalPath
+ * @param string $targetInternalPath
+ * @param bool $preserveMtime
+ * @return bool
+ */
+ public function moveFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime = true) {
+
+ // TODO clean this up once the underlying moveFromStorage in OC\Files\Storage\Wrapper\Common is fixed:
+ // - call $this->storage->moveFromStorage() instead of $this->copyBetweenStorage
+ // - copy the file cache update from $this->copyBetweenStorage to this method
+ // - remove $this->copyBetweenStorage
+
+ $result = $this->copyBetweenStorage($sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime, true);
+ if ($result) {
+ if ($sourceStorage->is_dir($sourceInternalPath)) {
+ $result &= $sourceStorage->rmdir($sourceInternalPath);
+ } else {
+ $result &= $sourceStorage->unlink($sourceInternalPath);
+ }
+ }
+ return $result;
+ }
+
+
+ /**
+ * @param \OCP\Files\Storage $sourceStorage
+ * @param string $sourceInternalPath
+ * @param string $targetInternalPath
+ * @param bool $preserveMtime
+ * @return bool
+ */
+ public function copyFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime = false) {
+
+ // TODO clean this up once the underlying moveFromStorage in OC\Files\Storage\Wrapper\Common is fixed:
+ // - call $this->storage->moveFromStorage() instead of $this->copyBetweenStorage
+ // - copy the file cache update from $this->copyBetweenStorage to this method
+ // - remove $this->copyBetweenStorage
+
+ return $this->copyBetweenStorage($sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime, false);
+ }
+
+ /**
+ * copy file between two storages
+ *
+ * @param \OCP\Files\Storage $sourceStorage
+ * @param string $sourceInternalPath
+ * @param string $targetInternalPath
+ * @param bool $preserveMtime
+ * @param bool $isRename
+ * @return bool
+ */
+ private function copyBetweenStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime, $isRename) {
+ if ($sourceStorage->is_dir($sourceInternalPath)) {
+ $dh = $sourceStorage->opendir($sourceInternalPath);
+ $result = $this->mkdir($targetInternalPath);
+ if (is_resource($dh)) {
+ while ($result and ($file = readdir($dh)) !== false) {
+ if (!Filesystem::isIgnoredDir($file)) {
+ $result &= $this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file);
+ }
+ }
+ }
+ } else {
+ $source = $sourceStorage->fopen($sourceInternalPath, 'r');
+ $target = $this->fopen($targetInternalPath, 'w');
+ list(, $result) = \OC_Helper::streamCopy($source, $target);
+ fclose($source);
+ fclose($target);
+
+ if($result) {
+ if ($preserveMtime) {
+ $this->touch($targetInternalPath, $sourceStorage->filemtime($sourceInternalPath));
+ }
+ $isEncrypted = $this->mount->getOption('encrypt', true) ? 1 : 0;
+
+ // in case of a rename we need to manipulate the source cache because
+ // this information will be kept for the new target
+ if ($isRename) {
+ $sourceStorage->getCache()->put($sourceInternalPath, ['encrypted' => $isEncrypted]);
+ } else {
+ $this->getCache()->put($targetInternalPath, ['encrypted' => $isEncrypted]);
+ }
+ } else {
+ // delete partially written target file
+ $this->unlink($targetInternalPath);
+ // delete cache entry that was created by fopen
+ $this->getCache()->remove($targetInternalPath);
+ }
+ }
+ return (bool)$result;
+
+ }
+
+ /**
* 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
*