Completed
Pull Request — master (#58)
by Roeland
01:39
created

Item::processInfected()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 23
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 23
ccs 0
cts 19
cp 0
rs 9.0856
cc 3
eloc 17
nc 4
nop 1
crap 12
1
<?php
2
/**
3
 * Copyright (c) 2015 Victor Dubiniuk <[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 OCA\Files_Antivirus\Activity\Provider;
12
use OCA\Files_Antivirus\AppInfo\Application;
13
use OCA\Files_Antivirus\Db\ItemMapper;
14
use OCP\Activity\IManager as ActivityManager;
15
use OCP\App;
16
use OCP\AppFramework\Db\DoesNotExistException;
17
use OCP\Files\File;
18
use OCP\IL10N;
19
use OCP\ILogger;
20
21
class Item implements IScannable{
22
	/**
23
	 * file handle, user to read from the file
24
	 * @var resource
25
	 */
26
	protected $fileHandle;
27
28
	/** @var IL10N */
29
	private $l10n;
30
31
	/** @var AppConfig */
32
	private $config;
33
34
	/** @var ActivityManager */
35
	private $activityManager;
36
37
	/** @var ItemMapper */
38
	private $itemMapper;
39
40
	/** @var ILogger */
41
	private $logger;
42
43
	/** @var File */
44
	private $file;
45
46 View Code Duplication
	public function __construct(IL10N $l10n,
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
47
								AppConfig $appConfig,
48
								ActivityManager $activityManager,
49
								ItemMapper $itemMapper,
50
								ILogger $logger,
51
								File $file) {
52
		$this->l10n = $l10n;
53
		$this->config = $appConfig;
54
		$this->activityManager = $activityManager;
55
		$this->itemMapper = $itemMapper;
56
		$this->logger = $logger;
57
		$this->file = $file;
58
	}
59
60
	/**
61
	 * Is this file good for scanning? 
62
	 * @return boolean
63
	 */
64
	public function isValid() {
65
		return $this->file->getSize() > 0;
66
	}
67
68
	/**
69
	 * Reads a file portion by portion until the very end
70
	 * @return string|boolean
71
	 */
72
	public function fread() {
73
		if (!$this->isValid()) {
74
			return false;
75
		}
76
		if (is_null($this->fileHandle)) {
77
			$this->getFileHandle();
78
		}
79
		
80
		if (!is_null($this->fileHandle) && !$this->feof()) {
81
			return fread($this->fileHandle, $this->config->getAvChunkSize());
82
		}
83
		return false;
84
	}
85
86
	/**
87
	 * Action to take if this item is infected
88
	 * @param Status $status
89
	 */
90
	public function processInfected(Status $status) {
91
		$infectedAction = $this->config->getAvInfectedAction();
92
		
93
		$shouldDelete = $infectedAction === 'delete';
94
		
95
		$message = $shouldDelete ? Provider::MESSAGE_FILE_DELETED : '';
96
97
		$activity = $this->activityManager->generateEvent();
98
		$activity->setApp(Application::APP_NAME)
99
			->setSubject(Provider::SUBJECT_VIRUS_DETECTED, [$this->file->getPath(), $status->getDetails()])
100
			->setMessage($message)
101
			->setObject('file', $this->file->getId(), $this->file->getPath())
102
			->setAffectedUser($this->file->getOwner()->getUID())
103
			->setType(Provider::TYPE_VIRUS_DETECTED);
104
		$this->activityManager->publish($activity);
105
106
		if ($shouldDelete) {
107
			$this->logError('Infected file deleted. ' . $status->getDetails());
108
			$this->deleteFile();
109
		} else {
110
			$this->logError('File is infected. '  . $status->getDetails());
111
		}
112
	}
113
114
	/**
115
	 * Action to take if this item status is unclear
116
	 * @param Status $status
117
	 * @param boolean $isBackground
0 ignored issues
show
Bug introduced by
There is no parameter named $isBackground. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
118
	 */
119
	public function processUnchecked(Status $status) {
120
		//TODO: Show warning to the user: The file can not be checked
121
		$this->logError('Not Checked. ' . $status->getDetails());
122
	}
123
124
	/**
125
	 * Action to take if this item status is not infected
126
	 * @param Status $status
127
	 * @param boolean $isBackground
128
	 */
129
	public function processClean(Status $status, $isBackground) {
0 ignored issues
show
Unused Code introduced by
The parameter $status is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
130
		if (!$isBackground) {
131
			return;
132
		}
133
		try {
134
			try {
135
				$item = $this->itemMapper->findByFileId($this->file->getId());
136
				$this->itemMapper->delete($item);
137
			} catch (DoesNotExistException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\AppFramework\Db\DoesNotExistException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
138
				//Just ignore
139
			}
140
141
			$item = new \OCA\Files_Antivirus\Db\Item();
142
			$item->setFileid($this->file->getId());
143
			$item->setCheckTime(time());
144
			$this->itemMapper->insert($item);
145
		} catch(\Exception $e) {
146
			$this->logger->error(__METHOD__.', exception: '.$e->getMessage(), ['app' => 'files_antivirus']);
147
		}
148
	}
149
150
	/**
151
	 * Check if the end of file is reached
152
	 * @return boolean
153
	 */
154
	private function feof() {
155
		$isDone = feof($this->fileHandle);
156
		if ($isDone) {
157
			$this->logDebug('Scan is done');
158
			fclose($this->fileHandle);
159
			$this->fileHandle = null;
160
		}
161
		return $isDone;
162
	}
163
164
	/**
165
	 * Opens a file for reading
166
	 * @throws \RuntimeException
167
	 */
168
	private function getFileHandle() {
169
		$fileHandle = $this->file->fopen('r');
170
		if ($fileHandle === false) {
171
			$this->logError('Can not open for reading.');
172
			throw new \RuntimeException();
173
		}
174
175
		$this->logDebug('Scan started');
176
		$this->fileHandle = $fileHandle;
177
	}
178
179
	/**
180
	 * Delete infected file
181
	 */
182
	private function deleteFile() {
183
		//prevent from going to trashbin
184
		if (App::isEnabled('files_trashbin')) {
185
			\OCA\Files_Trashbin\Storage::preRenameHook([]);
186
		}
187
		$this->file->delete();
188
		if (App::isEnabled('files_trashbin')) {
189
			\OCA\Files_Trashbin\Storage::postRenameHook([]);
190
		}
191
	}
192
193
	/**
194
	 * @param string $message
195
	 */
196
	public function logDebug($message) {
197
		$extra = ' File: ' . $this->file->getId()
198
				. 'Account: ' . $this->file->getOwner()->getUID()
199
				. ' Path: ' . $this->file->getPath();
200
		$this->logger->debug($message . $extra, ['app' => 'files_antivirus']);
201
	}
202
203
	/**
204
	 * @param string $message
205
	 */
206
	public function logError($message) {
207
		$ownerInfo = 'Account: ' . $this->file->getOwner()->getUID();
208
		$extra = ' File: ' . $this->file->getId()
209
				. $ownerInfo 
210
				. ' Path: ' . $this->file->getPath();
211
		$this->logger->error($message . $extra, ['app' => 'files_antivirus']);
212
	}
213
}
214