Skip to content

Commit

Permalink
Merge 847c42e into e336cea
Browse files Browse the repository at this point in the history
  • Loading branch information
VicDeo committed Aug 24, 2016
2 parents e336cea + 847c42e commit 7147662
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 127 deletions.
13 changes: 0 additions & 13 deletions appinfo/app.php
Expand Up @@ -32,16 +32,3 @@
\OC::$server->getURLGenerator()
);
});

$avBinary = \OCP\Config::getAppValue('files_antivirus', 'av_path', '');
if (empty($avBinary)){
try {
$ruleMapper = $app->getContainer()->query('RuleMapper');
$rules = $ruleMapper->findAll();
if(!count($rules)) {
$ruleMapper->populate();
}
\OCP\Config::setAppValue('files_antivirus', 'av_path', '/usr/bin/clamscan');
} catch (\Exception $e) {
}
}
13 changes: 4 additions & 9 deletions appinfo/application.php
Expand Up @@ -13,7 +13,6 @@
use OCA\Files_Antivirus\AppConfig;
use OCA\Files_Antivirus\Controller\RuleController;
use OCA\Files_Antivirus\Controller\SettingsController;
use OCA\Files_Antivirus\Hooks\FilesystemHooks;
use OCA\Files_Antivirus\Db\RuleMapper;
use OCA\Files_Antivirus\BackgroundScanner;
use OCA\Files_Antivirus\ScannerFactory;
Expand Down Expand Up @@ -57,16 +56,12 @@ public function __construct (array $urlParams = array()) {
$container->registerService('BackgroundScanner', function($c) {
return new BackgroundScanner(
$c->query('ScannerFactory'),
$c->query('ServerContainer')->getUserManager(),
$c->query('L10N')
);
});
$container->registerService('FilesystemHooks', function($c) {
return new FilesystemHooks(
$c->query('ServerContainer')->getRootFolder(),
$c->query('AppConfig')
$c->query('L10N'),
$c->getServer()->getRootFolder(),
$c->getServer()->getUserSession()
);
});

$container->registerService('RuleMapper', function($c) {
return new RuleMapper(
$c->query('ServerContainer')->getDb()
Expand Down
5 changes: 2 additions & 3 deletions appinfo/info.xml
Expand Up @@ -10,13 +10,12 @@ For this app to be effective, the ClamAV virus definitions should be kept up to
<repository type="git">http://github.com/owncloud/files_antivirus.git</repository>
<licence>AGPL</licence>
<author>Manuel Delgado, Bart Visscher, thinksilicon.de, Victor Dubiniuk</author>
<version>0.8.0.2</version>
<requiremin>8</requiremin>
<version>0.8.1.0</version>
<types>
<filesystem/>
</types>
<dependencies>
<owncloud min-version="8.2" max-version="9.0" />
<owncloud min-version="9.0" max-version="9.2" />
</dependencies>
<ocsid>157439</ocsid>
</info>
8 changes: 8 additions & 0 deletions appinfo/install.php
@@ -1,3 +1,11 @@
<?php

$app = new \OCA\Files_Antivirus\AppInfo\Application();
$ruleMapper = $app->getContainer()->query('RuleMapper');
$rules = $ruleMapper->findAll();
if(!count($rules)) {
$ruleMapper->populate();
}

\OC::$server->getConfig()->setAppValue('files_antivirus', 'av_path', '/usr/bin/clamscan');
\OC::$server->getJobList()->add('OCA\Files_Antivirus\Cron\Task');
4 changes: 2 additions & 2 deletions appinfo/preupdate.php
@@ -1,6 +1,6 @@
<?php

$installedVersion=OCP\Config::getAppValue('files_antivirus', 'installed_version');
$installedVersion = \OC::$server->getConfig()->getAppValue('files_antivirus', 'installed_version');
if (version_compare($installedVersion, '0.6', '<')) {
$query = OCP\DB::prepare( 'SELECT COUNT(*) AS `count`, `fileid` FROM `*PREFIX*files_antivirus` GROUP BY `fileid` HAVING COUNT(*) > 1' );
$result = $query->execute();
Expand All @@ -12,4 +12,4 @@
if (version_compare($installedVersion, '0.6.1', '<') && version_compare($installedVersion, '0.5', '>=')) {
$alterQuery = OCP\DB::prepare( 'ALTER TABLE `*PREFIX*files_antivirus_status` RENAME TO `*PREFIX*files_avir_status`' );
$alterQuery->execute();
}
}
5 changes: 3 additions & 2 deletions appinfo/update.php
Expand Up @@ -7,7 +7,7 @@
*/


$installedVersion = \OCP\Config::getAppValue('files_antivirus', 'installed_version');
$installedVersion = \OC::$server->getConfig()->getAppValue('files_antivirus', 'installed_version');

if (version_compare($installedVersion, '0.5', '<')) {
$app = new \OCA\Files_Antivirus\AppInfo\Application();
Expand All @@ -21,8 +21,9 @@
$jobs = $jobList->getAll();
foreach ($jobs as $job) {
$jobArg = $job->getArgument();
if($jobArg[0]=='OC_Files_Antivirus_BackgroundScanner')
if($jobArg[0] === 'OC_Files_Antivirus_BackgroundScanner') {
$jobList->remove($job);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion js/settings.js
Expand Up @@ -45,7 +45,7 @@ var antivirusSettings = antivirusSettings || {
row = $(node).parent(),
data = {
id : row.data('id'),
status_type : row.find('.status-type select').val(),
statusType : row.find('.status-type select').val(),
match : row.children('.match').text(),
description : row.children('.description').text(),
status : row.find('.scan-result select').val()
Expand Down
2 changes: 1 addition & 1 deletion lib/avirwrapper.php
Expand Up @@ -70,7 +70,7 @@ function ($data) use ($scanner){
},
function () use ($scanner, $path) {
$status = $scanner->completeAsyncScan();
if ($status->getNumericStatus() == \OCA\Files_Antivirus\Status::SCANRESULT_INFECTED){
if (intval($status->getNumericStatus()) === \OCA\Files_Antivirus\Status::SCANRESULT_INFECTED){
//prevent from going to trashbin
if (App::isEnabled('files_trashbin')) {
\OCA\Files_Trashbin\Storage::preRenameHook([]);
Expand Down
190 changes: 136 additions & 54 deletions lib/backgroundscanner.php
Expand Up @@ -8,101 +8,183 @@

namespace OCA\Files_Antivirus;

use OCP\IUserManager;
use OC\Files\Filesystem;
use OCP\IL10N;

use OCA\Files_Antivirus\Item;
use OCP\Files\IRootFolder;
use OCP\IUser;
use OCP\IUserSession;

class BackgroundScanner {

const BATCH_SIZE = 10;

/** @var IRootFolder */
protected $rootFolder;

/** @var \OCP\Files\Folder[] */
protected $userFolders;

/**
* @var ScannerFactory
*/
private $scannerFactory;

/**
* @var IUserManager
*/
private $userManager;


/**
* @var IL10N
*/
private $l10n;


/** @var string */
protected $currentFilesystemUser;

/** @var \OCP\IUserSession */
protected $userSession;

/**
* A constructor
*
* @param \OCA\Files_Antivirus\ScannerFactory $scannerFactory
* @param IUserManager $userManager
* @param IL10N $l10n
* @param IRootFolder $rootFolder
* @param IUserSession $userSession
*/
public function __construct(ScannerFactory $scannerFactory, IUserManager $userManager, IL10N $l10n){
public function __construct(ScannerFactory $scannerFactory,
IL10N $l10n,
IRootFolder $rootFolder,
IUserSession $userSession
){
$this->rootFolder = $rootFolder;
$this->scannerFactory = $scannerFactory;
$this->userManager = $userManager;
$this->l10n = $l10n;
$this->userSession = $userSession;
}

/**
* Background scanner main job
* @return null
*/
public function run(){
if (!$this->initFS()) {
return;
}
// locate files that are not checked yet
$dirMimetypeId = \OC::$server->getMimeTypeLoader()->getId('httpd/unix-directory');
$sql = 'SELECT `*PREFIX*filecache`.`fileid`, `*PREFIX*storages`.*'
.' FROM `*PREFIX*filecache`'
.' LEFT JOIN `*PREFIX*files_antivirus` ON `*PREFIX*files_antivirus`.`fileid` = `*PREFIX*filecache`.`fileid`'
.' JOIN `*PREFIX*storages` ON `*PREFIX*storages`.`numeric_id` = `*PREFIX*filecache`.`storage`'
.' WHERE `mimetype` != ?'
.' AND (`*PREFIX*storages`.`id` LIKE ? OR `*PREFIX*storages`.`id` LIKE ?)'
.' AND (`*PREFIX*files_antivirus`.`fileid` IS NULL OR `mtime` > `check_time`)'
.' AND `path` LIKE ?'
.' AND `*PREFIX*filecache`.`size` != 0';
$stmt = \OCP\DB::prepare($sql, 5);
$dirMimeTypeId = \OC::$server->getMimeTypeLoader()->getId('httpd/unix-directory');
try {
$result = $stmt->execute(array($dirMimetypeId, 'local::%', 'home::%', 'files/%'));
if (\OCP\DB::isError($result)) {
\OCP\Util::writeLog('files_antivirus', __METHOD__. 'DB error: ' . \OCP\DB::getErrorMessage($result), \OCP\Util::ERROR);
return;
}
$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
$qb->select(['fc.fileid'])
->from('filecache', 'fc')
->leftJoin('fc', 'files_antivirus', 'fa', $qb->expr()->eq('fa.fileid', 'fc.fileid'))
->innerJoin(
'fc',
'storages',
'ss',
$qb->expr()->andX(
$qb->expr()->eq('fc.storage', 'ss.numeric_id'),
$qb->expr()->orX(
$qb->expr()->like('ss.id', $qb->expr()->literal('local::%')),
$qb->expr()->like('ss.id', $qb->expr()->literal('home::%'))
)
)
)
->where(
$qb->expr()->neq('fc.mimetype', $qb->expr()->literal($dirMimeTypeId))
)
->andWhere(
$qb->expr()->orX(
$qb->expr()->isNull('fa.fileid'),
$qb->expr()->gt('fc.mtime', 'fa.check_time')
)
)
->andWhere(
$qb->expr()->like('fc.path', $qb->expr()->literal('files/%'))
)
->andWhere(
$qb->expr()->neq('fc.size', $qb->expr()->literal('0'))
)
;
$result = $qb->execute();
} catch(\Exception $e) {
\OCP\Util::writeLog('files_antivirus', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR);
\OC::$server->getLogger()->error( __METHOD__ . ', exception: ' . $e->getMessage(), ['app' => 'files_antivirus']);
return;
}

$view = new \OC\Files\View('/');
while ($row = $result->fetchRow()) {
$path = $view->getPath($row['fileid']);
if (!is_null($path)) {
$item = new Item($this->l10n, $view, $path, $row['fileid']);
$scanner = $this->scannerFactory->getScanner();
$status = $scanner->scan($item);
$status->dispatch($item, true);

$cnt = 0;
while ($row = $result->fetch() && $cnt < self::BATCH_SIZE) {
try {
$fileId = $row['fileid'];
$owner = $this->getOwner($fileId);
/** @var IUser $owner */
if (!$owner instanceof IUser){
continue;
}
$this->initFilesystemForUser($owner);
$view = Filesystem::getView();
$path = $view->getPath($fileId);
if (!is_null($path)) {
$item = new Item($this->l10n, $view, $path, $fileId);
$scanner = $this->scannerFactory->getScanner();
$status = $scanner->scan($item);
$status->dispatch($item, true);
}
// increased only for successfully scanned files
$cnt = $cnt + 1;
} catch (\Exception $e){
\OC::$server->getLogger()->error( __METHOD__ . ', exception: ' . $e->getMessage(), ['app' => 'files_antivirus']);
}
}
\OC_Util::tearDownFS();
$this->tearDownFilesystem();
}


/**
* @param int $fileId
* @return IUser|null
*/
protected function getOwner($fileId){
$mountProviderCollection = \OC::$server->getMountProviderCollection();
$mountCache = $mountProviderCollection->getMountCache();
$mounts = $mountCache->getMountsForFileId($fileId);
if (!empty($mounts)) {
$user = $mounts[0]->getUser();
if ($user instanceof IUser) {
return $user;
}
}
return null;
}

/**
* @param \OCP\IUser $user
* @return \OCP\Files\Folder
*/
protected function getUserFolder(IUser $user) {
if (!isset($this->userFolders[$user->getUID()])) {
$userFolder = $this->rootFolder->getUserFolder($user->getUID());
$this->userFolders[$user->getUID()] = $userFolder;
}
return $this->userFolders[$user->getUID()];
}

/**
* A hack to access files and views. Better than before.
* @param IUser $user
*/
protected function initFS(){
//Need any valid user to mount FS
$results = $this->userManager->search('', 2, 0);
$anyUser = array_pop($results);
if (is_null($anyUser)) {
\OCP\Util::writeLog('files_antivirus', "Failed to setup file system", \OCP\Util::ERROR);
return false;
protected function initFilesystemForUser(IUser $user) {
if ($this->currentFilesystemUser !== $user->getUID()) {
if ($this->currentFilesystemUser !== '') {
$this->tearDownFilesystem();
}
Filesystem::init($user->getUID(), '/' . $user->getUID() . '/files');
$this->userSession->setUser($user);
$this->currentFilesystemUser = $user->getUID();
Filesystem::initMountPoints($user->getUID());
}
}

/**
*
*/
protected function tearDownFilesystem(){
$this->userSession->setUser(null);
\OC_Util::tearDownFS();
\OC_Util::setupFS($anyUser->getUID());
return true;
}


/**
* @deprecated since v8.0.0
*/
Expand Down
5 changes: 3 additions & 2 deletions lib/db/rule.php
Expand Up @@ -69,13 +69,14 @@ class Rule extends Entity implements JsonSerializable{
* @return array
*/
public function jsonSerialize() {
return array(
return [
'id' => $this->id,
'group_id' => $this->groupId,
'status_type' => $this->statusType,
'result' => $this->result,
'match' => $this->match,
'description' => $this->description,
'status' => $this->status
);
];
}
}

0 comments on commit 7147662

Please sign in to comment.