From f017f431f6243f28318ff90374d165abc62f085e Mon Sep 17 00:00:00 2001
From: Robin Appelman <robin@icewind.nl>
Date: Mon, 14 May 2018 16:22:30 +0200
Subject: properly lock the target file on dav upload when not using part files

Signed-off-by: Robin Appelman <robin@icewind.nl>
---
 apps/dav/lib/Connector/Sabre/File.php | 38 +++++++++++++++++++++--------------
 1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php
index bbd6717d94f..ed1dbe5469e 100644
--- a/apps/dav/lib/Connector/Sabre/File.php
+++ b/apps/dav/lib/Connector/Sabre/File.php
@@ -150,12 +150,21 @@ class File extends Node implements IFile {
 			$this->emitPreHooks($exists);
 		}
 
+		$view = \OC\Files\Filesystem::getView();
+
 		// the part file and target file might be on a different storage in case of a single file storage (e.g. single file share)
 		/** @var \OC\Files\Storage\Storage $partStorage */
 		list($partStorage, $internalPartPath) = $this->fileView->resolvePath($partFilePath);
 		/** @var \OC\Files\Storage\Storage $storage */
 		list($storage, $internalPath) = $this->fileView->resolvePath($this->path);
 		try {
+			if (!$needsPartFile) {
+				if ($view && !$this->emitPreHooks($exists)) {
+					throw new Exception('Could not write to final file, canceled by hook');
+				}
+				$this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
+			}
+
 			$target = $partStorage->fopen($internalPartPath, 'wb');
 			if ($target === false) {
 				\OC::$server->getLogger()->error('\OC\Files\Filesystem::fopen() failed', ['app' => 'webdav']);
@@ -191,26 +200,25 @@ class File extends Node implements IFile {
 		}
 
 		try {
-			$view = \OC\Files\Filesystem::getView();
-			$run = ($view && $needsPartFile) ? $this->emitPreHooks($exists) : true;
-
-			try {
-				$this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
-			} catch (LockedException $e) {
-				if ($needsPartFile) {
+			if ($needsPartFile) {
+				if ($view && !$this->emitPreHooks($exists)) {
 					$partStorage->unlink($internalPartPath);
+					throw new Exception('Could not rename part file to final file, canceled by hook');
+				}
+				try {
+					$this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
+				} catch (LockedException $e) {
+					if ($needsPartFile) {
+						$partStorage->unlink($internalPartPath);
+					}
+					throw new FileLocked($e->getMessage(), $e->getCode(), $e);
 				}
-				throw new FileLocked($e->getMessage(), $e->getCode(), $e);
-			}
 
-			if ($needsPartFile) {
 				// rename to correct path
 				try {
-					if ($run) {
-						$renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath);
-						$fileExists = $storage->file_exists($internalPath);
-					}
-					if (!$run || $renameOkay === false || $fileExists === false) {
+					$renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath);
+					$fileExists = $storage->file_exists($internalPath);
+					if ($renameOkay === false || $fileExists === false) {
 						\OC::$server->getLogger()->error('renaming part file to final file failed ($run: ' . ( $run ? 'true' : 'false' ) . ', $renameOkay: '  . ( $renameOkay ? 'true' : 'false' ) . ', $fileExists: ' . ( $fileExists ? 'true' : 'false' ) . ')', ['app' => 'webdav']);
 						throw new Exception('Could not rename part file to final file');
 					}
-- 
cgit v1.2.3