Example #1
0
 /**
  * @param string $path
  * @param string $mode
  * @return resource
  */
 public function fopen($path, $mode)
 {
     $fullPath = $this->buildPath($path);
     try {
         switch ($mode) {
             case 'r':
             case 'rb':
                 if (!$this->file_exists($path)) {
                     return false;
                 }
                 return $this->share->read($fullPath);
             case 'w':
             case 'wb':
                 $source = $this->share->write($fullPath);
                 return CallBackWrapper::wrap($source, null, null, function () use($fullPath) {
                     unset($this->statCache[$fullPath]);
                 });
             case 'a':
             case 'ab':
             case 'r+':
             case 'w+':
             case 'wb+':
             case 'a+':
             case 'x':
             case 'x+':
             case 'c':
             case 'c+':
                 //emulate these
                 if (strrpos($path, '.') !== false) {
                     $ext = substr($path, strrpos($path, '.'));
                 } else {
                     $ext = '';
                 }
                 if ($this->file_exists($path)) {
                     if (!$this->isUpdatable($path)) {
                         return false;
                     }
                     $tmpFile = $this->getCachedFile($path);
                 } else {
                     if (!$this->isCreatable(dirname($path))) {
                         return false;
                     }
                     $tmpFile = \OCP\Files::tmpFile($ext);
                 }
                 $source = fopen($tmpFile, $mode);
                 $share = $this->share;
                 return CallbackWrapper::wrap($source, null, null, function () use($tmpFile, $fullPath, $share) {
                     unset($this->statCache[$fullPath]);
                     $share->put($tmpFile, $fullPath);
                     unlink($tmpFile);
                 });
         }
         return false;
     } catch (NotFoundException $e) {
         return false;
     } catch (ForbiddenException $e) {
         return false;
     } catch (ConnectException $e) {
         throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
     }
 }
Example #2
0
 /**
  * abstraction layer for basic filesystem functions: wrapper for \OC\Files\Storage\Storage
  *
  * @param string $operation
  * @param string $path
  * @param array $hooks (optional)
  * @param mixed $extraParam (optional)
  * @return mixed
  * @throws \Exception
  *
  * This method takes requests for basic filesystem functions (e.g. reading & writing
  * files), processes hooks and proxies, sanitises paths, and finally passes them on to
  * \OC\Files\Storage\Storage for delegation to a storage backend for execution
  */
 private function basicOperation($operation, $path, $hooks = [], $extraParam = null)
 {
     $postFix = substr($path, -1, 1) === '/' ? '/' : '';
     $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
     if (Filesystem::isValidPath($path) and !Filesystem::isFileBlacklisted($path)) {
         $path = $this->getRelativePath($absolutePath);
         if ($path == null) {
             return false;
         }
         if (in_array('write', $hooks) || in_array('delete', $hooks) || in_array('read', $hooks)) {
             // always a shared lock during pre-hooks so the hook can read the file
             $this->lockFile($path, ILockingProvider::LOCK_SHARED);
         }
         $run = $this->runHooks($hooks, $path);
         /** @var \OC\Files\Storage\Storage $storage */
         list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix);
         if ($run and $storage) {
             if (in_array('write', $hooks) || in_array('delete', $hooks)) {
                 $this->changeLock($path, ILockingProvider::LOCK_EXCLUSIVE);
             }
             try {
                 if (!is_null($extraParam)) {
                     $result = $storage->{$operation}($internalPath, $extraParam);
                 } else {
                     $result = $storage->{$operation}($internalPath);
                 }
             } catch (\Exception $e) {
                 if (in_array('write', $hooks) || in_array('delete', $hooks)) {
                     $this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
                 } else {
                     if (in_array('read', $hooks)) {
                         $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
                     }
                 }
                 throw $e;
             }
             if (in_array('delete', $hooks) and $result) {
                 $this->removeUpdate($storage, $internalPath);
             }
             if (in_array('write', $hooks) and $operation !== 'fopen') {
                 $this->writeUpdate($storage, $internalPath);
             }
             if (in_array('touch', $hooks)) {
                 $this->writeUpdate($storage, $internalPath, $extraParam);
             }
             if ((in_array('write', $hooks) || in_array('delete', $hooks)) && ($operation !== 'fopen' || $result === false)) {
                 $this->changeLock($path, ILockingProvider::LOCK_SHARED);
             }
             $unlockLater = false;
             if ($this->lockingEnabled && $operation === 'fopen' && is_resource($result)) {
                 $unlockLater = true;
                 $result = CallbackWrapper::wrap($result, null, null, function () use($hooks, $path) {
                     if (in_array('write', $hooks)) {
                         $this->unlockFile($path, ILockingProvider::LOCK_EXCLUSIVE);
                     } else {
                         if (in_array('read', $hooks)) {
                             $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
                         }
                     }
                 });
             }
             if ($this->shouldEmitHooks($path) && $result !== false) {
                 if ($operation != 'fopen') {
                     //no post hooks for fopen, the file stream is still open
                     $this->runHooks($hooks, $path, true);
                 }
             }
             if (!$unlockLater && (in_array('write', $hooks) || in_array('delete', $hooks) || in_array('read', $hooks))) {
                 $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
             }
             return $result;
         } else {
             $this->unlockFile($path, ILockingProvider::LOCK_SHARED);
         }
     }
     return null;
 }
Example #3
0
	/**
	 * {@inheritdoc}
	 */
	public function fopen($path, $mode) {
		$fullPath = $this->buildPath($path);
		$useExisting = true;
		switch ($mode) {
			case 'r':
			case 'rb':
				try {
					return $this->flysystem->readStream($fullPath);
				} catch (FileNotFoundException $e) {
					return false;
				}
			case 'w':
			case 'w+':
			case 'wb':
			case 'wb+':
				$useExisting = false;
			case 'a':
			case 'ab':
			case 'r+':
			case 'a+':
			case 'x':
			case 'x+':
			case 'c':
			case 'c+':
				//emulate these
				if ($useExisting and $this->file_exists($path)) {
					if (!$this->isUpdatable($path)) {
						return false;
					}
					$tmpFile = $this->getCachedFile($path);
				} else {
					if (!$this->isCreatable(dirname($path))) {
						return false;
					}
					$tmpFile = \OCP\Files::tmpFile();
				}
				$source = fopen($tmpFile, $mode);
				return CallbackWrapper::wrap($source, null, null, function () use ($tmpFile, $fullPath) {
					$this->flysystem->putStream($fullPath, fopen($tmpFile, 'r'));
					unlink($tmpFile);
				});
		}
		return false;
	}
Example #4
0
 /**
  * Open a writable stream to a remote file
  *
  * @param string $target
  * @return resource a write only stream to upload a remote file
  *
  * @throws \Icewind\SMB\Exception\NotFoundException
  * @throws \Icewind\SMB\Exception\InvalidTypeException
  */
 public function write($target)
 {
     $target = $this->escapePath($target);
     // since returned stream is closed by the caller we need to create a new instance
     // since we can't re-use the same file descriptor over multiple calls
     $workgroupArgument = $this->server->getWorkgroup() ? ' -W ' . escapeshellarg($this->server->getWorkgroup()) : '';
     $command = sprintf('%s %s --authentication-file=%s %s', $this->system->getSmbclientPath(), $workgroupArgument, System::getFD(3), escapeshellarg('//' . $this->server->getHost() . '/' . $this->name));
     $connection = new Connection($command);
     $connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
     $fh = $connection->getFileInputStream();
     $connection->write('put ' . System::getFD(4) . ' ' . $target);
     $connection->write('exit');
     // use a close callback to ensure the upload is finished before continuing
     // this also serves as a way to keep the connection in scope
     return CallbackWrapper::wrap($fh, null, null, function () use($connection, $target) {
         $connection->close(false);
         // dont terminate, give the upload some time
     });
 }
Example #5
0
 /**
  * Open a writable stream to a remote file
  *
  * @param string $target
  * @return resource a write only stream to upload a remote file
  *
  * @throws \Icewind\SMB\Exception\NotFoundException
  * @throws \Icewind\SMB\Exception\InvalidTypeException
  */
 public function write($target)
 {
     $target = $this->escapePath($target);
     // close the single quote, open a double quote where we put the single quote...
     $target = str_replace('\'', '\'"\'"\'', $target);
     // since returned stream is closed by the caller we need to create a new instance
     // since we can't re-use the same file descriptor over multiple calls
     $command = sprintf('%s --authentication-file=/proc/self/fd/3 //%s/%s -c \'put /proc/self/fd/4 %s\'', Server::CLIENT, $this->server->getHost(), $this->name, $target);
     $connection = new RawConnection($command);
     $connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
     $fh = $connection->getFileInputStream();
     // use a close callback to ensure the upload is finished before continuing
     // this also serves as a way to keep the connection in scope
     return CallbackWrapper::wrap($fh, null, null, function () use($connection) {
         $connection->close(false);
         // dont terminate, give the upload some time
     });
 }
Example #6
0
 /**
  * @param resource $source
  * @param callable $read
  * @param callable $write
  * @param callable $close
  * @param callable $readDir
  * @return resource
  */
 protected function wrapSource($source, $read = null, $write = null, $close = null, $readDir = null)
 {
     return \Icewind\Streams\CallbackWrapper::wrap($source, $read, $write, $close, $readDir);
 }