Example #1
0
	protected function setUp() {
		parent::setUp();

		$this->storage = new \OC\Files\Storage\Temporary(array());
		$textData = "dummy file data\n";
		$imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png');
		$this->storage->mkdir('folder');
		$this->storage->file_put_contents('foo.txt', $textData);
		$this->storage->file_put_contents('foo.png', $imgData);
		$this->storage->file_put_contents('folder/bar.txt', $textData);
		$this->storage->file_put_contents('folder/bar2.txt', $textData);

		$this->scanner = $this->storage->getScanner();
		$this->scanner->scan('');
		$this->cache = $this->storage->getCache();

		if (!self::$user) {
			self::$user = $this->getUniqueID();
		}

		\OC_User::createUser(self::$user, 'password');
		$this->loginAsUser(self::$user);

		Filesystem::init(self::$user, '/' . self::$user . '/files');

		Filesystem::clearMounts();
		Filesystem::mount($this->storage, array(), '/' . self::$user . '/files');

		\OC_Hook::clear('OC_Filesystem');
	}
Example #2
0
 public function setUp()
 {
     // remember files_encryption state
     $this->stateFilesEncryption = \OC_App::isEnabled('files_encryption');
     // we want to tests with the encryption app disabled
     \OC_App::disable('files_encryption');
     $this->storage = new \OC\Files\Storage\Temporary(array());
     $textData = "dummy file data\n";
     $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png');
     $this->storage->mkdir('folder');
     $this->storage->file_put_contents('foo.txt', $textData);
     $this->storage->file_put_contents('foo.png', $imgData);
     $this->storage->file_put_contents('folder/bar.txt', $textData);
     $this->storage->file_put_contents('folder/bar2.txt', $textData);
     $this->scanner = $this->storage->getScanner();
     $this->scanner->scan('');
     $this->cache = $this->storage->getCache();
     \OC\Files\Filesystem::tearDown();
     if (!self::$user) {
         self::$user = uniqid();
     }
     \OC_User::createUser(self::$user, 'password');
     \OC_User::setUserId(self::$user);
     \OC\Files\Filesystem::init(self::$user, '/' . self::$user . '/files');
     Filesystem::clearMounts();
     Filesystem::mount($this->storage, array(), '/' . self::$user . '/files');
     \OC_Hook::clear('OC_Filesystem');
 }
Example #3
0
 public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true)
 {
     $sourceScanner = $this->getSourceScanner();
     if ($sourceScanner instanceof NoopScanner) {
         return [];
     } else {
         return parent::scanFile($file, $reuseExisting, $parentId, $cacheData, $lock);
     }
 }
Example #4
0
 /**
  * Update the cache for changes to $path
  *
  * @param string $path
  * @param ICacheEntry $cachedData
  */
 public function update($path, $cachedData)
 {
     if ($this->storage->is_dir($path)) {
         $this->scanner->scan($path, Scanner::SCAN_SHALLOW);
     } else {
         $this->scanner->scanFile($path);
     }
     if ($cachedData['mimetype'] === 'httpd/unix-directory') {
         $this->cleanFolder($path);
     }
     $this->cache->correctFolderSize($path);
 }
Example #5
0
 /**
  * Scan a single file and store it in the cache.
  * If an exception happened while accessing the external storage,
  * the storage will be checked for availability and removed
  * if it is not available any more.
  *
  * @param string $file file to scan
  * @param int $reuseExisting
  * @param int $parentId
  * @param array | null $cacheData existing data in the cache for the file to be scanned
  * @return array an array of metadata of the scanned file
  */
 public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null)
 {
     try {
         return parent::scanFile($file, $reuseExisting);
     } catch (ForbiddenException $e) {
         $this->storage->checkStorageAvailability();
     } catch (NotFoundException $e) {
         // if the storage isn't found, the call to
         // checkStorageAvailable() will verify it and remove it
         // if appropriate
         $this->storage->checkStorageAvailability();
     } catch (StorageInvalidException $e) {
         $this->storage->checkStorageAvailability();
     } catch (StorageNotAvailableException $e) {
         $this->storage->checkStorageAvailability();
     }
 }
Example #6
0
 public function testRepairParentShallow()
 {
     $this->fillTestFolders();
     $this->scanner->scan('');
     $this->assertTrue($this->cache->inCache('folder/bar.txt'));
     $oldFolderId = $this->cache->getId('folder');
     // delete the folder without removing the childs
     $sql = 'DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?';
     \OC_DB::executeAudited($sql, array($oldFolderId));
     $cachedData = $this->cache->get('folder/bar.txt');
     $this->assertEquals($oldFolderId, $cachedData['parent']);
     $this->assertFalse($this->cache->inCache('folder'));
     $this->scanner->scan('folder', \OC\Files\Cache\Scanner::SCAN_SHALLOW);
     $this->assertTrue($this->cache->inCache('folder'));
     $newFolderId = $this->cache->getId('folder');
     $this->assertNotEquals($oldFolderId, $newFolderId);
     $cachedData = $this->cache->get('folder/bar.txt');
     $this->assertEquals($newFolderId, $cachedData['parent']);
 }
Example #7
0
 public function setUp()
 {
     $app = new Application();
     $container = $app->getContainer();
     // reset backend
     $um = $container->getServer()->getUserManager();
     $this->userSession = $container->getServer()->getUserSession();
     $um->clearBackends();
     $um->registerBackend(new \OC_User_Database());
     // create test user
     $this->userName = '******';
     \OC_User::deleteUser($this->userName);
     $um->createUser($this->userName, $this->userName);
     \OC_Util::tearDownFS();
     $this->userSession->setUser(null);
     Filesystem::tearDown();
     \OC_Util::setupFS($this->userName);
     $this->userSession->setUser($um->get($this->userName));
     $view = new \OC\Files\View('/' . $this->userName . '/files');
     // setup files
     $filesToCopy = array('documents' => array('document.pdf', 'document.docx', 'document.odt', 'document.txt'));
     $count = 0;
     foreach ($filesToCopy as $folder => $files) {
         foreach ($files as $file) {
             $imgData = file_get_contents(__DIR__ . '/data/' . $file);
             $view->mkdir($folder);
             $path = $folder . '/' . $file;
             $view->file_put_contents($path, $imgData);
             // set mtime to get fixed sorting with respect to recentFiles
             $count++;
             $view->touch($path, 1000 + $count);
         }
     }
     list($storage, ) = $view->resolvePath('');
     /** @var $storage Storage */
     $this->storage = $storage;
     $this->scanner = $storage->getScanner();
     $this->scanner->scan('');
 }
Example #8
0
 /**
  * get the filesystem info
  *
  * @param string $path
  * @param boolean|string $includeMountPoints true to add mountpoint sizes,
  * 'ext' to add only ext storage mount point sizes. Defaults to true.
  * defaults to true
  * @return \OC\Files\FileInfo|false
  */
 public function getFileInfo($path, $includeMountPoints = true)
 {
     $this->assertPathLength($path);
     $data = array();
     if (!Filesystem::isValidPath($path)) {
         return $data;
     }
     if (Cache\Scanner::isPartialFile($path)) {
         return $this->getPartFileInfo($path);
     }
     $path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
     $mount = Filesystem::getMountManager()->find($path);
     $storage = $mount->getStorage();
     $internalPath = $mount->getInternalPath($path);
     $data = null;
     if ($storage) {
         $cache = $storage->getCache($internalPath);
         $data = $cache->get($internalPath);
         $watcher = $storage->getWatcher($internalPath);
         // if the file is not in the cache or needs to be updated, trigger the scanner and reload the data
         if (!$data) {
             if (!$storage->file_exists($internalPath)) {
                 return false;
             }
             $scanner = $storage->getScanner($internalPath);
             $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
             $data = $cache->get($internalPath);
         } else {
             if (!Cache\Scanner::isPartialFile($internalPath) && $watcher->checkUpdate($internalPath, $data)) {
                 $this->updater->propagate($path);
                 $data = $cache->get($internalPath);
             }
         }
         if ($data and isset($data['fileid'])) {
             // upgrades from oc6 or lower might not have the permissions set in the file cache
             if ($data['permissions'] === 0) {
                 $data['permissions'] = $storage->getPermissions($data['path']);
                 $cache->update($data['fileid'], array('permissions' => $data['permissions']));
             }
             if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') {
                 //add the sizes of other mount points to the folder
                 $extOnly = $includeMountPoints === 'ext';
                 $mountPoints = Filesystem::getMountPoints($path);
                 foreach ($mountPoints as $mountPoint) {
                     $subStorage = Filesystem::getStorage($mountPoint);
                     if ($subStorage) {
                         // exclude shared storage ?
                         if ($extOnly && $subStorage instanceof \OC\Files\Storage\Shared) {
                             continue;
                         }
                         $subCache = $subStorage->getCache('');
                         $rootEntry = $subCache->get('');
                         $data['size'] += isset($rootEntry['size']) ? $rootEntry['size'] : 0;
                     }
                 }
             }
         }
     }
     if (!$data) {
         return false;
     }
     if ($mount instanceof MoveableMount && $internalPath === '') {
         $data['permissions'] |= \OCP\Constants::PERMISSION_DELETE;
     }
     return new FileInfo($path, $storage, $internalPath, $data, $mount);
 }
Example #9
0
 /**
  * get the filesystem info
  *
  * @param string $path
  * @param boolean|string $includeMountPoints true to add mountpoint sizes,
  * 'ext' to add only ext storage mount point sizes. Defaults to true.
  * defaults to true
  * @return \OC\Files\FileInfo|false False if file does not exist
  */
 public function getFileInfo($path, $includeMountPoints = true)
 {
     $this->assertPathLength($path);
     if (!Filesystem::isValidPath($path)) {
         return false;
     }
     if (Cache\Scanner::isPartialFile($path)) {
         return $this->getPartFileInfo($path);
     }
     $relativePath = $path;
     $path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
     $mount = Filesystem::getMountManager()->find($path);
     $storage = $mount->getStorage();
     $internalPath = $mount->getInternalPath($path);
     if ($storage) {
         $data = $this->getCacheEntry($storage, $internalPath, $relativePath);
         if (!$data instanceof ICacheEntry) {
             return false;
         }
         if ($mount instanceof MoveableMount && $internalPath === '') {
             $data['permissions'] |= \OCP\Constants::PERMISSION_DELETE;
         }
         $owner = $this->getUserObjectForOwner($storage->getOwner($internalPath));
         $info = new FileInfo($path, $storage, $internalPath, $data, $mount, $owner);
         if ($data and isset($data['fileid'])) {
             if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') {
                 //add the sizes of other mount points to the folder
                 $extOnly = $includeMountPoints === 'ext';
                 $mounts = Filesystem::getMountManager()->findIn($path);
                 foreach ($mounts as $mount) {
                     $subStorage = $mount->getStorage();
                     if ($subStorage) {
                         // exclude shared storage ?
                         if ($extOnly && $subStorage instanceof \OC\Files\Storage\Shared) {
                             continue;
                         }
                         $subCache = $subStorage->getCache('');
                         $rootEntry = $subCache->get('');
                         $info->addSubEntry($rootEntry, $mount->getMountPoint());
                     }
                 }
             }
         }
         return $info;
     }
     return false;
 }
Example #10
0
 /**
  * Rename a file or folder in the cache and update the size, etag and mtime of the parent folders
  *
  * @param IStorage $sourceStorage
  * @param string $source
  * @param string $target
  */
 public function renameFromStorage(IStorage $sourceStorage, $source, $target)
 {
     if (!$this->enabled or Scanner::isPartialFile($source) or Scanner::isPartialFile($target)) {
         return;
     }
     $time = time();
     $sourceCache = $sourceStorage->getCache();
     $sourceUpdater = $sourceStorage->getUpdater();
     $sourcePropagator = $sourceStorage->getPropagator();
     if ($sourceCache->inCache($source)) {
         if ($this->cache->inCache($target)) {
             $this->cache->remove($target);
         }
         if ($sourceStorage === $this->storage) {
             $this->cache->move($source, $target);
         } else {
             $this->cache->moveFromCache($sourceCache, $source, $target);
         }
     }
     if (pathinfo($source, PATHINFO_EXTENSION) !== pathinfo($target, PATHINFO_EXTENSION)) {
         // handle mime type change
         $mimeType = $this->storage->getMimeType($target);
         $fileId = $this->cache->getId($target);
         $this->cache->update($fileId, ['mimetype' => $mimeType]);
     }
     if ($sourceCache instanceof Cache) {
         $sourceCache->correctFolderSize($source);
     }
     if ($this->cache instanceof Cache) {
         $this->cache->correctFolderSize($target);
     }
     if ($sourceUpdater instanceof Updater) {
         $sourceUpdater->correctParentStorageMtime($source);
     }
     $this->correctParentStorageMtime($target);
     $this->updateStorageMTimeOnly($target);
     $sourcePropagator->propagateChange($source, $time);
     $this->propagator->propagateChange($target, $time);
 }
Example #11
0
 /**
  * last chunk received. This is the place where you can perform some final
  * operation and return some remaining data if something is left in your
  * buffer.
  *
  * @param string $path to the file
  * @param int $position
  * @return string remained data which should be written to the file in case
  *                of a write operation
  * @throws PublicKeyMissingException
  * @throws \Exception
  * @throws \OCA\Encryption\Exceptions\MultiKeyEncryptException
  */
 public function end($path, $position = 0)
 {
     $result = '';
     if ($this->isWriteOperation) {
         $this->keyManager->setVersion($path, $this->version + 1, new View());
         // in case of a part file we remember the new signature versions
         // the version will be set later on update.
         // This way we make sure that other apps listening to the pre-hooks
         // still get the old version which should be the correct value for them
         if (Scanner::isPartialFile($path)) {
             self::$rememberVersion[$this->stripPartFileExtension($path)] = $this->version + 1;
         }
         if (!empty($this->writeCache)) {
             $result = $this->crypt->symmetricEncryptFileContent($this->writeCache, $this->fileKey, $this->version + 1, $position);
             $this->writeCache = '';
         }
         $publicKeys = array();
         if ($this->useMasterPassword === true) {
             $publicKeys[$this->keyManager->getMasterKeyId()] = $this->keyManager->getPublicMasterKey();
         } else {
             foreach ($this->accessList['users'] as $uid) {
                 try {
                     $publicKeys[$uid] = $this->keyManager->getPublicKey($uid);
                 } catch (PublicKeyMissingException $e) {
                     $this->logger->warning('no public key found for user "{uid}", user will not be able to read the file', ['app' => 'encryption', 'uid' => $uid]);
                     // if the public key of the owner is missing we should fail
                     if ($uid === $this->user) {
                         throw $e;
                     }
                 }
             }
         }
         $publicKeys = $this->keyManager->addSystemKeys($this->accessList, $publicKeys, $this->user);
         $encryptedKeyfiles = $this->crypt->multiKeyEncrypt($this->fileKey, $publicKeys);
         $this->keyManager->setAllFileKeys($this->path, $encryptedKeyfiles);
     }
     return $result;
 }
Example #12
0
 /**
  * @dataProvider dataTestIsPartialFile
  *
  * @param string $path
  * @param bool $expected
  */
 public function testIsPartialFile($path, $expected)
 {
     $this->assertSame($expected, $this->scanner->isPartialFile($path));
 }
Example #13
0
 private function shouldEmitHooks($path = '')
 {
     if ($path && Cache\Scanner::isPartialFile($path)) {
         return false;
     }
     if (!Filesystem::$loaded) {
         return false;
     }
     $defaultRoot = Filesystem::getRoot();
     if ($this->fakeRoot === $defaultRoot) {
         return true;
     }
     return strlen($this->fakeRoot) > strlen($defaultRoot) && substr($this->fakeRoot, 0, strlen($defaultRoot) + 1) === $defaultRoot . '/';
 }
Example #14
0
 /**
  * get the filesystem info
  *
  * @param string $path
  * @param boolean|string $includeMountPoints true to add mountpoint sizes,
  * 'ext' to add only ext storage mount point sizes. Defaults to true.
  * defaults to true
  * @return \OC\Files\FileInfo|false
  */
 public function getFileInfo($path, $includeMountPoints = true)
 {
     $this->assertPathLength($path);
     $data = array();
     if (!Filesystem::isValidPath($path)) {
         return $data;
     }
     if (Cache\Scanner::isPartialFile($path)) {
         return $this->getPartFileInfo($path);
     }
     $path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
     $mount = Filesystem::getMountManager()->find($path);
     $storage = $mount->getStorage();
     $internalPath = $mount->getInternalPath($path);
     $data = null;
     if ($storage) {
         $cache = $storage->getCache($internalPath);
         if (!$cache->inCache($internalPath)) {
             if (!$storage->file_exists($internalPath)) {
                 return false;
             }
             $scanner = $storage->getScanner($internalPath);
             $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW);
         } else {
             $watcher = $storage->getWatcher($internalPath);
             $data = $watcher->checkUpdate($internalPath);
         }
         if (!is_array($data)) {
             $data = $cache->get($internalPath);
         }
         if ($data and isset($data['fileid'])) {
             if ($data['permissions'] === 0) {
                 $data['permissions'] = $storage->getPermissions($data['path']);
                 $cache->update($data['fileid'], array('permissions' => $data['permissions']));
             }
             if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') {
                 //add the sizes of other mount points to the folder
                 $extOnly = $includeMountPoints === 'ext';
                 $mountPoints = Filesystem::getMountPoints($path);
                 foreach ($mountPoints as $mountPoint) {
                     $subStorage = Filesystem::getStorage($mountPoint);
                     if ($subStorage) {
                         // exclude shared storage ?
                         if ($extOnly && $subStorage instanceof \OC\Files\Storage\Shared) {
                             continue;
                         }
                         $subCache = $subStorage->getCache('');
                         $rootEntry = $subCache->get('');
                         $data['size'] += isset($rootEntry['size']) ? $rootEntry['size'] : 0;
                     }
                 }
             }
         }
     }
     if (!$data) {
         return false;
     }
     if ($mount instanceof MoveableMount && $internalPath === '') {
         $data['permissions'] |= \OCP\PERMISSION_DELETE | \OCP\PERMISSION_UPDATE;
     }
     $data = \OC_FileProxy::runPostProxies('getFileInfo', $path, $data);
     return new FileInfo($path, $storage, $internalPath, $data);
 }
Example #15
0
	/**
	 * Rename a file or folder in the cache and update the size, etag and mtime of the parent folders
	 *
	 * @param string $source
	 * @param string $target
	 */
	public function rename($source, $target) {
		if (!$this->enabled or Scanner::isPartialFile($source) or Scanner::isPartialFile($target)) {
			return;
		}
		/**
		 * @var \OC\Files\Storage\Storage $sourceStorage
		 * @var \OC\Files\Storage\Storage $targetStorage
		 * @var string $sourceInternalPath
		 * @var string $targetInternalPath
		 */
		list($sourceStorage, $sourceInternalPath) = $this->view->resolvePath($source);
		// if it's a moved mountpoint we dont need to do anything
		if ($sourceInternalPath === '') {
			return;
		}
		list($targetStorage, $targetInternalPath) = $this->view->resolvePath($target);

		if ($sourceStorage && $targetStorage) {
			$targetCache = $targetStorage->getCache($sourceInternalPath);
			if ($sourceStorage->getCache($sourceInternalPath)->inCache($sourceInternalPath)) {
				if ($targetCache->inCache($targetInternalPath)) {
					$targetCache->remove($targetInternalPath);
				}
				if ($sourceStorage === $targetStorage) {
					$targetCache->move($sourceInternalPath, $targetInternalPath);
				} else {
					$targetCache->moveFromCache($sourceStorage->getCache(), $sourceInternalPath, $targetInternalPath);
				}
			}

			if (pathinfo($sourceInternalPath, PATHINFO_EXTENSION) !== pathinfo($targetInternalPath, PATHINFO_EXTENSION)) {
				// handle mime type change
				$mimeType = $targetStorage->getMimeType($targetInternalPath);
				$fileId = $targetCache->getId($targetInternalPath);
				$targetCache->update($fileId, array('mimetype' => $mimeType));
			}

			$targetCache->correctFolderSize($sourceInternalPath);
			$targetCache->correctFolderSize($targetInternalPath);
			$this->correctParentStorageMtime($sourceStorage, $sourceInternalPath);
			$this->correctParentStorageMtime($targetStorage, $targetInternalPath);
			$this->propagator->addChange($this->getPropagatorPath($source));
			$this->propagator->addChange($this->getPropagatorPath($target));
			$this->propagator->propagateChanges();
		}
	}