Example #1
0
 /**
  * @param resource $data
  * @return null|string
  */
 private function createFileChunked($data)
 {
     list($path, $name) = \Sabre\DAV\URLUtil::splitPath($this->path);
     $info = OC_FileChunking::decodeName($name);
     if (empty($info)) {
         throw new \Sabre\DAV\Exception\NotImplemented();
     }
     $chunk_handler = new OC_FileChunking($info);
     $bytesWritten = $chunk_handler->store($info['index'], $data);
     //detect aborted upload
     if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
         if (isset($_SERVER['CONTENT_LENGTH'])) {
             $expected = $_SERVER['CONTENT_LENGTH'];
             if ($bytesWritten != $expected) {
                 $chunk_handler->remove($info['index']);
                 throw new \Sabre\DAV\Exception\BadRequest('expected filesize ' . $expected . ' got ' . $bytesWritten);
             }
         }
     }
     if ($chunk_handler->isComplete()) {
         // we first assembly the target file as a part file
         $partFile = $path . '/' . $info['name'] . '.ocTransferId' . $info['transferid'] . '.part';
         $chunk_handler->file_assemble($partFile);
         // here is the final atomic rename
         $targetPath = $path . '/' . $info['name'];
         $renameOkay = $this->fileView->rename($partFile, $targetPath);
         $fileExists = $this->fileView->file_exists($targetPath);
         if ($renameOkay === false || $fileExists === false) {
             \OC_Log::write('webdav', '\\OC\\Files\\Filesystem::rename() failed', \OC_Log::ERROR);
             // only delete if an error occurred and the target file was already created
             if ($fileExists) {
                 $this->fileView->unlink($targetPath);
             }
             throw new \Sabre\DAV\Exception('Could not rename part file assembled from chunks');
         }
         // allow sync clients to send the mtime along in a header
         $mtime = OC_Request::hasModificationTime();
         if ($mtime !== false) {
             if ($this->fileView->touch($targetPath, $mtime)) {
                 header('X-OC-MTime: accepted');
             }
         }
         $info = $this->fileView->getFileInfo($targetPath);
         return $info->getEtag();
     }
     return null;
 }
Example #2
0
	/**
	 * @param resource $data
	 * @return null|string
	 * @throws Exception
	 * @throws BadRequest
	 * @throws NotImplemented
	 * @throws ServiceUnavailable
	 */
	private function createFileChunked($data) {
		list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($this->path);

		$info = \OC_FileChunking::decodeName($name);
		if (empty($info)) {
			throw new NotImplemented('Invalid chunk name');
		}
		$chunk_handler = new \OC_FileChunking($info);
		$bytesWritten = $chunk_handler->store($info['index'], $data);

		//detect aborted upload
		if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
			if (isset($_SERVER['CONTENT_LENGTH'])) {
				$expected = $_SERVER['CONTENT_LENGTH'];
				if ($bytesWritten != $expected) {
					$chunk_handler->remove($info['index']);
					throw new BadRequest(
						'expected filesize ' . $expected . ' got ' . $bytesWritten);
				}
			}
		}

		if ($chunk_handler->isComplete()) {
			list($storage,) = $this->fileView->resolvePath($path);
			$needsPartFile = $this->needsPartFile($storage);
			$partFile = null;

			$targetPath = $path . '/' . $info['name'];
			/** @var \OC\Files\Storage\Storage $targetStorage */
			list($targetStorage, $targetInternalPath) = $this->fileView->resolvePath($targetPath);

			$exists = $this->fileView->file_exists($targetPath);

			try {
				$this->emitPreHooks($exists, $targetPath);

				$this->changeLock(ILockingProvider::LOCK_EXCLUSIVE);

				if ($needsPartFile) {
					// we first assembly the target file as a part file
					$partFile = $this->getPartFileBasePath($path . '/' . $info['name']) . '.ocTransferId' . $info['transferid'] . '.part';
					/** @var \OC\Files\Storage\Storage $targetStorage */
					list($partStorage, $partInternalPath) = $this->fileView->resolvePath($partFile);


					$chunk_handler->file_assemble($partStorage, $partInternalPath, $this->fileView->getAbsolutePath($targetPath));

					// here is the final atomic rename
					$renameOkay = $targetStorage->moveFromStorage($partStorage, $partInternalPath, $targetInternalPath);

					$fileExists = $this->fileView->file_exists($targetPath);
					if ($renameOkay === false || $fileExists === false) {
						\OCP\Util::writeLog('webdav', '\OC\Files\Filesystem::rename() failed', \OCP\Util::ERROR);
						// only delete if an error occurred and the target file was already created
						if ($fileExists) {
							// set to null to avoid double-deletion when handling exception
							// stray part file
							$partFile = null;
							$targetStorage->unlink($targetInternalPath);
						}
						$this->changeLock(ILockingProvider::LOCK_SHARED);
						throw new Exception('Could not rename part file assembled from chunks');
					}
				} else {
					// assemble directly into the final file
					$chunk_handler->file_assemble($targetStorage, $targetInternalPath, $this->fileView->getAbsolutePath($targetPath));
				}

				// allow sync clients to send the mtime along in a header
				$request = \OC::$server->getRequest();
				if (isset($request->server['HTTP_X_OC_MTIME'])) {
					if ($targetStorage->touch($targetInternalPath, $request->server['HTTP_X_OC_MTIME'])) {
						header('X-OC-MTime: accepted');
					}
				}

				// since we skipped the view we need to scan and emit the hooks ourselves
				$this->fileView->getUpdater()->update($targetPath);

				$this->changeLock(ILockingProvider::LOCK_SHARED);

				$this->emitPostHooks($exists, $targetPath);

				$info = $this->fileView->getFileInfo($targetPath);
				return $info->getEtag();
			} catch (\Exception $e) {
				if ($partFile !== null) {
					$targetStorage->unlink($targetInternalPath);
				}
				$this->convertToSabreException($e);
			}
		}

		return null;
	}
Example #3
0
 /**
  * @param resource $data
  * @return null|string
  * @throws Exception
  * @throws BadRequest
  * @throws NotImplemented
  * @throws ServiceUnavailable
  */
 private function createFileChunked($data)
 {
     list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($this->path);
     $info = \OC_FileChunking::decodeName($name);
     if (empty($info)) {
         throw new NotImplemented();
     }
     $chunk_handler = new \OC_FileChunking($info);
     $bytesWritten = $chunk_handler->store($info['index'], $data);
     //detect aborted upload
     if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
         if (isset($_SERVER['CONTENT_LENGTH'])) {
             $expected = $_SERVER['CONTENT_LENGTH'];
             if ($bytesWritten != $expected) {
                 $chunk_handler->remove($info['index']);
                 throw new BadRequest('expected filesize ' . $expected . ' got ' . $bytesWritten);
             }
         }
     }
     if ($chunk_handler->isComplete()) {
         list($storage, ) = $this->fileView->resolvePath($path);
         $needsPartFile = $this->needsPartFile($storage);
         try {
             $targetPath = $path . '/' . $info['name'];
             if ($needsPartFile) {
                 // we first assembly the target file as a part file
                 $partFile = $path . '/' . $info['name'] . '.ocTransferId' . $info['transferid'] . '.part';
                 $chunk_handler->file_assemble($partFile);
                 // here is the final atomic rename
                 $renameOkay = $this->fileView->rename($partFile, $targetPath);
                 $fileExists = $this->fileView->file_exists($targetPath);
                 if ($renameOkay === false || $fileExists === false) {
                     \OC_Log::write('webdav', '\\OC\\Files\\Filesystem::rename() failed', \OC_Log::ERROR);
                     // only delete if an error occurred and the target file was already created
                     if ($fileExists) {
                         $this->fileView->unlink($targetPath);
                     }
                     throw new Exception('Could not rename part file assembled from chunks');
                 }
             } else {
                 // assemble directly into the final file
                 $chunk_handler->file_assemble($targetPath);
             }
             // allow sync clients to send the mtime along in a header
             $request = \OC::$server->getRequest();
             if (isset($request->server['HTTP_X_OC_MTIME'])) {
                 if ($this->fileView->touch($targetPath, $request->server['HTTP_X_OC_MTIME'])) {
                     header('X-OC-MTime: accepted');
                 }
             }
             $info = $this->fileView->getFileInfo($targetPath);
             return $info->getEtag();
         } catch (StorageNotAvailableException $e) {
             throw new ServiceUnavailable("Failed to put file: " . $e->getMessage());
         }
     }
     return null;
 }