/**
  * get the stored metadata of a file or folder
  *
  * @param string /int $file
  * @return array|false
  */
 public function get($file)
 {
     $result = $this->cache->get($file);
     if ($result) {
         $result = $this->formatCacheEntry($result);
     }
     return $result;
 }
Beispiel #2
0
 /**
  * check $path for updates and update if needed
  *
  * @param string $path
  * @param ICacheEntry|null $cachedEntry
  * @return boolean true if path was updated
  */
 public function checkUpdate($path, $cachedEntry = null)
 {
     if (is_null($cachedEntry)) {
         $cachedEntry = $this->cache->get($path);
     }
     if ($this->needsUpdate($path, $cachedEntry)) {
         $this->update($path, $cachedEntry);
         return true;
     } else {
         return false;
     }
 }
Beispiel #3
0
 /**
  * scan a single file and store it in the cache
  *
  * @param string $file
  * @param int $reuseExisting
  * @return array an array of metadata of the scanned file
  */
 public function scanFile($file, $reuseExisting = 0)
 {
     if (!self::isPartialFile($file) and !Filesystem::isFileBlacklisted($file)) {
         $this->emit('\\OC\\Files\\Cache\\Scanner', 'scanFile', array($file, $this->storageId));
         \OC_Hook::emit('\\OC\\Files\\Cache\\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId));
         $data = $this->getData($file);
         if ($data) {
             $parent = dirname($file);
             if ($parent === '.' or $parent === '/') {
                 $parent = '';
             }
             $parentId = $this->cache->getId($parent);
             // scan the parent if it's not in the cache (id -1) and the current file is not the root folder
             if ($file and $parentId === -1) {
                 $parentData = $this->scanFile($parent);
                 $parentId = $parentData['fileid'];
             }
             if ($parent) {
                 $data['parent'] = $parentId;
             }
             $cacheData = $this->cache->get($file);
             if ($cacheData and $reuseExisting) {
                 // prevent empty etag
                 if (empty($cacheData['etag'])) {
                     $etag = $data['etag'];
                 } else {
                     $etag = $cacheData['etag'];
                 }
                 // only reuse data if the file hasn't explicitly changed
                 if (isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime']) {
                     $data['mtime'] = $cacheData['mtime'];
                     if ($reuseExisting & self::REUSE_SIZE && $data['size'] === -1) {
                         $data['size'] = $cacheData['size'];
                     }
                     if ($reuseExisting & self::REUSE_ETAG) {
                         $data['etag'] = $etag;
                     }
                 }
                 // Only update metadata that has changed
                 $newData = array_diff_assoc($data, $cacheData);
                 if (isset($newData['etag'])) {
                     $cacheDataString = print_r($cacheData, true);
                     $dataString = print_r($data, true);
                     \OCP\Util::writeLog('OC\\Files\\Cache\\Scanner', "!!! No reuse of etag for '{$file}' !!! \ncache: {$cacheDataString} \ndata: {$dataString}", \OCP\Util::DEBUG);
                 }
             } else {
                 $newData = $data;
             }
             if (!empty($newData)) {
                 $data['fileid'] = $this->addToCache($file, $newData);
                 $this->emit('\\OC\\Files\\Cache\\Scanner', 'postScanFile', array($file, $this->storageId));
                 \OC_Hook::emit('\\OC\\Files\\Cache\\Scanner', 'post_scan_file', array('path' => $file, 'storage' => $this->storageId));
             }
         } else {
             $this->removeFromCache($file);
         }
         return $data;
     }
     return null;
 }
Beispiel #4
0
 /**
  * this test shows that there is no bug if we use the normalizer
  */
 public function testWithNormalizer()
 {
     if (!class_exists('Patchwork\\PHP\\Shim\\Normalizer')) {
         $this->markTestSkipped('The 3rdparty Normalizer extension is not available.');
         return;
     }
     // folder name "Schön" with U+00F6 (normalized)
     $folderWith00F6 = "Schön";
     // folder name "Schön" with U+0308 (un-normalized)
     $folderWith0308 = "Schön";
     $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory');
     // put root folder
     $this->assertFalse($this->cache->get('folder'));
     $this->assertGreaterThan(0, $this->cache->put('folder', $data));
     // put un-normalized folder
     $this->assertFalse($this->cache->get('folder/' . $folderWith0308));
     $this->assertGreaterThan(0, $this->cache->put('folder/' . $folderWith0308, $data));
     // get un-normalized folder by name
     $unNormalizedFolderName = $this->cache->get('folder/' . $folderWith0308);
     // check if folder name was normalized
     $this->assertEquals($folderWith00F6, $unNormalizedFolderName['name']);
     // put normalized folder
     $this->assertTrue(is_array($this->cache->get('folder/' . $folderWith00F6)));
     $this->assertGreaterThan(0, $this->cache->put('folder/' . $folderWith00F6, $data));
     // at this point we should have only one folder named "Schön"
     $this->assertEquals(1, count($this->cache->getFolderContents('folder')));
 }
Beispiel #5
0
 public function testTouch()
 {
     $rootCachedData = $this->cache->get('');
     $fooCachedData = $this->cache->get('foo.txt');
     Filesystem::touch('foo.txt');
     $cachedData = $this->cache->get('foo.txt');
     $this->assertInternalType('string', $fooCachedData['etag']);
     $this->assertInternalType('string', $cachedData['etag']);
     $this->assertGreaterThanOrEqual($fooCachedData['mtime'], $cachedData['mtime']);
     $cachedData = $this->cache->get('');
     $this->assertInternalType('string', $rootCachedData['etag']);
     $this->assertInternalType('string', $cachedData['etag']);
     $this->assertNotSame($rootCachedData['etag'], $cachedData['etag']);
     $this->assertGreaterThanOrEqual($rootCachedData['mtime'], $cachedData['mtime']);
     $rootCachedData = $cachedData;
     $time = 1371006070;
     $barCachedData = $this->cache->get('folder/bar.txt');
     $folderCachedData = $this->cache->get('folder');
     $this->cache->put('', ['mtime' => $time - 100]);
     Filesystem::touch('folder/bar.txt', $time);
     $cachedData = $this->cache->get('folder/bar.txt');
     $this->assertInternalType('string', $barCachedData['etag']);
     $this->assertInternalType('string', $cachedData['etag']);
     $this->assertNotSame($barCachedData['etag'], $cachedData['etag']);
     $this->assertEquals($time, $cachedData['mtime']);
     $cachedData = $this->cache->get('folder');
     $this->assertInternalType('string', $folderCachedData['etag']);
     $this->assertInternalType('string', $cachedData['etag']);
     $this->assertNotSame($folderCachedData['etag'], $cachedData['etag']);
     $cachedData = $this->cache->get('');
     $this->assertInternalType('string', $rootCachedData['etag']);
     $this->assertInternalType('string', $cachedData['etag']);
     $this->assertNotSame($rootCachedData['etag'], $cachedData['etag']);
     $this->assertEquals($time, $cachedData['mtime']);
 }
Beispiel #6
0
	public function testTouchWithMountPoints() {
		$storage2 = new \OC\Files\Storage\Temporary(array());
		$cache2 = $storage2->getCache();
		Filesystem::mount($storage2, array(), '/' . self::$user . '/files/folder/substorage');
		Filesystem::file_put_contents('folder/substorage/foo.txt', 'asd');
		$this->assertTrue($cache2->inCache('foo.txt'));
		$folderCachedData = $this->cache->get('folder');
		$substorageCachedData = $cache2->get('');
		$fooCachedData = $cache2->get('foo.txt');
		$cachedData = $cache2->get('foo.txt');
		$time = 1371006070;
		$this->cache->put('folder', ['mtime' => $time - 100]);
		Filesystem::touch('folder/substorage/foo.txt', $time);
		$cachedData = $cache2->get('foo.txt');
		$this->assertInternalType('string', $fooCachedData['etag']);
		$this->assertInternalType('string', $cachedData['etag']);
		$this->assertNotSame($fooCachedData['etag'], $cachedData['etag']);
		$this->assertEquals($time, $cachedData['mtime']);

		$cachedData = $cache2->get('');
		$this->assertInternalType('string', $substorageCachedData['etag']);
		$this->assertInternalType('string', $cachedData['etag']);
		$this->assertNotSame($substorageCachedData['etag'], $cachedData['etag']);

		$cachedData = $this->cache->get('folder');
		$this->assertInternalType('string', $folderCachedData['etag']);
		$this->assertInternalType('string', $cachedData['etag']);
		$this->assertNotSame($folderCachedData['etag'], $cachedData['etag']);
		$this->assertEquals($time, $cachedData['mtime']);
	}
Beispiel #7
0
 public function get($file)
 {
     $result = parent::get($file);
     $result['displayname_owner'] = $this->remoteUser . '@' . $this->remote;
     if (!$file || $file === '') {
         $result['is_share_mount_point'] = true;
         $mountPoint = rtrim($this->storage->getMountPoint());
         $result['name'] = basename($mountPoint);
     }
     return $result;
 }
Beispiel #8
0
	public function testMoveFolderCrossStorage() {
		$storage2 = new Temporary(array());
		$cache2 = $storage2->getCache();
		Filesystem::mount($storage2, array(), '/bar');
		$this->storage->mkdir('foo');
		$this->storage->mkdir('foo/bar');
		$this->storage->file_put_contents('foo/foo.txt', 'qwerty');
		$this->storage->file_put_contents('foo/bar.txt', 'foo');
		$this->storage->file_put_contents('foo/bar/bar.txt', 'qwertyuiop');

		$this->storage->getScanner()->scan('');

		$this->assertTrue($this->cache->inCache('foo'));
		$this->assertTrue($this->cache->inCache('foo/foo.txt'));
		$this->assertTrue($this->cache->inCache('foo/bar.txt'));
		$this->assertTrue($this->cache->inCache('foo/bar'));
		$this->assertTrue($this->cache->inCache('foo/bar/bar.txt'));
		$cached = [];
		$cached[] = $this->cache->get('foo');
		$cached[] = $this->cache->get('foo/foo.txt');
		$cached[] = $this->cache->get('foo/bar.txt');
		$cached[] = $this->cache->get('foo/bar');
		$cached[] = $this->cache->get('foo/bar/bar.txt');

		// add extension to trigger the possible mimetype change
		$this->view->rename('/foo', '/bar/foo.b');

		$this->assertFalse($this->cache->inCache('foo'));
		$this->assertFalse($this->cache->inCache('foo/foo.txt'));
		$this->assertFalse($this->cache->inCache('foo/bar.txt'));
		$this->assertFalse($this->cache->inCache('foo/bar'));
		$this->assertFalse($this->cache->inCache('foo/bar/bar.txt'));
		$this->assertTrue($cache2->inCache('foo.b'));
		$this->assertTrue($cache2->inCache('foo.b/foo.txt'));
		$this->assertTrue($cache2->inCache('foo.b/bar.txt'));
		$this->assertTrue($cache2->inCache('foo.b/bar'));
		$this->assertTrue($cache2->inCache('foo.b/bar/bar.txt'));

		$cachedTarget = [];
		$cachedTarget[] = $cache2->get('foo.b');
		$cachedTarget[] = $cache2->get('foo.b/foo.txt');
		$cachedTarget[] = $cache2->get('foo.b/bar.txt');
		$cachedTarget[] = $cache2->get('foo.b/bar');
		$cachedTarget[] = $cache2->get('foo.b/bar/bar.txt');

		foreach ($cached as $i => $old) {
			$new = $cachedTarget[$i];
			$this->assertEquals($old['mtime'], $new['mtime']);
			$this->assertEquals($old['size'], $new['size']);
			$this->assertEquals($old['etag'], $new['etag']);
			$this->assertEquals($old['fileid'], $new['fileid']);
			$this->assertEquals($old['mimetype'], $new['mimetype']);
		}
	}
Beispiel #9
0
 /**
  * Returns the sizes of the path and its parent dirs in a hash
  * where the key is the path and the value is the size.
  * @param string $path
  */
 function getOwnerDirSizes($path)
 {
     $result = array();
     while ($path != '' && $path != '' && $path != '.') {
         $cachedData = $this->ownerCache->get($path);
         $result[$path] = $cachedData['size'];
         $path = dirname($path);
     }
     $cachedData = $this->ownerCache->get('');
     $result[''] = $cachedData['size'];
     return $result;
 }
Beispiel #10
0
 /**
  * @param string $path
  * @return ICacheEntry
  */
 public function get($path)
 {
     $data = parent::get($path);
     if ($path === '' or $path === '/') {
         // only the size of the "files" dir counts
         $filesData = parent::get('files');
         if (isset($filesData['size'])) {
             $data['size'] = $filesData['size'];
         }
     }
     return $data;
 }
Beispiel #11
0
	public function testNoReuseOfFileId() {
		$data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain');
		$this->cache->put('somefile.txt', $data1);
		$info = $this->cache->get('somefile.txt');
		$fileId = $info['fileid'];
		$this->cache->remove('somefile.txt');
		$data2 = array('size' => 200, 'mtime' => 100, 'mimetype' => 'text/plain');
		$this->cache->put('anotherfile.txt', $data2);
		$info2 = $this->cache->get('anotherfile.txt');
		$fileId2 = $info2['fileid'];
		$this->assertNotEquals($fileId, $fileId2);
	}
Beispiel #12
0
 public function testMoveDisabled()
 {
     $this->storage->file_put_contents('foo.txt', 'qwerty');
     $this->updater->update('foo.txt');
     $this->assertTrue($this->cache->inCache('foo.txt'));
     $this->assertFalse($this->cache->inCache('bar.txt'));
     $cached = $this->cache->get('foo.txt');
     $this->storage->rename('foo.txt', 'bar.txt');
     $this->assertTrue($this->cache->inCache('foo.txt'));
     $this->assertFalse($this->cache->inCache('bar.txt'));
     $this->updater->disable();
     $this->updater->rename('foo.txt', 'bar.txt');
     $this->assertTrue($this->cache->inCache('foo.txt'));
     $this->assertFalse($this->cache->inCache('bar.txt'));
 }
Beispiel #13
0
 /**
  * Test searching by tag for multiple sections of the tree
  */
 function testSearchByTagTree()
 {
     $userId = \OC::$server->getUserSession()->getUser()->getUId();
     $this->sharedStorage->mkdir('subdir/emptydir');
     $this->sharedStorage->mkdir('subdir/emptydir2');
     $this->ownerStorage->getScanner()->scan('');
     $allIds = array($this->sharedCache->get('')['fileid'], $this->sharedCache->get('bar.txt')['fileid'], $this->sharedCache->get('subdir/another too.txt')['fileid'], $this->sharedCache->get('subdir/not a text file.xml')['fileid'], $this->sharedCache->get('subdir/another.txt')['fileid'], $this->sharedCache->get('subdir/emptydir')['fileid'], $this->sharedCache->get('subdir/emptydir2')['fileid']);
     $tagManager = \OC::$server->getTagManager()->load('files', null, null, $userId);
     foreach ($allIds as $id) {
         $tagManager->tagAs($id, 'tag1');
     }
     $results = $this->sharedStorage->getCache()->searchByTag('tag1', $userId);
     $check = array(array('name' => 'shareddir', 'path' => ''), array('name' => 'bar.txt', 'path' => 'bar.txt'), array('name' => 'another.txt', 'path' => 'subdir/another.txt'), array('name' => 'another too.txt', 'path' => 'subdir/another too.txt'), array('name' => 'emptydir', 'path' => 'subdir/emptydir'), array('name' => 'emptydir2', 'path' => 'subdir/emptydir2'), array('name' => 'not a text file.xml', 'path' => 'subdir/not a text file.xml'));
     $this->verifyFiles($check, $results);
     $tagManager->delete(array('tag1'));
 }
Beispiel #14
0
 /**
  * Test bogus paths with leading or doubled slashes
  *
  * @dataProvider bogusPathNamesProvider
  */
 public function testBogusPaths($bogusPath, $fixedBogusPath)
 {
     $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory');
     // put root folder
     $this->assertFalse($this->cache->get(''));
     $parentId = $this->cache->put('', $data);
     $this->assertGreaterThan(0, $parentId);
     $this->assertGreaterThan(0, $this->cache->put($bogusPath, $data));
     $newData = $this->cache->get($fixedBogusPath);
     $this->assertNotFalse($newData);
     $this->assertEquals($fixedBogusPath, $newData['path']);
     // parent is the correct one, resolved properly (they used to not be)
     $this->assertEquals($parentId, $newData['parent']);
     $newDataFromBogus = $this->cache->get($bogusPath);
     // same entry
     $this->assertEquals($newData, $newDataFromBogus);
 }
Beispiel #15
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']);
 }
Beispiel #16
0
 public function testMove()
 {
     $this->storage->file_put_contents('foo.txt', 'qwerty');
     $this->updater->update('foo.txt');
     $this->assertTrue($this->cache->inCache('foo.txt'));
     $this->assertFalse($this->cache->inCache('bar.txt'));
     $cached = $this->cache->get('foo.txt');
     $this->storage->rename('foo.txt', 'bar.txt');
     $this->assertTrue($this->cache->inCache('foo.txt'));
     $this->assertFalse($this->cache->inCache('bar.txt'));
     $this->updater->rename('foo.txt', 'bar.txt');
     $this->assertFalse($this->cache->inCache('foo.txt'));
     $this->assertTrue($this->cache->inCache('bar.txt'));
     $cachedTarget = $this->cache->get('bar.txt');
     $this->assertEquals($cached['etag'], $cachedTarget['etag']);
     $this->assertEquals($cached['mtime'], $cachedTarget['mtime']);
     $this->assertEquals($cached['size'], $cachedTarget['size']);
     $this->assertEquals($cached['fileid'], $cachedTarget['fileid']);
 }
Beispiel #17
0
 /**
  * Remove $path from the cache and update the size, etag and mtime of the parent folders
  *
  * @param string $path
  */
 public function remove($path)
 {
     if (!$this->enabled or Scanner::isPartialFile($path)) {
         return;
     }
     $parent = dirname($path);
     if ($parent === '.') {
         $parent = '';
     }
     $entry = $this->cache->get($path);
     $this->cache->remove($path);
     $this->correctParentStorageMtime($path);
     if ($entry instanceof ICacheEntry) {
         $this->propagator->propagateChange($path, time(), -$entry->getSize());
     } else {
         $this->propagator->propagateChange($path, time());
         if ($this->cache instanceof Cache) {
             $this->cache->correctFolderSize($parent);
         }
     }
 }
Beispiel #18
0
 /**
  * @param string $name
  * @dataProvider escapingProvider
  */
 public function testEscaping($name)
 {
     $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain');
     $this->cache->put($name, $data);
     $this->assertTrue($this->cache->inCache($name));
     $retrievedData = $this->cache->get($name);
     foreach ($data as $key => $value) {
         $this->assertEquals($value, $retrievedData[$key]);
     }
     $this->cache->move($name, $name . 'asd');
     $this->assertFalse($this->cache->inCache($name));
     $this->assertTrue($this->cache->inCache($name . 'asd'));
     $this->cache->remove($name . 'asd');
     $this->assertFalse($this->cache->inCache($name . 'asd'));
     $folderData = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory');
     $this->cache->put($name, $folderData);
     $this->cache->put('other', $folderData);
     $childs = ['asd', 'bar', 'foo', 'sub/folder'];
     $this->cache->put($name . '/sub', $folderData);
     $this->cache->put('other/sub', $folderData);
     foreach ($childs as $child) {
         $this->cache->put($name . '/' . $child, $data);
         $this->cache->put('other/' . $child, $data);
         $this->assertTrue($this->cache->inCache($name . '/' . $child));
     }
     $this->cache->move($name, $name . 'asd');
     foreach ($childs as $child) {
         $this->assertTrue($this->cache->inCache($name . 'asd/' . $child));
         $this->assertTrue($this->cache->inCache('other/' . $child));
     }
     foreach ($childs as $child) {
         $this->cache->remove($name . 'asd/' . $child);
         $this->assertFalse($this->cache->inCache($name . 'asd/' . $child));
         $this->assertTrue($this->cache->inCache('other/' . $child));
     }
 }
Beispiel #19
0
 /**
  * scan a single file and store it in the cache
  *
  * @param string $file
  * @param int $reuseExisting
  * @param bool $parentExistsInCache
  * @return array with metadata of the scanned file
  */
 public function scanFile($file, $reuseExisting = 0, $parentExistsInCache = false)
 {
     if (!self::isPartialFile($file) and !Filesystem::isFileBlacklisted($file)) {
         $this->emit('\\OC\\Files\\Cache\\Scanner', 'scanFile', array($file, $this->storageId));
         \OC_Hook::emit('\\OC\\Files\\Cache\\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId));
         $data = $this->getData($file);
         if ($data) {
             if ($file and !$parentExistsInCache) {
                 $parent = dirname($file);
                 if ($parent === '.' or $parent === '/') {
                     $parent = '';
                 }
                 if (!$this->cache->inCache($parent)) {
                     $this->scanFile($parent);
                 }
             }
             $newData = $data;
             $cacheData = $this->cache->get($file);
             if ($cacheData) {
                 if (isset($cacheData['fileid'])) {
                     $this->permissionsCache->remove($cacheData['fileid']);
                 }
                 if ($reuseExisting) {
                     // prevent empty etag
                     $etag = $cacheData['etag'];
                     $propagateETagChange = false;
                     if (empty($etag)) {
                         $etag = $data['etag'];
                         $propagateETagChange = true;
                     }
                     // only reuse data if the file hasn't explicitly changed
                     if (isset($data['mtime']) && isset($cacheData['mtime']) && $data['mtime'] === $cacheData['mtime']) {
                         if ($reuseExisting & self::REUSE_SIZE && $data['size'] === -1) {
                             $data['size'] = $cacheData['size'];
                         }
                         if ($reuseExisting & self::REUSE_ETAG) {
                             $data['etag'] = $etag;
                             if ($propagateETagChange) {
                                 $parent = $file;
                                 while ($parent !== '') {
                                     $parent = dirname($parent);
                                     if ($parent === '.') {
                                         $parent = '';
                                     }
                                     $parentCacheData = $this->cache->get($parent);
                                     $this->cache->update($parentCacheData['fileid'], array('etag' => $this->storage->getETag($parent)));
                                 }
                             }
                         }
                     }
                     // Only update metadata that has changed
                     $newData = array_diff_assoc($data, $cacheData);
                     if (isset($newData['etag'])) {
                         $cacheDataString = print_r($cacheData, true);
                         $dataString = print_r($data, true);
                         \OCP\Util::writeLog('OC\\Files\\Cache\\Scanner', "!!! No reuse of etag for '{$file}' !!! \ncache: {$cacheDataString} \ndata: {$dataString}", \OCP\Util::DEBUG);
                     }
                 }
             }
             if (!empty($newData)) {
                 $this->cache->put($file, $newData);
                 $this->emit('\\OC\\Files\\Cache\\Scanner', 'postScanFile', array($file, $this->storageId));
                 \OC_Hook::emit('\\OC\\Files\\Cache\\Scanner', 'post_scan_file', array('path' => $file, 'storage' => $this->storageId));
             }
         } else {
             $this->cache->remove($file);
         }
         return $data;
     }
     return null;
 }
Beispiel #20
0
 /**
  * scan a single file and store it in the cache
  *
  * @param string $file
  * @param int $reuseExisting
  * @param int $parentId
  * @param array | null $cacheData existing data in the cache for the file to be scanned
  * @param bool $lock set to false to disable getting an additional read lock during scanning
  * @return array an array of metadata of the scanned file
  * @throws \OC\ServerNotAvailableException
  * @throws \OCP\Lock\LockedException
  */
 public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true)
 {
     // only proceed if $file is not a partial file nor a blacklisted file
     if (!self::isPartialFile($file) and !Filesystem::isFileBlacklisted($file)) {
         //acquire a lock
         if ($lock) {
             if ($this->storage->instanceOfStorage('\\OCP\\Files\\Storage\\ILockingStorage')) {
                 $this->storage->acquireLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
             }
         }
         $data = $this->getData($file);
         if ($data) {
             // pre-emit only if it was a file. By that we avoid counting/treating folders as files
             if ($data['mimetype'] !== 'httpd/unix-directory') {
                 $this->emit('\\OC\\Files\\Cache\\Scanner', 'scanFile', array($file, $this->storageId));
                 \OC_Hook::emit('\\OC\\Files\\Cache\\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId));
             }
             $parent = dirname($file);
             if ($parent === '.' or $parent === '/') {
                 $parent = '';
             }
             if ($parentId === -1) {
                 $parentId = $this->cache->getId($parent);
             }
             // scan the parent if it's not in the cache (id -1) and the current file is not the root folder
             if ($file and $parentId === -1) {
                 $parentData = $this->scanFile($parent);
                 $parentId = $parentData['fileid'];
             }
             if ($parent) {
                 $data['parent'] = $parentId;
             }
             if (is_null($cacheData)) {
                 /** @var CacheEntry $cacheData */
                 $cacheData = $this->cache->get($file);
             }
             if ($cacheData and $reuseExisting and isset($cacheData['fileid'])) {
                 // prevent empty etag
                 if (empty($cacheData['etag'])) {
                     $etag = $data['etag'];
                 } else {
                     $etag = $cacheData['etag'];
                 }
                 $fileId = $cacheData['fileid'];
                 $data['fileid'] = $fileId;
                 // only reuse data if the file hasn't explicitly changed
                 if (isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime']) {
                     $data['mtime'] = $cacheData['mtime'];
                     if ($reuseExisting & self::REUSE_SIZE && $data['size'] === -1) {
                         $data['size'] = $cacheData['size'];
                     }
                     if ($reuseExisting & self::REUSE_ETAG) {
                         $data['etag'] = $etag;
                     }
                 }
                 // Only update metadata that has changed
                 $newData = array_diff_assoc($data, $cacheData->getData());
             } else {
                 $newData = $data;
                 $fileId = -1;
             }
             if (!empty($newData)) {
                 // Reset the checksum if the data has changed
                 $newData['checksum'] = '';
                 $data['fileid'] = $this->addToCache($file, $newData, $fileId);
             }
             if (isset($cacheData['size'])) {
                 $data['oldSize'] = $cacheData['size'];
             } else {
                 $data['oldSize'] = 0;
             }
             if (isset($cacheData['encrypted'])) {
                 $data['encrypted'] = $cacheData['encrypted'];
             }
             // post-emit only if it was a file. By that we avoid counting/treating folders as files
             if ($data['mimetype'] !== 'httpd/unix-directory') {
                 $this->emit('\\OC\\Files\\Cache\\Scanner', 'postScanFile', array($file, $this->storageId));
                 \OC_Hook::emit('\\OC\\Files\\Cache\\Scanner', 'post_scan_file', array('path' => $file, 'storage' => $this->storageId));
             }
         } else {
             $this->removeFromCache($file);
         }
         //release the acquired lock
         if ($lock) {
             if ($this->storage->instanceOfStorage('\\OCP\\Files\\Storage\\ILockingStorage')) {
                 $this->storage->releaseLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
             }
         }
         if ($data && !isset($data['encrypted'])) {
             $data['encrypted'] = false;
         }
         return $data;
     }
     return null;
 }
Beispiel #21
0
 /**
  * scan a single file and store it in the cache
  *
  * @param string $file
  * @param int $reuseExisting
  * @param int $parentId
  * @param array | null $cacheData existing data in the cache for the file to be scanned
  * @param bool $lock set to false to disable getting an additional read lock during scanning
  * @return array an array of metadata of the scanned file
  * @throws \OC\ServerNotAvailableException
  * @throws \OCP\Lock\LockedException
  */
 public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true)
 {
     if (!self::isPartialFile($file) and !Filesystem::isFileBlacklisted($file)) {
         if ($lock) {
             $this->storage->acquireLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
         }
         $this->emit('\\OC\\Files\\Cache\\Scanner', 'scanFile', array($file, $this->storageId));
         \OC_Hook::emit('\\OC\\Files\\Cache\\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId));
         $data = $this->getData($file);
         if ($data) {
             $parent = dirname($file);
             if ($parent === '.' or $parent === '/') {
                 $parent = '';
             }
             if ($parentId === -1) {
                 $parentId = $this->cache->getId($parent);
             }
             // scan the parent if it's not in the cache (id -1) and the current file is not the root folder
             if ($file and $parentId === -1) {
                 $parentData = $this->scanFile($parent);
                 $parentId = $parentData['fileid'];
             }
             if ($parent) {
                 $data['parent'] = $parentId;
             }
             if (is_null($cacheData)) {
                 $cacheData = $this->cache->get($file);
             }
             if ($cacheData and $reuseExisting and isset($cacheData['fileid'])) {
                 // prevent empty etag
                 if (empty($cacheData['etag'])) {
                     $etag = $data['etag'];
                 } else {
                     $etag = $cacheData['etag'];
                 }
                 $fileId = $cacheData['fileid'];
                 $data['fileid'] = $fileId;
                 // only reuse data if the file hasn't explicitly changed
                 if (isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime']) {
                     $data['mtime'] = $cacheData['mtime'];
                     if ($reuseExisting & self::REUSE_SIZE && $data['size'] === -1) {
                         $data['size'] = $cacheData['size'];
                     }
                     if ($reuseExisting & self::REUSE_ETAG) {
                         $data['etag'] = $etag;
                     }
                 }
                 // Only update metadata that has changed
                 $newData = array_diff_assoc($data, $cacheData);
             } else {
                 $newData = $data;
                 $fileId = -1;
             }
             if (!empty($newData)) {
                 $data['fileid'] = $this->addToCache($file, $newData, $fileId);
             }
             $this->emit('\\OC\\Files\\Cache\\Scanner', 'postScanFile', array($file, $this->storageId));
             \OC_Hook::emit('\\OC\\Files\\Cache\\Scanner', 'post_scan_file', array('path' => $file, 'storage' => $this->storageId));
         } else {
             $this->removeFromCache($file);
         }
         if ($lock) {
             $this->storage->releaseLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
         }
         return $data;
     }
     return null;
 }
Beispiel #22
0
 /**
  * Move a file or folder in the cache
  *
  * @param \OC\Files\Cache\Cache $sourceCache
  * @param string $sourcePath
  * @param string $targetPath
  * @throws \OC\DatabaseException
  */
 public function moveFromCache(Cache $sourceCache, $sourcePath, $targetPath)
 {
     // normalize source and target
     $sourcePath = $this->normalize($sourcePath);
     $targetPath = $this->normalize($targetPath);
     $sourceData = $sourceCache->get($sourcePath);
     $sourceId = $sourceData['fileid'];
     $newParentId = $this->getParentId($targetPath);
     list($sourceStorageId, $sourcePath) = $sourceCache->getMoveInfo($sourcePath);
     list($targetStorageId, $targetPath) = $this->getMoveInfo($targetPath);
     // sql for final update
     $moveSql = 'UPDATE `*PREFIX*filecache` SET `storage` =  ?, `path` = ?, `path_hash` = ?, `name` = ?, `parent` =? WHERE `fileid` = ?';
     if ($sourceData['mimetype'] === 'httpd/unix-directory') {
         //find all child entries
         $sql = 'SELECT `path`, `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path` LIKE ?';
         $result = $this->connection->executeQuery($sql, [$sourceStorageId, $this->connection->escapeLikeParameter($sourcePath) . '/%']);
         $childEntries = $result->fetchAll();
         $sourceLength = strlen($sourcePath);
         $this->connection->beginTransaction();
         $query = $this->connection->prepare('UPDATE `*PREFIX*filecache` SET `storage` = ?, `path` = ?, `path_hash` = ? WHERE `fileid` = ?');
         foreach ($childEntries as $child) {
             $newTargetPath = $targetPath . substr($child['path'], $sourceLength);
             $query->execute([$targetStorageId, $newTargetPath, md5($newTargetPath), $child['fileid']]);
         }
         $this->connection->executeQuery($moveSql, [$targetStorageId, $targetPath, md5($targetPath), basename($targetPath), $newParentId, $sourceId]);
         $this->connection->commit();
     } else {
         $this->connection->executeQuery($moveSql, [$targetStorageId, $targetPath, md5($targetPath), basename($targetPath), $newParentId, $sourceId]);
     }
 }
Beispiel #23
0
 public function get($path)
 {
     $data = parent::get($path);
     $data['permissions'] &= \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_SHARE;
     return $data;
 }