2013-07-19 14:44:47 +00:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
|
|
|
|
* This file is licensed under the Affero General Public License version 3 or
|
|
|
|
* later.
|
|
|
|
* See the COPYING-README file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace OC\Files\Utils;
|
|
|
|
|
2014-06-02 13:17:00 +00:00
|
|
|
use OC\Files\View;
|
|
|
|
use OC\Files\Cache\ChangePropagator;
|
2013-07-19 14:44:47 +00:00
|
|
|
use OC\Files\Filesystem;
|
2014-06-25 13:22:49 +00:00
|
|
|
use OC\ForbiddenException;
|
2013-07-26 13:43:10 +00:00
|
|
|
use OC\Hooks\PublicEmitter;
|
2013-07-19 14:44:47 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Class Scanner
|
|
|
|
*
|
|
|
|
* Hooks available in scope \OC\Utils\Scanner
|
|
|
|
* - scanFile(string $absolutePath)
|
|
|
|
* - scanFolder(string $absolutePath)
|
|
|
|
*
|
|
|
|
* @package OC\Files\Utils
|
|
|
|
*/
|
2013-07-26 13:43:10 +00:00
|
|
|
class Scanner extends PublicEmitter {
|
2013-07-19 14:44:47 +00:00
|
|
|
/**
|
|
|
|
* @var string $user
|
|
|
|
*/
|
|
|
|
private $user;
|
|
|
|
|
2014-06-02 13:17:00 +00:00
|
|
|
/**
|
|
|
|
* @var \OC\Files\Cache\ChangePropagator
|
|
|
|
*/
|
|
|
|
protected $propagator;
|
|
|
|
|
2014-09-07 23:34:03 +00:00
|
|
|
/**
|
|
|
|
* @var \OCP\IDBConnection
|
|
|
|
*/
|
|
|
|
protected $db;
|
|
|
|
|
2013-07-19 14:44:47 +00:00
|
|
|
/**
|
|
|
|
* @param string $user
|
2014-09-07 23:34:03 +00:00
|
|
|
* @param \OCP\IDBConnection $db
|
2013-07-19 14:44:47 +00:00
|
|
|
*/
|
2014-09-07 23:34:03 +00:00
|
|
|
public function __construct($user, $db) {
|
2013-07-19 14:44:47 +00:00
|
|
|
$this->user = $user;
|
2014-06-02 13:17:00 +00:00
|
|
|
$this->propagator = new ChangePropagator(new View(''));
|
2014-09-07 23:34:03 +00:00
|
|
|
$this->db = $db;
|
2013-07-19 14:44:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get all storages for $dir
|
|
|
|
*
|
|
|
|
* @param string $dir
|
|
|
|
* @return \OC\Files\Mount\Mount[]
|
|
|
|
*/
|
|
|
|
protected function getMounts($dir) {
|
|
|
|
//TODO: move to the node based fileapi once that's done
|
|
|
|
\OC_Util::tearDownFS();
|
|
|
|
\OC_Util::setupFS($this->user);
|
|
|
|
$absolutePath = Filesystem::getView()->getAbsolutePath($dir);
|
|
|
|
|
|
|
|
$mountManager = Filesystem::getMountManager();
|
|
|
|
$mounts = $mountManager->findIn($absolutePath);
|
|
|
|
$mounts[] = $mountManager->find($absolutePath);
|
|
|
|
$mounts = array_reverse($mounts); //start with the mount of $dir
|
|
|
|
|
|
|
|
return $mounts;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* attach listeners to the scanner
|
|
|
|
*
|
|
|
|
* @param \OC\Files\Mount\Mount $mount
|
|
|
|
*/
|
|
|
|
protected function attachListener($mount) {
|
|
|
|
$scanner = $mount->getStorage()->getScanner();
|
2013-07-26 13:43:10 +00:00
|
|
|
$emitter = $this;
|
2013-07-29 15:03:57 +00:00
|
|
|
$scanner->listen('\OC\Files\Cache\Scanner', 'scanFile', function ($path) use ($mount, $emitter) {
|
2013-07-26 13:43:10 +00:00
|
|
|
$emitter->emit('\OC\Files\Utils\Scanner', 'scanFile', array($mount->getMountPoint() . $path));
|
2013-07-19 14:44:47 +00:00
|
|
|
});
|
2013-07-29 15:03:57 +00:00
|
|
|
$scanner->listen('\OC\Files\Cache\Scanner', 'scanFolder', function ($path) use ($mount, $emitter) {
|
2013-07-26 13:43:10 +00:00
|
|
|
$emitter->emit('\OC\Files\Utils\Scanner', 'scanFolder', array($mount->getMountPoint() . $path));
|
2013-07-19 14:44:47 +00:00
|
|
|
});
|
2014-06-02 13:17:00 +00:00
|
|
|
|
|
|
|
// propagate etag and mtimes when files are changed or removed
|
|
|
|
$propagator = $this->propagator;
|
|
|
|
$propagatorListener = function ($path) use ($mount, $propagator) {
|
|
|
|
$fullPath = Filesystem::normalizePath($mount->getMountPoint() . $path);
|
|
|
|
$propagator->addChange($fullPath);
|
|
|
|
};
|
|
|
|
$scanner->listen('\OC\Files\Cache\Scanner', 'addToCache', $propagatorListener);
|
|
|
|
$scanner->listen('\OC\Files\Cache\Scanner', 'removeFromCache', $propagatorListener);
|
2013-07-19 14:44:47 +00:00
|
|
|
}
|
|
|
|
|
2014-02-19 08:31:54 +00:00
|
|
|
/**
|
|
|
|
* @param string $dir
|
|
|
|
*/
|
2013-07-19 14:44:47 +00:00
|
|
|
public function backgroundScan($dir) {
|
|
|
|
$mounts = $this->getMounts($dir);
|
|
|
|
foreach ($mounts as $mount) {
|
2013-09-15 18:38:57 +00:00
|
|
|
if (is_null($mount->getStorage())) {
|
|
|
|
continue;
|
|
|
|
}
|
2013-07-19 14:44:47 +00:00
|
|
|
$scanner = $mount->getStorage()->getScanner();
|
|
|
|
$this->attachListener($mount);
|
|
|
|
$scanner->backgroundScan();
|
|
|
|
}
|
2014-06-02 13:17:00 +00:00
|
|
|
$this->propagator->propagateChanges(time());
|
2013-07-19 14:44:47 +00:00
|
|
|
}
|
|
|
|
|
2014-02-06 15:30:58 +00:00
|
|
|
/**
|
|
|
|
* @param string $dir
|
2014-06-25 13:22:49 +00:00
|
|
|
* @throws \OC\ForbiddenException
|
2014-02-06 15:30:58 +00:00
|
|
|
*/
|
2013-07-19 14:44:47 +00:00
|
|
|
public function scan($dir) {
|
|
|
|
$mounts = $this->getMounts($dir);
|
|
|
|
foreach ($mounts as $mount) {
|
2013-09-15 18:38:57 +00:00
|
|
|
if (is_null($mount->getStorage())) {
|
|
|
|
continue;
|
|
|
|
}
|
2014-06-25 13:22:49 +00:00
|
|
|
$storage = $mount->getStorage();
|
|
|
|
// if the home storage isn't writable then the scanner is run as the wrong user
|
|
|
|
if ($storage->instanceOfStorage('\OC\Files\Storage\Home') and
|
|
|
|
(!$storage->isCreatable('') or !$storage->isCreatable('files'))
|
|
|
|
) {
|
|
|
|
throw new ForbiddenException();
|
|
|
|
}
|
|
|
|
$scanner = $storage->getScanner();
|
2014-09-07 23:34:03 +00:00
|
|
|
$scanner->useTransactions(false);
|
2013-07-19 14:44:47 +00:00
|
|
|
$this->attachListener($mount);
|
2014-09-07 23:34:03 +00:00
|
|
|
$this->db->beginTransaction();
|
2014-06-02 13:17:00 +00:00
|
|
|
$scanner->scan('', \OC\Files\Cache\Scanner::SCAN_RECURSIVE, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
|
2014-09-07 23:34:03 +00:00
|
|
|
$this->db->commit();
|
2013-07-19 14:44:47 +00:00
|
|
|
}
|
2014-06-02 13:17:00 +00:00
|
|
|
$this->propagator->propagateChanges(time());
|
2013-07-19 14:44:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|