Completed
Push — master ( aa875b...df65e3 )
by Roeland
02:29
created

BackgroundScanner   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 191
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 5

Test Coverage

Coverage 52.22%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 19
c 1
b 0
f 0
lcom 2
cbo 5
dl 0
loc 191
ccs 47
cts 90
cp 0.5222
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
B run() 0 28 6
A getFilesForScan() 0 53 3
A scanOneFile() 0 11 2
A getUserFolder() 0 7 2
A initFilesystemForUser() 0 11 3
A tearDownFilesystem() 0 4 1
A check() 0 2 1
1
<?php
2
/**
3
 * Copyright (c) 2012 Bart Visscher <[email protected]>
4
 * This file is licensed under the Affero General Public License version 3 or
5
 * later.
6
 * See the COPYING-README file.
7
 */
8
9
namespace OCA\Files_Antivirus;
10
11
use Doctrine\DBAL\Platforms\MySqlPlatform;
12
use OCA\Files_Antivirus\Scanner\ScannerFactory;
13
use OC\Files\Filesystem;
14
use OCP\IL10N;
15
use OCP\Files\IRootFolder;
16
use OCP\IUser;
17
use OCP\IUserSession;
18
19
class BackgroundScanner {
20
21
	const BATCH_SIZE = 10;
22
23
	/** @var IRootFolder */
24
	protected $rootFolder;
25
26
	/** @var \OCP\Files\Folder[] */
27
	protected $userFolders;
28
29
	/** @var ScannerFactory */
30
	private $scannerFactory;
31
32
	/** @var IL10N */
33
	private $l10n;
34
35
	/** @var  AppConfig  */
36
	private $appConfig;
37
38
	/** @var string */
39
	protected $currentFilesystemUser;
40
41
	/** @var \OCP\IUserSession */
42
	protected $userSession;
43
44
	/**
45
	 * A constructor
46
	 *
47
	 * @param ScannerFactory $scannerFactory
48
	 * @param IL10N $l10n
49
	 * @param AppConfig $appConfig
50
	 * @param IRootFolder $rootFolder
51
	 * @param IUserSession $userSession
52
	 */
53 1
	public function __construct(ScannerFactory $scannerFactory,
54
								IL10N $l10n,
55
								AppConfig $appConfig,
56
								IRootFolder $rootFolder,
57
								IUserSession $userSession
58
	){
59 1
		$this->rootFolder = $rootFolder;
60 1
		$this->scannerFactory = $scannerFactory;
61 1
		$this->l10n = $l10n;
62 1
		$this->appConfig = $appConfig;
63 1
		$this->userSession = $userSession;
64 1
	}
65
	
66
	/**
67
	 * Background scanner main job
68
	 * @return null
69
	 */
70 1
	public function run(){
71
		// locate files that are not checked yet
72
		try {
73 1
			$result = $this->getFilesForScan();
74
		} catch(\Exception $e) {
75
			\OC::$server->getLogger()->error( __METHOD__ . ', exception: ' . $e->getMessage(), ['app' => 'files_antivirus']);
76
			return;
77
		}
78
79 1
		$cnt = 0;
80 1
		while (($row = $result->fetch()) && $cnt < self::BATCH_SIZE) {
81
			try {
82
				$fileId = $row['fileid'];
83
				$userId = $row['user_id'];
84
				/** @var IUser $owner */
85
				$owner = \OC::$server->getUserManager()->get($userId);
86
				if (!$owner instanceof IUser){
0 ignored issues
show
Bug introduced by
The class OCP\IUser does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
87
					continue;
88
				}
89
				$this->scanOneFile($owner, $fileId);
90
				// increased only for successfully scanned files
91
				$cnt = $cnt + 1;
92
			} catch (\Exception $e){
93
				\OC::$server->getLogger()->error( __METHOD__ . ', exception: ' . $e->getMessage(), ['app' => 'files_antivirus']);
94
			}
95
		}
96 1
		$this->tearDownFilesystem();
97 1
	}
98
99 1
	protected function getFilesForScan(){
100 1
		$dirMimeTypeId = \OC::$server->getMimeTypeLoader()->getId('httpd/unix-directory');
101
102 1
		$dbConnection = \OC::$server->getDatabaseConnection();
103 1
		$qb = $dbConnection->getQueryBuilder();
104 1
		if ($dbConnection->getDatabasePlatform() instanceof MySqlPlatform) {
0 ignored issues
show
Bug introduced by
The class Doctrine\DBAL\Platforms\MySqlPlatform does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
105
			$concatFunction = $qb->createFunction(
106
				"CONCAT('/', mnt.user_id, '/')"
107
			);
108
		} else {
109 1
			$concatFunction = $qb->createFunction(
110 1
				"'/' || " . $qb->getColumnName('mnt.user_id') . " || '/'"
111
			);
112
		}
113
114 1
		$sizeLimit = intval($this->appConfig->getAvMaxFileSize());
115 1
		if ( $sizeLimit === -1 ){
116 1
			$sizeLimitExpr = $qb->expr()->neq('fc.size', $qb->expr()->literal('0'));
117
		} else {
118
			$sizeLimitExpr = $qb->expr()->andX(
119
				$qb->expr()->neq('fc.size', $qb->expr()->literal('0')),
120
				$qb->expr()->lt('fc.size', $qb->expr()->literal((string) $sizeLimit))
121
			);
122
		}
123
124 1
		$qb->select(['fc.fileid', 'mnt.user_id'])
125 1
			->from('filecache', 'fc')
126 1
			->leftJoin('fc', 'files_antivirus', 'fa', $qb->expr()->eq('fa.fileid', 'fc.fileid'))
127 1
			->innerJoin(
128 1
				'fc',
129 1
				'mounts',
130 1
				'mnt',
131 1
				$qb->expr()->andX(
132 1
					$qb->expr()->eq('fc.storage', 'mnt.storage_id'),
133 1
					$qb->expr()->eq('mnt.mount_point', $concatFunction)
134
				)
135
			)
136 1
			->where(
137 1
				$qb->expr()->neq('fc.mimetype', $qb->expr()->literal($dirMimeTypeId))
138
			)
139 1
			->andWhere(
140 1
				$qb->expr()->orX(
141 1
					$qb->expr()->isNull('fa.fileid'),
142 1
					$qb->expr()->gt('fc.mtime', 'fa.check_time')
143
				)
144
			)
145 1
			->andWhere(
146 1
				$qb->expr()->like('fc.path', $qb->expr()->literal('files/%'))
147
			)
148 1
			->andWhere( $sizeLimitExpr )
149
		;
150 1
		return $qb->execute();
151
	}
152
153
	/**
154
	 * @param IUser $owner
155
	 * @param int $fileId
156
	 */
157
	protected function scanOneFile($owner, $fileId){
158
		$this->initFilesystemForUser($owner);
159
		$view = Filesystem::getView();
160
		$path = $view->getPath($fileId);
161
		if (!is_null($path)) {
162
			$item = new Item($this->l10n, $view, $path, $fileId);
163
			$scanner = $this->scannerFactory->getScanner();
164
			$status = $scanner->scan($item);
165
			$status->dispatch($item, true);
166
		}
167
	}
168
169
	/**
170
	 * @param \OCP\IUser $user
171
	 * @return \OCP\Files\Folder
172
	 */
173
	protected function getUserFolder(IUser $user) {
174
		if (!isset($this->userFolders[$user->getUID()])) {
175
			$userFolder = $this->rootFolder->getUserFolder($user->getUID());
176
			$this->userFolders[$user->getUID()] = $userFolder;
177
		}
178
		return $this->userFolders[$user->getUID()];
179
	}
180
181
	/**
182
	 * @param IUser $user
183
	 */
184
	protected function initFilesystemForUser(IUser $user) {
185
		if ($this->currentFilesystemUser !== $user->getUID()) {
186
			if ($this->currentFilesystemUser !== '') {
187
				$this->tearDownFilesystem();
188
			}
189
			Filesystem::init($user->getUID(), '/' . $user->getUID() . '/files');
190
			$this->userSession->setUser($user);
191
			$this->currentFilesystemUser = $user->getUID();
192
			Filesystem::initMountPoints($user->getUID());
193
		}
194
	}
195
196
	/**
197
	 *
198
	 */
199 1
	protected function tearDownFilesystem(){
200 1
		$this->userSession->setUser(null);
201 1
		\OC_Util::tearDownFS();
202 1
	}
203
204
	/**
205
	 * @deprecated since  v8.0.0
206
	 */
207
	public static function check(){
208
	}
209
}
210