Exemplo n.º 1
0
 /**
  * Creates a new file in the directory
  *
  * Data will either be supplied as a stream resource, or in certain cases
  * as a string. Keep in mind that you may have to support either.
  *
  * After succesful creation of the file, you may choose to return the ETag
  * of the new file here.
  *
  * The returned ETag must be surrounded by double-quotes (The quotes should
  * be part of the actual string).
  *
  * If you cannot accurately determine the ETag, you should not return it.
  * If you don't store the file exactly as-is (you're transforming it
  * somehow) you should also not return an ETag.
  *
  * This means that if a subsequent GET to this new file does not exactly
  * return the same contents of what was submitted here, you are strongly
  * recommended to omit the ETag.
  *
  * @param string $name Name of the file
  * @param resource|string $data Initial payload
  * @throws Sabre_DAV_Exception_Forbidden
  * @return null|string
  */
 public function createFile($name, $data = null)
 {
     if (!\OC\Files\Filesystem::isCreatable($this->path)) {
         throw new \Sabre_DAV_Exception_Forbidden();
     }
     if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
         $info = OC_FileChunking::decodeName($name);
         if (empty($info)) {
             throw new Sabre_DAV_Exception_NotImplemented();
         }
         $chunk_handler = new OC_FileChunking($info);
         $chunk_handler->store($info['index'], $data);
         if ($chunk_handler->isComplete()) {
             $newPath = $this->path . '/' . $info['name'];
             $chunk_handler->file_assemble($newPath);
             return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
         }
     } else {
         $newPath = $this->path . '/' . $name;
         // mark file as partial while uploading (ignored by the scanner)
         $partpath = $newPath . '.part';
         \OC\Files\Filesystem::file_put_contents($partpath, $data);
         //detect aborted upload
         if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
             if (isset($_SERVER['CONTENT_LENGTH'])) {
                 $expected = $_SERVER['CONTENT_LENGTH'];
                 $actual = \OC\Files\Filesystem::filesize($partpath);
                 if ($actual != $expected) {
                     \OC\Files\Filesystem::unlink($partpath);
                     throw new Sabre_DAV_Exception_BadRequest('expected filesize ' . $expected . ' got ' . $actual);
                 }
             }
         }
         // rename to correct path
         \OC\Files\Filesystem::rename($partpath, $newPath);
         // allow sync clients to send the mtime along in a header
         $mtime = OC_Request::hasModificationTime();
         if ($mtime !== false) {
             if (\OC\Files\Filesystem::touch($newPath, $mtime)) {
                 header('X-OC-MTime: accepted');
             }
         }
         return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
     }
     return null;
 }
Exemplo n.º 2
0
 /**
  * Creates a new file in the directory
  *
  * Data will either be supplied as a stream resource, or in certain cases
  * as a string. Keep in mind that you may have to support either.
  *
  * After succesful creation of the file, you may choose to return the ETag
  * of the new file here.
  *
  * The returned ETag must be surrounded by double-quotes (The quotes should
  * be part of the actual string).
  *
  * If you cannot accurately determine the ETag, you should not return it.
  * If you don't store the file exactly as-is (you're transforming it
  * somehow) you should also not return an ETag.
  *
  * This means that if a subsequent GET to this new file does not exactly
  * return the same contents of what was submitted here, you are strongly
  * recommended to omit the ETag.
  *
  * @param string $name Name of the file
  * @param resource|string $data Initial payload
  * @return null|string
  */
 public function createFile($name, $data = null)
 {
     if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
         $info = OC_FileChunking::decodeName($name);
         if (empty($info)) {
             throw new Sabre_DAV_Exception_NotImplemented();
         }
         $chunk_handler = new OC_FileChunking($info);
         $chunk_handler->store($info['index'], $data);
         if ($chunk_handler->isComplete()) {
             $newPath = $this->path . '/' . $info['name'];
             $chunk_handler->file_assemble($newPath);
             return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
         }
     } else {
         $newPath = $this->path . '/' . $name;
         OC_Filesystem::file_put_contents($newPath, $data);
         return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
     }
     return null;
 }
Exemplo n.º 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('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;
	}
Exemplo n.º 4
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;
 }
Exemplo n.º 5
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;
 }