]> source.dussan.org Git - nextcloud-server.git/commitdiff
Work directly on the storage when uploading over webdav
authorRobin Appelman <icewind@owncloud.com>
Thu, 6 Nov 2014 15:48:20 +0000 (16:48 +0100)
committerThomas Müller <thomas.mueller@tmit.eu>
Wed, 8 Apr 2015 12:04:58 +0000 (14:04 +0200)
lib/private/connector/sabre/file.php

index b4acaa150731399df88f0a9fd8d8e439013e5cc0..ec27e84c19aa07e462e520320d08e83ddbfd48ac 100644 (file)
@@ -83,8 +83,8 @@ class File extends Node implements IFile {
         */
        public function put($data) {
                try {
-                       if ($this->info && $this->fileView->file_exists($this->path) &&
-                               !$this->info->isUpdateable()) {
+                       $exists = $this->fileView->file_exists($this->path);
+                       if ($this->info && $exists && !$this->info->isUpdateable()) {
                                throw new Forbidden();
                        }
                } catch (StorageNotAvailableException $e) {
@@ -110,14 +110,31 @@ class File extends Node implements IFile {
                        $partFilePath = $this->path;
                }
 
+               /** @var \OC\Files\Storage\Storage $storage */
+               list($storage, $internalPartPath) = $this->fileView->resolvePath($partFilePath);
+               list(, $internalPath) = $this->fileView->resolvePath($this->path);
                try {
-                       $putOkay = $this->fileView->file_put_contents($partFilePath, $data);
-                       if ($putOkay === false) {
+                       $target = $storage->fopen($internalPartPath, 'wb');
+                       if ($target === false) {
                                \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 Exception('Could not write file contents');
                        }
+                       $count = stream_copy_to_stream($data, $target);
+                       fclose($target);
+
+                       // if content length is sent by client:
+                       // double check if the file was fully received
+                       // compare expected and actual size
+                       if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] !== 'LOCK') {
+                               $expected = $_SERVER['CONTENT_LENGTH'];
+                               if ($count != $expected) {
+                                       $storage->unlink($internalPartPath);
+                                       throw new BadRequest('expected filesize ' . $expected . ' got ' . $count);
+                               }
+                       }
+
                } catch (NotPermittedException $e) {
                        // a more general case - due to whatever reason the content could not be written
                        throw new Forbidden($e->getMessage());
@@ -142,35 +159,39 @@ class File extends Node implements IFile {
                }
 
                try {
-                       // if content length is sent by client:
-                       // double check if the file was fully received
-                       // compare expected and actual size
-                       if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] !== 'LOCK') {
-                               $expected = $_SERVER['CONTENT_LENGTH'];
-                               $actual = $this->fileView->filesize($partFilePath);
-                               if ($actual != $expected) {
-                                       $this->fileView->unlink($partFilePath);
-                                       throw new BadRequest('expected filesize ' . $expected . ' got ' . $actual);
-                               }
-                       }
-
                        if ($needsPartFile) {
                                // rename to correct path
                                try {
-                                       $renameOkay = $this->fileView->rename($partFilePath, $this->path);
-                                       $fileExists = $this->fileView->file_exists($this->path);
+                                       $renameOkay = $storage->rename($internalPartPath, $internalPath);
+                                       $fileExists = $storage->file_exists($internalPath);
                                        if ($renameOkay === false || $fileExists === false) {
                                                \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
                                                $this->fileView->unlink($partFilePath);
                                                throw new Exception('Could not rename part file to final file');
                                        }
-                               }
-                               catch (LockNotAcquiredException $e) {
+                               } catch (\OCP\Files\LockNotAcquiredException $e) {
                                        // the file is currently being written to by another process
                                        throw new FileLocked($e->getMessage(), $e->getCode(), $e);
                                }
                        }
 
+                       // since we skipped the view we need to scan and emit the hooks ourselves
+                       $storage->getScanner()->scanFile($internalPath);
+
+                       $hookPath = \OC\Files\Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($this->path));
+                       if (!$exists) {
+                               \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_create, array(
+                                       \OC\Files\Filesystem::signal_param_path => $hookPath
+                               ));
+                       } else {
+                               \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_update, array(
+                                       \OC\Files\Filesystem::signal_param_path => $hookPath
+                               ));
+                       }
+                       \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_write, array(
+                               \OC\Files\Filesystem::signal_param_path => $hookPath
+                       ));
+
                        // allow sync clients to send the mtime along in a header
                        $request = \OC::$server->getRequest();
                        if (isset($request->server['HTTP_X_OC_MTIME'])) {
@@ -266,8 +287,7 @@ class File extends Node implements IFile {
         * @throws NotImplemented
         * @throws ServiceUnavailable
         */
-       private function createFileChunked($data)
-       {
+       private function createFileChunked($data) {
                list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($this->path);
 
                $info = \OC_FileChunking::decodeName($name);
@@ -278,7 +298,7 @@ class File extends Node implements IFile {
                $bytesWritten = $chunk_handler->store($info['index'], $data);
 
                //detect aborted upload
-               if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT' ) {
+               if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
                        if (isset($_SERVER['CONTENT_LENGTH'])) {
                                $expected = $_SERVER['CONTENT_LENGTH'];
                                if ($bytesWritten != $expected) {