Completed
Pull Request — master (#9473)
by Robin
20:40
created
apps/dav/lib/Connector/Sabre/File.php 2 patches
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -121,7 +121,7 @@  discard block
 block discarded – undo
121 121
 				throw new Forbidden();
122 122
 			}
123 123
 		} catch (StorageNotAvailableException $e) {
124
-			throw new ServiceUnavailable("File is not updatable: " . $e->getMessage());
124
+			throw new ServiceUnavailable("File is not updatable: ".$e->getMessage());
125 125
 		}
126 126
 
127 127
 		// verify path of the target
@@ -142,7 +142,7 @@  discard block
 block discarded – undo
142 142
 
143 143
 		if ($needsPartFile) {
144 144
 			// mark file as partial while uploading (ignored by the scanner)
145
-			$partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part';
145
+			$partFilePath = $this->getPartFileBasePath($this->path).'.ocTransferId'.rand().'.part';
146 146
 		} else {
147 147
 			// upload file directly as the final path
148 148
 			$partFilePath = $this->path;
@@ -179,7 +179,7 @@  discard block
 block discarded – undo
179 179
 				if (isset($_SERVER['CONTENT_LENGTH'])) {
180 180
 					$expected = $_SERVER['CONTENT_LENGTH'];
181 181
 				}
182
-				throw new Exception('Error while copying file to target location (copied bytes: ' . $count . ', expected filesize: ' . $expected . ' )');
182
+				throw new Exception('Error while copying file to target location (copied bytes: '.$count.', expected filesize: '.$expected.' )');
183 183
 			}
184 184
 
185 185
 			// if content length is sent by client:
@@ -188,7 +188,7 @@  discard block
 block discarded – undo
188 188
 			if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
189 189
 				$expected = (int) $_SERVER['CONTENT_LENGTH'];
190 190
 				if ($count !== $expected) {
191
-					throw new BadRequest('expected filesize ' . $expected . ' got ' . $count);
191
+					throw new BadRequest('expected filesize '.$expected.' got '.$count);
192 192
 				}
193 193
 			}
194 194
 
@@ -220,7 +220,7 @@  discard block
 block discarded – undo
220 220
 					$renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath);
221 221
 					$fileExists = $storage->file_exists($internalPath);
222 222
 					if ($renameOkay === false || $fileExists === false) {
223
-						\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']);
223
+						\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']);
224 224
 						throw new Exception('Could not rename part file to final file');
225 225
 					}
226 226
 				} catch (ForbiddenException $ex) {
@@ -264,10 +264,10 @@  discard block
 block discarded – undo
264 264
 			}
265 265
 
266 266
 		} catch (StorageNotAvailableException $e) {
267
-			throw new ServiceUnavailable("Failed to check file size: " . $e->getMessage());
267
+			throw new ServiceUnavailable("Failed to check file size: ".$e->getMessage());
268 268
 		}
269 269
 
270
-		return '"' . $this->info->getEtag() . '"';
270
+		return '"'.$this->info->getEtag().'"';
271 271
 	}
272 272
 
273 273
 	private function getPartFileBasePath($path) {
@@ -354,9 +354,9 @@  discard block
 block discarded – undo
354 354
 			return $res;
355 355
 		} catch (GenericEncryptionException $e) {
356 356
 			// returning 503 will allow retry of the operation at a later point in time
357
-			throw new ServiceUnavailable("Encryption not ready: " . $e->getMessage());
357
+			throw new ServiceUnavailable("Encryption not ready: ".$e->getMessage());
358 358
 		} catch (StorageNotAvailableException $e) {
359
-			throw new ServiceUnavailable("Failed to open file: " . $e->getMessage());
359
+			throw new ServiceUnavailable("Failed to open file: ".$e->getMessage());
360 360
 		} catch (ForbiddenException $ex) {
361 361
 			throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
362 362
 		} catch (LockedException $e) {
@@ -381,7 +381,7 @@  discard block
 block discarded – undo
381 381
 				throw new Forbidden();
382 382
 			}
383 383
 		} catch (StorageNotAvailableException $e) {
384
-			throw new ServiceUnavailable("Failed to unlink: " . $e->getMessage());
384
+			throw new ServiceUnavailable("Failed to unlink: ".$e->getMessage());
385 385
 		} catch (ForbiddenException $ex) {
386 386
 			throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
387 387
 		} catch (LockedException $e) {
@@ -448,7 +448,7 @@  discard block
 block discarded – undo
448 448
 				if ($bytesWritten !== $expected) {
449 449
 					$chunk_handler->remove($info['index']);
450 450
 					throw new BadRequest(
451
-						'expected filesize ' . $expected . ' got ' . $bytesWritten);
451
+						'expected filesize '.$expected.' got '.$bytesWritten);
452 452
 				}
453 453
 			}
454 454
 		}
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
 			$needsPartFile = $storage->needsPartFile();
460 460
 			$partFile = null;
461 461
 
462
-			$targetPath = $path . '/' . $info['name'];
462
+			$targetPath = $path.'/'.$info['name'];
463 463
 			/** @var \OC\Files\Storage\Storage $targetStorage */
464 464
 			list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);
465 465
 
@@ -475,7 +475,7 @@  discard block
 block discarded – undo
475 475
 
476 476
 				if ($needsPartFile) {
477 477
 					// we first assembly the target file as a part file
478
-					$partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part';
478
+					$partFile = $this->getPartFileBasePath($path.'/'.$info['name']).'.ocTransferId'.$info['transferid'].'.part';
479 479
 					/** @var \OC\Files\Storage\Storage $targetStorage */
480 480
 					list($partStorage, $partInternalPath) = $this->fileView->resolvePath($partFile);
481 481
 
@@ -579,10 +579,10 @@  discard block
 block discarded – undo
579 579
 		}
580 580
 		if ($e instanceof GenericEncryptionException) {
581 581
 			// returning 503 will allow retry of the operation at a later point in time
582
-			throw new ServiceUnavailable('Encryption not ready: ' . $e->getMessage(), 0, $e);
582
+			throw new ServiceUnavailable('Encryption not ready: '.$e->getMessage(), 0, $e);
583 583
 		}
584 584
 		if ($e instanceof StorageNotAvailableException) {
585
-			throw new ServiceUnavailable('Failed to write file contents: ' . $e->getMessage(), 0, $e);
585
+			throw new ServiceUnavailable('Failed to write file contents: '.$e->getMessage(), 0, $e);
586 586
 		}
587 587
 
588 588
 		throw new \Sabre\DAV\Exception($e->getMessage(), 0, $e);
Please login to merge, or discard this patch.
Indentation   +531 added lines, -531 removed lines patch added patch discarded remove patch
@@ -66,536 +66,536 @@
 block discarded – undo
66 66
 
67 67
 class File extends Node implements IFile {
68 68
 
69
-	protected $request;
70
-
71
-	/**
72
-	 * Sets up the node, expects a full path name
73
-	 *
74
-	 * @param \OC\Files\View $view
75
-	 * @param \OCP\Files\FileInfo $info
76
-	 * @param \OCP\Share\IManager $shareManager
77
-	 * @param \OC\AppFramework\Http\Request $request
78
-	 */
79
-	public function __construct(View $view, FileInfo $info, IManager $shareManager = null, Request $request = null) {
80
-		parent::__construct($view, $info, $shareManager);
81
-
82
-		if (isset($request)) {
83
-			$this->request = $request;
84
-		} else {
85
-			$this->request = \OC::$server->getRequest();
86
-		}
87
-	}
88
-
89
-	/**
90
-	 * Updates the data
91
-	 *
92
-	 * The data argument is a readable stream resource.
93
-	 *
94
-	 * After a successful put operation, you may choose to return an ETag. The
95
-	 * etag must always be surrounded by double-quotes. These quotes must
96
-	 * appear in the actual string you're returning.
97
-	 *
98
-	 * Clients may use the ETag from a PUT request to later on make sure that
99
-	 * when they update the file, the contents haven't changed in the mean
100
-	 * time.
101
-	 *
102
-	 * If you don't plan to store the file byte-by-byte, and you return a
103
-	 * different object on a subsequent GET you are strongly recommended to not
104
-	 * return an ETag, and just return null.
105
-	 *
106
-	 * @param resource $data
107
-	 *
108
-	 * @throws Forbidden
109
-	 * @throws UnsupportedMediaType
110
-	 * @throws BadRequest
111
-	 * @throws Exception
112
-	 * @throws EntityTooLarge
113
-	 * @throws ServiceUnavailable
114
-	 * @throws FileLocked
115
-	 * @return string|null
116
-	 */
117
-	public function put($data) {
118
-		try {
119
-			$exists = $this->fileView->file_exists($this->path);
120
-			if ($this->info && $exists && !$this->info->isUpdateable()) {
121
-				throw new Forbidden();
122
-			}
123
-		} catch (StorageNotAvailableException $e) {
124
-			throw new ServiceUnavailable("File is not updatable: " . $e->getMessage());
125
-		}
126
-
127
-		// verify path of the target
128
-		$this->verifyPath();
129
-
130
-		// chunked handling
131
-		if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
132
-			try {
133
-				return $this->createFileChunked($data);
134
-			} catch (\Exception $e) {
135
-				$this->convertToSabreException($e);
136
-			}
137
-		}
138
-
139
-		/** @var Storage $partStorage */
140
-		list($partStorage) = $this->fileView->resolvePath($this->path);
141
-		$needsPartFile = $partStorage->needsPartFile() && (strlen($this->path) > 1);
142
-
143
-		if ($needsPartFile) {
144
-			// mark file as partial while uploading (ignored by the scanner)
145
-			$partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part';
146
-		} else {
147
-			// upload file directly as the final path
148
-			$partFilePath = $this->path;
149
-
150
-			$this->emitPreHooks($exists);
151
-		}
152
-
153
-		$view = \OC\Files\Filesystem::getView();
154
-
155
-		// the part file and target file might be on a different storage in case of a single file storage (e.g. single file share)
156
-		/** @var \OC\Files\Storage\Storage $partStorage */
157
-		list($partStorage, $internalPartPath) = $this->fileView->resolvePath($partFilePath);
158
-		/** @var \OC\Files\Storage\Storage $storage */
159
-		list($storage, $internalPath) = $this->fileView->resolvePath($this->path);
160
-		try {
161
-			if (!$needsPartFile) {
162
-				if ($view) {
163
-					$this->emitPreHooks($exists);
164
-				}
165
-				$this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
166
-			}
167
-
168
-			$target = $partStorage->fopen($internalPartPath, 'wb');
169
-			if ($target === false) {
170
-				\OC::$server->getLogger()->error('\OC\Files\Filesystem::fopen() failed', ['app' => 'webdav']);
171
-				// because we have no clue about the cause we can only throw back a 500/Internal Server Error
172
-				throw new Exception('Could not write file contents');
173
-			}
174
-			list($count, $result) = \OC_Helper::streamCopy($data, $target);
175
-			fclose($target);
176
-
177
-			if ($result === false) {
178
-				$expected = -1;
179
-				if (isset($_SERVER['CONTENT_LENGTH'])) {
180
-					$expected = $_SERVER['CONTENT_LENGTH'];
181
-				}
182
-				throw new Exception('Error while copying file to target location (copied bytes: ' . $count . ', expected filesize: ' . $expected . ' )');
183
-			}
184
-
185
-			// if content length is sent by client:
186
-			// double check if the file was fully received
187
-			// compare expected and actual size
188
-			if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
189
-				$expected = (int) $_SERVER['CONTENT_LENGTH'];
190
-				if ($count !== $expected) {
191
-					throw new BadRequest('expected filesize ' . $expected . ' got ' . $count);
192
-				}
193
-			}
194
-
195
-		} catch (\Exception $e) {
196
-			if ($needsPartFile) {
197
-				$partStorage->unlink($internalPartPath);
198
-			}
199
-			$this->convertToSabreException($e);
200
-		}
201
-
202
-		try {
203
-			if ($needsPartFile) {
204
-				if ($view) {
205
-					$this->emitPreHooks($exists);
206
-				}
207
-				try {
208
-					$this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
209
-				} catch (LockedException $e) {
210
-					if ($needsPartFile) {
211
-						$partStorage->unlink($internalPartPath);
212
-					}
213
-					throw new FileLocked($e->getMessage(), $e->getCode(), $e);
214
-				}
215
-
216
-				// rename to correct path
217
-				try {
218
-					$renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath);
219
-					$fileExists = $storage->file_exists($internalPath);
220
-					if ($renameOkay === false || $fileExists === false) {
221
-						\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']);
222
-						throw new Exception('Could not rename part file to final file');
223
-					}
224
-				} catch (ForbiddenException $ex) {
225
-					throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
226
-				} catch (\Exception $e) {
227
-					$partStorage->unlink($internalPartPath);
228
-					$this->convertToSabreException($e);
229
-				}
230
-			}
231
-
232
-			// since we skipped the view we need to scan and emit the hooks ourselves
233
-			$storage->getUpdater()->update($internalPath);
234
-
235
-			try {
236
-				$this->changeLock(ILockingProvider::LOCK_SHARED);
237
-			} catch (LockedException $e) {
238
-				throw new FileLocked($e->getMessage(), $e->getCode(), $e);
239
-			}
240
-
241
-			// allow sync clients to send the mtime along in a header
242
-			if (isset($this->request->server['HTTP_X_OC_MTIME'])) {
243
-				$mtime = $this->sanitizeMtime($this->request->server['HTTP_X_OC_MTIME']);
244
-				if ($this->fileView->touch($this->path, $mtime)) {
245
-					$this->header('X-OC-MTime: accepted');
246
-				}
247
-			}
69
+    protected $request;
70
+
71
+    /**
72
+     * Sets up the node, expects a full path name
73
+     *
74
+     * @param \OC\Files\View $view
75
+     * @param \OCP\Files\FileInfo $info
76
+     * @param \OCP\Share\IManager $shareManager
77
+     * @param \OC\AppFramework\Http\Request $request
78
+     */
79
+    public function __construct(View $view, FileInfo $info, IManager $shareManager = null, Request $request = null) {
80
+        parent::__construct($view, $info, $shareManager);
81
+
82
+        if (isset($request)) {
83
+            $this->request = $request;
84
+        } else {
85
+            $this->request = \OC::$server->getRequest();
86
+        }
87
+    }
88
+
89
+    /**
90
+     * Updates the data
91
+     *
92
+     * The data argument is a readable stream resource.
93
+     *
94
+     * After a successful put operation, you may choose to return an ETag. The
95
+     * etag must always be surrounded by double-quotes. These quotes must
96
+     * appear in the actual string you're returning.
97
+     *
98
+     * Clients may use the ETag from a PUT request to later on make sure that
99
+     * when they update the file, the contents haven't changed in the mean
100
+     * time.
101
+     *
102
+     * If you don't plan to store the file byte-by-byte, and you return a
103
+     * different object on a subsequent GET you are strongly recommended to not
104
+     * return an ETag, and just return null.
105
+     *
106
+     * @param resource $data
107
+     *
108
+     * @throws Forbidden
109
+     * @throws UnsupportedMediaType
110
+     * @throws BadRequest
111
+     * @throws Exception
112
+     * @throws EntityTooLarge
113
+     * @throws ServiceUnavailable
114
+     * @throws FileLocked
115
+     * @return string|null
116
+     */
117
+    public function put($data) {
118
+        try {
119
+            $exists = $this->fileView->file_exists($this->path);
120
+            if ($this->info && $exists && !$this->info->isUpdateable()) {
121
+                throw new Forbidden();
122
+            }
123
+        } catch (StorageNotAvailableException $e) {
124
+            throw new ServiceUnavailable("File is not updatable: " . $e->getMessage());
125
+        }
126
+
127
+        // verify path of the target
128
+        $this->verifyPath();
129
+
130
+        // chunked handling
131
+        if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
132
+            try {
133
+                return $this->createFileChunked($data);
134
+            } catch (\Exception $e) {
135
+                $this->convertToSabreException($e);
136
+            }
137
+        }
138
+
139
+        /** @var Storage $partStorage */
140
+        list($partStorage) = $this->fileView->resolvePath($this->path);
141
+        $needsPartFile = $partStorage->needsPartFile() && (strlen($this->path) > 1);
142
+
143
+        if ($needsPartFile) {
144
+            // mark file as partial while uploading (ignored by the scanner)
145
+            $partFilePath = $this->getPartFileBasePath($this->path) . '.ocTransferId' . rand() . '.part';
146
+        } else {
147
+            // upload file directly as the final path
148
+            $partFilePath = $this->path;
149
+
150
+            $this->emitPreHooks($exists);
151
+        }
152
+
153
+        $view = \OC\Files\Filesystem::getView();
154
+
155
+        // the part file and target file might be on a different storage in case of a single file storage (e.g. single file share)
156
+        /** @var \OC\Files\Storage\Storage $partStorage */
157
+        list($partStorage, $internalPartPath) = $this->fileView->resolvePath($partFilePath);
158
+        /** @var \OC\Files\Storage\Storage $storage */
159
+        list($storage, $internalPath) = $this->fileView->resolvePath($this->path);
160
+        try {
161
+            if (!$needsPartFile) {
162
+                if ($view) {
163
+                    $this->emitPreHooks($exists);
164
+                }
165
+                $this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
166
+            }
167
+
168
+            $target = $partStorage->fopen($internalPartPath, 'wb');
169
+            if ($target === false) {
170
+                \OC::$server->getLogger()->error('\OC\Files\Filesystem::fopen() failed', ['app' => 'webdav']);
171
+                // because we have no clue about the cause we can only throw back a 500/Internal Server Error
172
+                throw new Exception('Could not write file contents');
173
+            }
174
+            list($count, $result) = \OC_Helper::streamCopy($data, $target);
175
+            fclose($target);
176
+
177
+            if ($result === false) {
178
+                $expected = -1;
179
+                if (isset($_SERVER['CONTENT_LENGTH'])) {
180
+                    $expected = $_SERVER['CONTENT_LENGTH'];
181
+                }
182
+                throw new Exception('Error while copying file to target location (copied bytes: ' . $count . ', expected filesize: ' . $expected . ' )');
183
+            }
184
+
185
+            // if content length is sent by client:
186
+            // double check if the file was fully received
187
+            // compare expected and actual size
188
+            if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
189
+                $expected = (int) $_SERVER['CONTENT_LENGTH'];
190
+                if ($count !== $expected) {
191
+                    throw new BadRequest('expected filesize ' . $expected . ' got ' . $count);
192
+                }
193
+            }
194
+
195
+        } catch (\Exception $e) {
196
+            if ($needsPartFile) {
197
+                $partStorage->unlink($internalPartPath);
198
+            }
199
+            $this->convertToSabreException($e);
200
+        }
201
+
202
+        try {
203
+            if ($needsPartFile) {
204
+                if ($view) {
205
+                    $this->emitPreHooks($exists);
206
+                }
207
+                try {
208
+                    $this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);
209
+                } catch (LockedException $e) {
210
+                    if ($needsPartFile) {
211
+                        $partStorage->unlink($internalPartPath);
212
+                    }
213
+                    throw new FileLocked($e->getMessage(), $e->getCode(), $e);
214
+                }
215
+
216
+                // rename to correct path
217
+                try {
218
+                    $renameOkay = $storage->moveFromStorage($partStorage, $internalPartPath, $internalPath);
219
+                    $fileExists = $storage->file_exists($internalPath);
220
+                    if ($renameOkay === false || $fileExists === false) {
221
+                        \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']);
222
+                        throw new Exception('Could not rename part file to final file');
223
+                    }
224
+                } catch (ForbiddenException $ex) {
225
+                    throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
226
+                } catch (\Exception $e) {
227
+                    $partStorage->unlink($internalPartPath);
228
+                    $this->convertToSabreException($e);
229
+                }
230
+            }
231
+
232
+            // since we skipped the view we need to scan and emit the hooks ourselves
233
+            $storage->getUpdater()->update($internalPath);
234
+
235
+            try {
236
+                $this->changeLock(ILockingProvider::LOCK_SHARED);
237
+            } catch (LockedException $e) {
238
+                throw new FileLocked($e->getMessage(), $e->getCode(), $e);
239
+            }
240
+
241
+            // allow sync clients to send the mtime along in a header
242
+            if (isset($this->request->server['HTTP_X_OC_MTIME'])) {
243
+                $mtime = $this->sanitizeMtime($this->request->server['HTTP_X_OC_MTIME']);
244
+                if ($this->fileView->touch($this->path, $mtime)) {
245
+                    $this->header('X-OC-MTime: accepted');
246
+                }
247
+            }
248 248
 					
249
-			if ($view) {
250
-				$this->emitPostHooks($exists);
251
-			}
252
-
253
-			$this->refreshInfo();
254
-
255
-			if (isset($this->request->server['HTTP_OC_CHECKSUM'])) {
256
-				$checksum = trim($this->request->server['HTTP_OC_CHECKSUM']);
257
-				$this->fileView->putFileInfo($this->path, ['checksum' => $checksum]);
258
-				$this->refreshInfo();
259
-			} else if ($this->getChecksum() !== null && $this->getChecksum() !== '') {
260
-				$this->fileView->putFileInfo($this->path, ['checksum' => '']);
261
-				$this->refreshInfo();
262
-			}
263
-
264
-		} catch (StorageNotAvailableException $e) {
265
-			throw new ServiceUnavailable("Failed to check file size: " . $e->getMessage());
266
-		}
267
-
268
-		return '"' . $this->info->getEtag() . '"';
269
-	}
270
-
271
-	private function getPartFileBasePath($path) {
272
-		$partFileInStorage = \OC::$server->getConfig()->getSystemValue('part_file_in_storage', true);
273
-		if ($partFileInStorage) {
274
-			return $path;
275
-		} else {
276
-			return md5($path); // will place it in the root of the view with a unique name
277
-		}
278
-	}
279
-
280
-	/**
281
-	 * @param string $path
282
-	 */
283
-	private function emitPreHooks($exists, $path = null) {
284
-		if (is_null($path)) {
285
-			$path = $this->path;
286
-		}
287
-		$hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
288
-		$run = true;
289
-
290
-		if (!$exists) {
291
-			\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_create, array(
292
-				\OC\Files\Filesystem::signal_param_path => $hookPath,
293
-				\OC\Files\Filesystem::signal_param_run => &$run,
294
-			));
295
-		} else {
296
-			\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_update, array(
297
-				\OC\Files\Filesystem::signal_param_path => $hookPath,
298
-				\OC\Files\Filesystem::signal_param_run => &$run,
299
-			));
300
-		}
301
-		\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_write, array(
302
-			\OC\Files\Filesystem::signal_param_path => $hookPath,
303
-			\OC\Files\Filesystem::signal_param_run => &$run,
304
-		));
305
-		return $run;
306
-	}
307
-
308
-	/**
309
-	 * @param string $path
310
-	 */
311
-	private function emitPostHooks($exists, $path = null) {
312
-		if (is_null($path)) {
313
-			$path = $this->path;
314
-		}
315
-		$hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
316
-		if (!$exists) {
317
-			\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_create, array(
318
-				\OC\Files\Filesystem::signal_param_path => $hookPath
319
-			));
320
-		} else {
321
-			\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_update, array(
322
-				\OC\Files\Filesystem::signal_param_path => $hookPath
323
-			));
324
-		}
325
-		\OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_write, array(
326
-			\OC\Files\Filesystem::signal_param_path => $hookPath
327
-		));
328
-	}
329
-
330
-	/**
331
-	 * Returns the data
332
-	 *
333
-	 * @return resource
334
-	 * @throws Forbidden
335
-	 * @throws ServiceUnavailable
336
-	 */
337
-	public function get() {
338
-		//throw exception if encryption is disabled but files are still encrypted
339
-		try {
340
-			if (!$this->info->isReadable()) {
341
-				// do a if the file did not exist
342
-				throw new NotFound();
343
-			}
344
-			try {
345
-				$res = $this->fileView->fopen(ltrim($this->path, '/'), 'rb');
346
-			} catch (\Exception $e) {
347
-				$this->convertToSabreException($e);
348
-			}
349
-			if ($res === false) {
350
-				throw new ServiceUnavailable("Could not open file");
351
-			}
352
-			return $res;
353
-		} catch (GenericEncryptionException $e) {
354
-			// returning 503 will allow retry of the operation at a later point in time
355
-			throw new ServiceUnavailable("Encryption not ready: " . $e->getMessage());
356
-		} catch (StorageNotAvailableException $e) {
357
-			throw new ServiceUnavailable("Failed to open file: " . $e->getMessage());
358
-		} catch (ForbiddenException $ex) {
359
-			throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
360
-		} catch (LockedException $e) {
361
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
362
-		}
363
-	}
364
-
365
-	/**
366
-	 * Delete the current file
367
-	 *
368
-	 * @throws Forbidden
369
-	 * @throws ServiceUnavailable
370
-	 */
371
-	public function delete() {
372
-		if (!$this->info->isDeletable()) {
373
-			throw new Forbidden();
374
-		}
375
-
376
-		try {
377
-			if (!$this->fileView->unlink($this->path)) {
378
-				// assume it wasn't possible to delete due to permissions
379
-				throw new Forbidden();
380
-			}
381
-		} catch (StorageNotAvailableException $e) {
382
-			throw new ServiceUnavailable("Failed to unlink: " . $e->getMessage());
383
-		} catch (ForbiddenException $ex) {
384
-			throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
385
-		} catch (LockedException $e) {
386
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
387
-		}
388
-	}
389
-
390
-	/**
391
-	 * Returns the mime-type for a file
392
-	 *
393
-	 * If null is returned, we'll assume application/octet-stream
394
-	 *
395
-	 * @return string
396
-	 */
397
-	public function getContentType() {
398
-		$mimeType = $this->info->getMimetype();
399
-
400
-		// PROPFIND needs to return the correct mime type, for consistency with the web UI
401
-		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PROPFIND') {
402
-			return $mimeType;
403
-		}
404
-		return \OC::$server->getMimeTypeDetector()->getSecureMimeType($mimeType);
405
-	}
406
-
407
-	/**
408
-	 * @return array|false
409
-	 */
410
-	public function getDirectDownload() {
411
-		if (\OCP\App::isEnabled('encryption')) {
412
-			return [];
413
-		}
414
-		/** @var \OCP\Files\Storage $storage */
415
-		list($storage, $internalPath) = $this->fileView->resolvePath($this->path);
416
-		if (is_null($storage)) {
417
-			return [];
418
-		}
419
-
420
-		return $storage->getDirectDownload($internalPath);
421
-	}
422
-
423
-	/**
424
-	 * @param resource $data
425
-	 * @return null|string
426
-	 * @throws Exception
427
-	 * @throws BadRequest
428
-	 * @throws NotImplemented
429
-	 * @throws ServiceUnavailable
430
-	 */
431
-	private function createFileChunked($data) {
432
-		list($path, $name) = \Sabre\Uri\split($this->path);
433
-
434
-		$info = \OC_FileChunking::decodeName($name);
435
-		if (empty($info)) {
436
-			throw new NotImplemented('Invalid chunk name');
437
-		}
438
-
439
-		$chunk_handler = new \OC_FileChunking($info);
440
-		$bytesWritten = $chunk_handler->store($info['index'], $data);
441
-
442
-		//detect aborted upload
443
-		if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
444
-			if (isset($_SERVER['CONTENT_LENGTH'])) {
445
-				$expected = (int) $_SERVER['CONTENT_LENGTH'];
446
-				if ($bytesWritten !== $expected) {
447
-					$chunk_handler->remove($info['index']);
448
-					throw new BadRequest(
449
-						'expected filesize ' . $expected . ' got ' . $bytesWritten);
450
-				}
451
-			}
452
-		}
453
-
454
-		if ($chunk_handler->isComplete()) {
455
-			/** @var Storage $storage */
456
-			list($storage,) = $this->fileView->resolvePath($path);
457
-			$needsPartFile = $storage->needsPartFile();
458
-			$partFile = null;
459
-
460
-			$targetPath = $path . '/' . $info['name'];
461
-			/** @var \OC\Files\Storage\Storage $targetStorage */
462
-			list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);
463
-
464
-			$exists = $this->fileView->file_exists($targetPath);
465
-
466
-			try {
467
-				$this->fileView->lockFile($targetPath, ILockingProvider::LOCK_SHARED);
468
-
469
-				$this->emitPreHooks($exists, $targetPath);
470
-				$this->fileView->changeLock($targetPath, ILockingProvider::LOCK_EXCLUSIVE);
471
-				/** @var \OC\Files\Storage\Storage $targetStorage */
472
-				list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);
473
-
474
-				if ($needsPartFile) {
475
-					// we first assembly the target file as a part file
476
-					$partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part';
477
-					/** @var \OC\Files\Storage\Storage $targetStorage */
478
-					list($partStorage, $partInternalPath) = $this->fileView->resolvePath($partFile);
479
-
480
-
481
-					$chunk_handler->file_assemble($partStorage, $partInternalPath);
482
-
483
-					// here is the final atomic rename
484
-					$renameOkay = $targetStorage->moveFromStorage($partStorage, $partInternalPath, $targetInternalPath);
485
-					$fileExists = $targetStorage->file_exists($targetInternalPath);
486
-					if ($renameOkay === false || $fileExists === false) {
487
-						\OC::$server->getLogger()->error('\OC\Files\Filesystem::rename() failed', ['app' => 'webdav']);
488
-						// only delete if an error occurred and the target file was already created
489
-						if ($fileExists) {
490
-							// set to null to avoid double-deletion when handling exception
491
-							// stray part file
492
-							$partFile = null;
493
-							$targetStorage->unlink($targetInternalPath);
494
-						}
495
-						$this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
496
-						throw new Exception('Could not rename part file assembled from chunks');
497
-					}
498
-				} else {
499
-					// assemble directly into the final file
500
-					$chunk_handler->file_assemble($targetStorage, $targetInternalPath);
501
-				}
502
-
503
-				// allow sync clients to send the mtime along in a header
504
-				if (isset($this->request->server['HTTP_X_OC_MTIME'])) {
505
-					$mtime = $this->sanitizeMtime($this->request->server['HTTP_X_OC_MTIME']);
506
-					if ($targetStorage->touch($targetInternalPath, $mtime)) {
507
-						$this->header('X-OC-MTime: accepted');
508
-					}
509
-				}
510
-
511
-				// since we skipped the view we need to scan and emit the hooks ourselves
512
-				$targetStorage->getUpdater()->update($targetInternalPath);
513
-
514
-				$this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
515
-
516
-				$this->emitPostHooks($exists, $targetPath);
517
-
518
-				// FIXME: should call refreshInfo but can't because $this->path is not the of the final file
519
-				$info = $this->fileView->getFileInfo($targetPath);
520
-
521
-				if (isset($this->request->server['HTTP_OC_CHECKSUM'])) {
522
-					$checksum = trim($this->request->server['HTTP_OC_CHECKSUM']);
523
-					$this->fileView->putFileInfo($targetPath, ['checksum' => $checksum]);
524
-				} else if ($info->getChecksum() !== null && $info->getChecksum() !== '') {
525
-					$this->fileView->putFileInfo($this->path, ['checksum' => '']);
526
-				}
527
-
528
-				$this->fileView->unlockFile($targetPath, ILockingProvider::LOCK_SHARED);
529
-
530
-				return $info->getEtag();
531
-			} catch (\Exception $e) {
532
-				if ($partFile !== null) {
533
-					$targetStorage->unlink($targetInternalPath);
534
-				}
535
-				$this->convertToSabreException($e);
536
-			}
537
-		}
538
-
539
-		return null;
540
-	}
541
-
542
-	/**
543
-	 * Convert the given exception to a SabreException instance
544
-	 *
545
-	 * @param \Exception $e
546
-	 *
547
-	 * @throws \Sabre\DAV\Exception
548
-	 */
549
-	private function convertToSabreException(\Exception $e) {
550
-		if ($e instanceof \Sabre\DAV\Exception) {
551
-			throw $e;
552
-		}
553
-		if ($e instanceof NotPermittedException) {
554
-			// a more general case - due to whatever reason the content could not be written
555
-			throw new Forbidden($e->getMessage(), 0, $e);
556
-		}
557
-		if ($e instanceof ForbiddenException) {
558
-			// the path for the file was forbidden
559
-			throw new DAVForbiddenException($e->getMessage(), $e->getRetry(), $e);
560
-		}
561
-		if ($e instanceof EntityTooLargeException) {
562
-			// the file is too big to be stored
563
-			throw new EntityTooLarge($e->getMessage(), 0, $e);
564
-		}
565
-		if ($e instanceof InvalidContentException) {
566
-			// the file content is not permitted
567
-			throw new UnsupportedMediaType($e->getMessage(), 0, $e);
568
-		}
569
-		if ($e instanceof InvalidPathException) {
570
-			// the path for the file was not valid
571
-			// TODO: find proper http status code for this case
572
-			throw new Forbidden($e->getMessage(), 0, $e);
573
-		}
574
-		if ($e instanceof LockedException || $e instanceof LockNotAcquiredException) {
575
-			// the file is currently being written to by another process
576
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
577
-		}
578
-		if ($e instanceof GenericEncryptionException) {
579
-			// returning 503 will allow retry of the operation at a later point in time
580
-			throw new ServiceUnavailable('Encryption not ready: ' . $e->getMessage(), 0, $e);
581
-		}
582
-		if ($e instanceof StorageNotAvailableException) {
583
-			throw new ServiceUnavailable('Failed to write file contents: ' . $e->getMessage(), 0, $e);
584
-		}
585
-
586
-		throw new \Sabre\DAV\Exception($e->getMessage(), 0, $e);
587
-	}
588
-
589
-	/**
590
-	 * Get the checksum for this file
591
-	 *
592
-	 * @return string
593
-	 */
594
-	public function getChecksum() {
595
-		return $this->info->getChecksum();
596
-	}
597
-
598
-	protected function header($string) {
599
-		\header($string);
600
-	}
249
+            if ($view) {
250
+                $this->emitPostHooks($exists);
251
+            }
252
+
253
+            $this->refreshInfo();
254
+
255
+            if (isset($this->request->server['HTTP_OC_CHECKSUM'])) {
256
+                $checksum = trim($this->request->server['HTTP_OC_CHECKSUM']);
257
+                $this->fileView->putFileInfo($this->path, ['checksum' => $checksum]);
258
+                $this->refreshInfo();
259
+            } else if ($this->getChecksum() !== null && $this->getChecksum() !== '') {
260
+                $this->fileView->putFileInfo($this->path, ['checksum' => '']);
261
+                $this->refreshInfo();
262
+            }
263
+
264
+        } catch (StorageNotAvailableException $e) {
265
+            throw new ServiceUnavailable("Failed to check file size: " . $e->getMessage());
266
+        }
267
+
268
+        return '"' . $this->info->getEtag() . '"';
269
+    }
270
+
271
+    private function getPartFileBasePath($path) {
272
+        $partFileInStorage = \OC::$server->getConfig()->getSystemValue('part_file_in_storage', true);
273
+        if ($partFileInStorage) {
274
+            return $path;
275
+        } else {
276
+            return md5($path); // will place it in the root of the view with a unique name
277
+        }
278
+    }
279
+
280
+    /**
281
+     * @param string $path
282
+     */
283
+    private function emitPreHooks($exists, $path = null) {
284
+        if (is_null($path)) {
285
+            $path = $this->path;
286
+        }
287
+        $hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
288
+        $run = true;
289
+
290
+        if (!$exists) {
291
+            \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_create, array(
292
+                \OC\Files\Filesystem::signal_param_path => $hookPath,
293
+                \OC\Files\Filesystem::signal_param_run => &$run,
294
+            ));
295
+        } else {
296
+            \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_update, array(
297
+                \OC\Files\Filesystem::signal_param_path => $hookPath,
298
+                \OC\Files\Filesystem::signal_param_run => &$run,
299
+            ));
300
+        }
301
+        \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_write, array(
302
+            \OC\Files\Filesystem::signal_param_path => $hookPath,
303
+            \OC\Files\Filesystem::signal_param_run => &$run,
304
+        ));
305
+        return $run;
306
+    }
307
+
308
+    /**
309
+     * @param string $path
310
+     */
311
+    private function emitPostHooks($exists, $path = null) {
312
+        if (is_null($path)) {
313
+            $path = $this->path;
314
+        }
315
+        $hookPath = Filesystem::getView()->getRelativePath($this->fileView->getAbsolutePath($path));
316
+        if (!$exists) {
317
+            \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_create, array(
318
+                \OC\Files\Filesystem::signal_param_path => $hookPath
319
+            ));
320
+        } else {
321
+            \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_update, array(
322
+                \OC\Files\Filesystem::signal_param_path => $hookPath
323
+            ));
324
+        }
325
+        \OC_Hook::emit(\OC\Files\Filesystem::CLASSNAME, \OC\Files\Filesystem::signal_post_write, array(
326
+            \OC\Files\Filesystem::signal_param_path => $hookPath
327
+        ));
328
+    }
329
+
330
+    /**
331
+     * Returns the data
332
+     *
333
+     * @return resource
334
+     * @throws Forbidden
335
+     * @throws ServiceUnavailable
336
+     */
337
+    public function get() {
338
+        //throw exception if encryption is disabled but files are still encrypted
339
+        try {
340
+            if (!$this->info->isReadable()) {
341
+                // do a if the file did not exist
342
+                throw new NotFound();
343
+            }
344
+            try {
345
+                $res = $this->fileView->fopen(ltrim($this->path, '/'), 'rb');
346
+            } catch (\Exception $e) {
347
+                $this->convertToSabreException($e);
348
+            }
349
+            if ($res === false) {
350
+                throw new ServiceUnavailable("Could not open file");
351
+            }
352
+            return $res;
353
+        } catch (GenericEncryptionException $e) {
354
+            // returning 503 will allow retry of the operation at a later point in time
355
+            throw new ServiceUnavailable("Encryption not ready: " . $e->getMessage());
356
+        } catch (StorageNotAvailableException $e) {
357
+            throw new ServiceUnavailable("Failed to open file: " . $e->getMessage());
358
+        } catch (ForbiddenException $ex) {
359
+            throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
360
+        } catch (LockedException $e) {
361
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
362
+        }
363
+    }
364
+
365
+    /**
366
+     * Delete the current file
367
+     *
368
+     * @throws Forbidden
369
+     * @throws ServiceUnavailable
370
+     */
371
+    public function delete() {
372
+        if (!$this->info->isDeletable()) {
373
+            throw new Forbidden();
374
+        }
375
+
376
+        try {
377
+            if (!$this->fileView->unlink($this->path)) {
378
+                // assume it wasn't possible to delete due to permissions
379
+                throw new Forbidden();
380
+            }
381
+        } catch (StorageNotAvailableException $e) {
382
+            throw new ServiceUnavailable("Failed to unlink: " . $e->getMessage());
383
+        } catch (ForbiddenException $ex) {
384
+            throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
385
+        } catch (LockedException $e) {
386
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
387
+        }
388
+    }
389
+
390
+    /**
391
+     * Returns the mime-type for a file
392
+     *
393
+     * If null is returned, we'll assume application/octet-stream
394
+     *
395
+     * @return string
396
+     */
397
+    public function getContentType() {
398
+        $mimeType = $this->info->getMimetype();
399
+
400
+        // PROPFIND needs to return the correct mime type, for consistency with the web UI
401
+        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PROPFIND') {
402
+            return $mimeType;
403
+        }
404
+        return \OC::$server->getMimeTypeDetector()->getSecureMimeType($mimeType);
405
+    }
406
+
407
+    /**
408
+     * @return array|false
409
+     */
410
+    public function getDirectDownload() {
411
+        if (\OCP\App::isEnabled('encryption')) {
412
+            return [];
413
+        }
414
+        /** @var \OCP\Files\Storage $storage */
415
+        list($storage, $internalPath) = $this->fileView->resolvePath($this->path);
416
+        if (is_null($storage)) {
417
+            return [];
418
+        }
419
+
420
+        return $storage->getDirectDownload($internalPath);
421
+    }
422
+
423
+    /**
424
+     * @param resource $data
425
+     * @return null|string
426
+     * @throws Exception
427
+     * @throws BadRequest
428
+     * @throws NotImplemented
429
+     * @throws ServiceUnavailable
430
+     */
431
+    private function createFileChunked($data) {
432
+        list($path, $name) = \Sabre\Uri\split($this->path);
433
+
434
+        $info = \OC_FileChunking::decodeName($name);
435
+        if (empty($info)) {
436
+            throw new NotImplemented('Invalid chunk name');
437
+        }
438
+
439
+        $chunk_handler = new \OC_FileChunking($info);
440
+        $bytesWritten = $chunk_handler->store($info['index'], $data);
441
+
442
+        //detect aborted upload
443
+        if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
444
+            if (isset($_SERVER['CONTENT_LENGTH'])) {
445
+                $expected = (int) $_SERVER['CONTENT_LENGTH'];
446
+                if ($bytesWritten !== $expected) {
447
+                    $chunk_handler->remove($info['index']);
448
+                    throw new BadRequest(
449
+                        'expected filesize ' . $expected . ' got ' . $bytesWritten);
450
+                }
451
+            }
452
+        }
453
+
454
+        if ($chunk_handler->isComplete()) {
455
+            /** @var Storage $storage */
456
+            list($storage,) = $this->fileView->resolvePath($path);
457
+            $needsPartFile = $storage->needsPartFile();
458
+            $partFile = null;
459
+
460
+            $targetPath = $path . '/' . $info['name'];
461
+            /** @var \OC\Files\Storage\Storage $targetStorage */
462
+            list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);
463
+
464
+            $exists = $this->fileView->file_exists($targetPath);
465
+
466
+            try {
467
+                $this->fileView->lockFile($targetPath, ILockingProvider::LOCK_SHARED);
468
+
469
+                $this->emitPreHooks($exists, $targetPath);
470
+                $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_EXCLUSIVE);
471
+                /** @var \OC\Files\Storage\Storage $targetStorage */
472
+                list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);
473
+
474
+                if ($needsPartFile) {
475
+                    // we first assembly the target file as a part file
476
+                    $partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part';
477
+                    /** @var \OC\Files\Storage\Storage $targetStorage */
478
+                    list($partStorage, $partInternalPath) = $this->fileView->resolvePath($partFile);
479
+
480
+
481
+                    $chunk_handler->file_assemble($partStorage, $partInternalPath);
482
+
483
+                    // here is the final atomic rename
484
+                    $renameOkay = $targetStorage->moveFromStorage($partStorage, $partInternalPath, $targetInternalPath);
485
+                    $fileExists = $targetStorage->file_exists($targetInternalPath);
486
+                    if ($renameOkay === false || $fileExists === false) {
487
+                        \OC::$server->getLogger()->error('\OC\Files\Filesystem::rename() failed', ['app' => 'webdav']);
488
+                        // only delete if an error occurred and the target file was already created
489
+                        if ($fileExists) {
490
+                            // set to null to avoid double-deletion when handling exception
491
+                            // stray part file
492
+                            $partFile = null;
493
+                            $targetStorage->unlink($targetInternalPath);
494
+                        }
495
+                        $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
496
+                        throw new Exception('Could not rename part file assembled from chunks');
497
+                    }
498
+                } else {
499
+                    // assemble directly into the final file
500
+                    $chunk_handler->file_assemble($targetStorage, $targetInternalPath);
501
+                }
502
+
503
+                // allow sync clients to send the mtime along in a header
504
+                if (isset($this->request->server['HTTP_X_OC_MTIME'])) {
505
+                    $mtime = $this->sanitizeMtime($this->request->server['HTTP_X_OC_MTIME']);
506
+                    if ($targetStorage->touch($targetInternalPath, $mtime)) {
507
+                        $this->header('X-OC-MTime: accepted');
508
+                    }
509
+                }
510
+
511
+                // since we skipped the view we need to scan and emit the hooks ourselves
512
+                $targetStorage->getUpdater()->update($targetInternalPath);
513
+
514
+                $this->fileView->changeLock($targetPath, ILockingProvider::LOCK_SHARED);
515
+
516
+                $this->emitPostHooks($exists, $targetPath);
517
+
518
+                // FIXME: should call refreshInfo but can't because $this->path is not the of the final file
519
+                $info = $this->fileView->getFileInfo($targetPath);
520
+
521
+                if (isset($this->request->server['HTTP_OC_CHECKSUM'])) {
522
+                    $checksum = trim($this->request->server['HTTP_OC_CHECKSUM']);
523
+                    $this->fileView->putFileInfo($targetPath, ['checksum' => $checksum]);
524
+                } else if ($info->getChecksum() !== null && $info->getChecksum() !== '') {
525
+                    $this->fileView->putFileInfo($this->path, ['checksum' => '']);
526
+                }
527
+
528
+                $this->fileView->unlockFile($targetPath, ILockingProvider::LOCK_SHARED);
529
+
530
+                return $info->getEtag();
531
+            } catch (\Exception $e) {
532
+                if ($partFile !== null) {
533
+                    $targetStorage->unlink($targetInternalPath);
534
+                }
535
+                $this->convertToSabreException($e);
536
+            }
537
+        }
538
+
539
+        return null;
540
+    }
541
+
542
+    /**
543
+     * Convert the given exception to a SabreException instance
544
+     *
545
+     * @param \Exception $e
546
+     *
547
+     * @throws \Sabre\DAV\Exception
548
+     */
549
+    private function convertToSabreException(\Exception $e) {
550
+        if ($e instanceof \Sabre\DAV\Exception) {
551
+            throw $e;
552
+        }
553
+        if ($e instanceof NotPermittedException) {
554
+            // a more general case - due to whatever reason the content could not be written
555
+            throw new Forbidden($e->getMessage(), 0, $e);
556
+        }
557
+        if ($e instanceof ForbiddenException) {
558
+            // the path for the file was forbidden
559
+            throw new DAVForbiddenException($e->getMessage(), $e->getRetry(), $e);
560
+        }
561
+        if ($e instanceof EntityTooLargeException) {
562
+            // the file is too big to be stored
563
+            throw new EntityTooLarge($e->getMessage(), 0, $e);
564
+        }
565
+        if ($e instanceof InvalidContentException) {
566
+            // the file content is not permitted
567
+            throw new UnsupportedMediaType($e->getMessage(), 0, $e);
568
+        }
569
+        if ($e instanceof InvalidPathException) {
570
+            // the path for the file was not valid
571
+            // TODO: find proper http status code for this case
572
+            throw new Forbidden($e->getMessage(), 0, $e);
573
+        }
574
+        if ($e instanceof LockedException || $e instanceof LockNotAcquiredException) {
575
+            // the file is currently being written to by another process
576
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
577
+        }
578
+        if ($e instanceof GenericEncryptionException) {
579
+            // returning 503 will allow retry of the operation at a later point in time
580
+            throw new ServiceUnavailable('Encryption not ready: ' . $e->getMessage(), 0, $e);
581
+        }
582
+        if ($e instanceof StorageNotAvailableException) {
583
+            throw new ServiceUnavailable('Failed to write file contents: ' . $e->getMessage(), 0, $e);
584
+        }
585
+
586
+        throw new \Sabre\DAV\Exception($e->getMessage(), 0, $e);
587
+    }
588
+
589
+    /**
590
+     * Get the checksum for this file
591
+     *
592
+     * @return string
593
+     */
594
+    public function getChecksum() {
595
+        return $this->info->getChecksum();
596
+    }
597
+
598
+    protected function header($string) {
599
+        \header($string);
600
+    }
601 601
 }
Please login to merge, or discard this patch.