diff options
author | Vincent Petry <pvince81@owncloud.com> | 2016-03-01 22:43:54 +0300 |
---|---|---|
committer | Vincent Petry <pvince81@owncloud.com> | 2016-03-01 22:43:54 +0300 |
commit | 5200baa9668f9cbbb5f5f693ba5038c55aed56e7 (patch) | |
tree | 63f9cbd95a9518c56d366ffcebc8976198312c29 | |
parent | ee4d57660d6563440fdd61eb9997d0463df136a3 (diff) | |
parent | d32fc2d7718db89e30c636889ebed522db82e5cc (diff) |
Merge pull request #22752 from owncloud/part-file-root-82
[stable8.2] allow putting the part file in the view root
-rw-r--r-- | apps/dav/tests/unit/connector/sabre/requesttest/partfileinrootupload.php | 56 | ||||
-rw-r--r-- | config/config.sample.php | 10 | ||||
-rw-r--r-- | lib/private/connector/sabre/file.php | 23 | ||||
-rw-r--r-- | lib/private/files/storage/wrapper/quota.php | 27 |
4 files changed, 104 insertions, 12 deletions
diff --git a/apps/dav/tests/unit/connector/sabre/requesttest/partfileinrootupload.php b/apps/dav/tests/unit/connector/sabre/requesttest/partfileinrootupload.php new file mode 100644 index 00000000000..52790c5b00b --- /dev/null +++ b/apps/dav/tests/unit/connector/sabre/requesttest/partfileinrootupload.php @@ -0,0 +1,56 @@ +<?php +/** + * @author Robin Appelman <icewind@owncloud.com> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, 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 OCA\DAV\Tests\Unit\Connector\Sabre\RequestTest; + +use OC\Files\View; +use Test\Traits\EncryptionTrait; + +/** + * Class EncryptionUploadTest + * + * @group DB + * + * @package OCA\DAV\Tests\Unit\Connector\Sabre\RequestTest + */ +class PartFileInRootUpload extends UploadTest { + protected function setUp() { + $config = \OC::$server->getConfig(); + $mockConfig = $this->getMock('\OCP\IConfig'); + $mockConfig->expects($this->any()) + ->method('getSystemValue') + ->will($this->returnCallback(function ($key, $default) use ($config) { + if ($key === 'part_file_in_storage') { + return false; + } else { + return $config->getSystemValue($key, $default); + } + })); + $this->overwriteService('AllConfig', $mockConfig); + parent::setUp(); + } + + protected function tearDown() { + $this->restoreService('AllConfig'); + return parent::tearDown(); + } +} diff --git a/config/config.sample.php b/config/config.sample.php index d572adf1a05..31ebd2d0321 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -406,7 +406,7 @@ $CONFIG = array( * delete all files in the trash bin that are older than D days * automatically, delete other files anytime if space needed * * ``D1, D2`` - * keep files and folders the in trash bin for at least D1 days and + * keep files and folders the in trash bin for at least D1 days and * delete when exceeds D2 days * * ``disabled`` * trash bin auto clean disabled, files and folders will be kept forever @@ -1060,6 +1060,14 @@ $CONFIG = array( 'filesystem_check_changes' => 0, /** + * On default ownCloud will store the part files created during upload in the + * same storage as the upload target. Setting this to false will store the part + * files in the root of the users folder which might be required to work with certain + * external storage setups that have limited rename capabilities. + */ +'part_file_in_storage' => true, + +/** * All css and js files will be served by the web server statically in one js * file and one css file if this is set to ``true``. This improves performance. */ diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php index 50c9bbf5bc4..76a82e49416 100644 --- a/lib/private/connector/sabre/file.php +++ b/lib/private/connector/sabre/file.php @@ -109,7 +109,7 @@ class File extends Node implements IFile { if ($needsPartFile) { // mark file as partial while uploading (ignored by the scanner) - $partFilePath = $this->path . '.ocTransferId' . rand() . '.part'; + $partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part'; } else { // upload file directly as the final path $partFilePath = $this->path; @@ -130,12 +130,12 @@ class File extends Node implements IFile { list($count, $result) = \OC_Helper::streamCopy($data, $target); fclose($target); - if($result === false) { + if ($result === false) { $expected = -1; if (isset($_SERVER['CONTENT_LENGTH'])) { $expected = $_SERVER['CONTENT_LENGTH']; } - throw new Exception('Error while copying file to target location (copied bytes: ' . $count . ', expected filesize: '. $expected .' )'); + throw new Exception('Error while copying file to target location (copied bytes: ' . $count . ', expected filesize: ' . $expected . ' )'); } // if content length is sent by client: @@ -217,6 +217,18 @@ class File extends Node implements IFile { return '"' . $this->info->getEtag() . '"'; } + private function getPartFileBasePath($path) { + $partFileInStorage = \OC::$server->getConfig()->getSystemValue('part_file_in_storage', true); + if ($partFileInStorage) { + return $path; + } else { + return md5($path); // will place it in the root of the view with a unique name + } + } + + /** + * @param string $path + */ private function emitPreHooks($exists, $path = null) { if (is_null($path)) { $path = $this->path; @@ -390,9 +402,8 @@ class File extends Node implements IFile { if ($needsPartFile) { // we first assembly the target file as a part file - $partFile = $path . '/' . $info['name'] . '.ocTransferId' . $info['transferid'] . '.part'; - - + $partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part'; + /** @var \OC\Files\Storage\Storage $targetStorage */ list($partStorage, $partInternalPath) = $this->fileView->resolvePath($partFile); diff --git a/lib/private/files/storage/wrapper/quota.php b/lib/private/files/storage/wrapper/quota.php index 98664e27e2d..00680841b2a 100644 --- a/lib/private/files/storage/wrapper/quota.php +++ b/lib/private/files/storage/wrapper/quota.php @@ -139,17 +139,34 @@ class Quota extends Wrapper { */ public function fopen($path, $mode) { $source = $this->storage->fopen($path, $mode); - $free = $this->free_space(''); - if ($source && $free >= 0 && $mode !== 'r' && $mode !== 'rb') { - // only apply quota for files, not metadata, trash or others - if (strpos(ltrim($path, '/'), 'files/') === 0) { - return \OC\Files\Stream\Quota::wrap($source, $free); + + // don't apply quota for part files + if (!$this->isPartFile($path)) { + $free = $this->free_space(''); + if ($source && $free >= 0 && $mode !== 'r' && $mode !== 'rb') { + // only apply quota for files, not metadata, trash or others + if (strpos(ltrim($path, '/'), 'files/') === 0) { + return \OC\Files\Stream\Quota::wrap($source, $free); + } } } return $source; } /** + * Checks whether the given path is a part file + * + * @param string $path Path that may identify a .part file + * @return string File path without .part extension + * @note this is needed for reusing keys + */ + private function isPartFile($path) { + $extension = pathinfo($path, PATHINFO_EXTENSION); + + return ($extension === 'part'); + } + + /** * @param \OCP\Files\Storage $sourceStorage * @param string $sourceInternalPath * @param string $targetInternalPath |