1 | <?php |
||
15 | class Item implements IScannable{ |
||
16 | /** |
||
17 | * Scanned fileid (optional) |
||
18 | * @var int |
||
19 | */ |
||
20 | protected $id; |
||
21 | |||
22 | /** |
||
23 | * File view |
||
24 | * @var \OC\Files\View |
||
25 | */ |
||
26 | protected $view; |
||
27 | |||
28 | /** |
||
29 | * Path relative to the view |
||
30 | * @var string |
||
31 | */ |
||
32 | protected $path; |
||
33 | |||
34 | /** |
||
35 | * file handle, user to read from the file |
||
36 | * @var resource |
||
37 | */ |
||
38 | protected $fileHandle; |
||
39 | |||
40 | /** |
||
41 | * Portion size |
||
42 | * @var int |
||
43 | */ |
||
44 | protected $chunkSize; |
||
45 | |||
46 | /** |
||
47 | * Is filesize match the size conditions |
||
48 | * @var bool |
||
49 | */ |
||
50 | protected $isValidSize; |
||
51 | |||
52 | /** |
||
53 | * @var IL10N |
||
54 | */ |
||
55 | private $l10n; |
||
56 | |||
57 | 5 | public function __construct(IL10N $l10n, $view, $path, $id = null) { |
|
58 | 5 | $this->l10n = $l10n; |
|
59 | |||
60 | 5 | if (!is_object($view)){ |
|
61 | $this->logError('Can\'t init filesystem view.', $id, $path); |
||
62 | throw new \RuntimeException(); |
||
63 | } |
||
64 | |||
65 | 5 | if(!$view->file_exists($path)) { |
|
66 | 1 | $this->logError('File does not exist.', $id, $path); |
|
67 | 1 | throw new \RuntimeException(); |
|
68 | } |
||
69 | |||
70 | 5 | if (is_null($id)){ |
|
71 | 1 | $this->id = $view->getFileInfo($path)->getId(); |
|
72 | 1 | } else { |
|
73 | 4 | $this->id = $id; |
|
74 | } |
||
75 | |||
76 | 5 | $this->view = $view; |
|
77 | 5 | $this->path = $path; |
|
78 | |||
79 | 5 | $this->isValidSize = $view->filesize($path) > 0; |
|
80 | |||
81 | 5 | $application = new AppInfo\Application(); |
|
82 | 5 | $config = $application->getContainer()->query('AppConfig'); |
|
83 | 5 | $this->chunkSize = $config->getAvChunkSize(); |
|
84 | 5 | } |
|
85 | |||
86 | /** |
||
87 | * Is this file good for scanning? |
||
88 | * @return boolean |
||
89 | */ |
||
90 | 3 | public function isValid() { |
|
94 | |||
95 | /** |
||
96 | * Reads a file portion by portion until the very end |
||
97 | * @return string|boolean |
||
98 | */ |
||
99 | 3 | public function fread() { |
|
100 | 3 | if (!$this->isValid()) { |
|
101 | return; |
||
102 | } |
||
103 | 3 | if (is_null($this->fileHandle)) { |
|
104 | 3 | $this->getFileHandle(); |
|
105 | 3 | } |
|
106 | |||
107 | 3 | if (!is_null($this->fileHandle) && !$this->feof()) { |
|
108 | 3 | $chunk = fread($this->fileHandle, $this->chunkSize); |
|
109 | 3 | return $chunk; |
|
110 | } |
||
111 | 2 | return false; |
|
112 | } |
||
113 | |||
114 | /** |
||
115 | * Action to take if this item is infected |
||
116 | * @param Status $status |
||
117 | * @param boolean $isBackground |
||
118 | */ |
||
119 | 1 | public function processInfected(Status $status, $isBackground) { |
|
120 | $application = new AppInfo\Application(); |
||
121 | $appConfig = $application->getContainer()->query('AppConfig'); |
||
122 | $infectedAction = $appConfig->getAvInfectedAction(); |
||
123 | |||
124 | $shouldDelete = !$isBackground || ($isBackground && $infectedAction === 'delete'); |
||
125 | |||
126 | $message = $shouldDelete ? Activity::MESSAGE_FILE_DELETED : ''; |
||
127 | |||
128 | \OC::$server->getActivityManager()->publishActivity( |
||
129 | 'files_antivirus', |
||
130 | Activity::SUBJECT_VIRUS_DETECTED, |
||
131 | array($this->path, $status->getDetails()), |
||
132 | $message, |
||
133 | array(), |
||
134 | $this->path, |
||
135 | '', |
||
136 | $this->view->getOwner($this->path), |
||
137 | Activity::TYPE_VIRUS_DETECTED, |
||
138 | Activity::PRIORITY_HIGH |
||
139 | 1 | ); |
|
140 | if ($isBackground) { |
||
141 | if ($shouldDelete) { |
||
142 | $this->logError('Infected file deleted. ' . $status->getDetails()); |
||
143 | $this->view->unlink($this->path); |
||
144 | } else { |
||
145 | $this->logError('File is infected. ' . $status->getDetails()); |
||
146 | } |
||
147 | } else { |
||
148 | $this->logError('Virus(es) found: ' . $status->getDetails()); |
||
149 | //remove file |
||
150 | $this->view->unlink($this->path); |
||
151 | Notification::sendMail($this->path); |
||
152 | $message = $this->l10n->t( |
||
153 | "Virus detected! Can't upload the file %s", |
||
154 | array(basename($this->path)) |
||
155 | ); |
||
156 | \OCP\JSON::error(array("data" => array( "message" => $message))); |
||
157 | exit(); |
||
158 | } |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * Action to take if this item status is unclear |
||
163 | * @param Status $status |
||
164 | * @param boolean $isBackground |
||
165 | */ |
||
166 | public function processUnchecked(Status $status, $isBackground) { |
||
170 | |||
171 | /** |
||
172 | * Action to take if this item status is not infected |
||
173 | * @param Status $status |
||
174 | * @param boolean $isBackground |
||
175 | */ |
||
176 | public function processClean(Status $status, $isBackground) { |
||
177 | if (!$isBackground) { |
||
178 | return; |
||
179 | } |
||
180 | try { |
||
181 | $stmt = \OCP\DB::prepare('DELETE FROM `*PREFIX*files_antivirus` WHERE `fileid` = ?'); |
||
182 | $result = $stmt->execute(array($this->id)); |
||
183 | if (\OCP\DB::isError($result)) { |
||
184 | //TODO: Use logger |
||
185 | $this->logError(__METHOD__. ', DB error: ' . \OCP\DB::getErrorMessage()); |
||
186 | } |
||
187 | $stmt = \OCP\DB::prepare('INSERT INTO `*PREFIX*files_antivirus` (`fileid`, `check_time`) VALUES (?, ?)'); |
||
188 | $result = $stmt->execute(array($this->id, time())); |
||
189 | if (\OCP\DB::isError($result)) { |
||
190 | $this->logError(__METHOD__. ', DB error: ' . \OCP\DB::getErrorMessage()); |
||
191 | } |
||
192 | } catch(\Exception $e) { |
||
193 | \OCP\Util::writeLog('files_antivirus', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR); |
||
194 | } |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * Check if the end of file is reached |
||
199 | * @return boolean |
||
200 | */ |
||
201 | 3 | private function feof() { |
|
202 | 3 | $isDone = feof($this->fileHandle); |
|
203 | 3 | if ($isDone) { |
|
204 | 2 | $this->logDebug('Scan is done'); |
|
205 | 2 | fclose($this->fileHandle); |
|
206 | 2 | $this->fileHandle = null; |
|
207 | 2 | } |
|
208 | 3 | return $isDone; |
|
209 | } |
||
210 | |||
211 | /** |
||
212 | * Opens a file for reading |
||
213 | * @throws \RuntimeException |
||
214 | */ |
||
215 | 3 | private function getFileHandle() { |
|
225 | |||
226 | /** |
||
227 | * @param string $message |
||
228 | */ |
||
229 | 3 | public function logDebug($message) { |
|
235 | |||
236 | /** |
||
237 | * @param string $message |
||
238 | * @param int $id optional |
||
239 | * @param string $path optional |
||
240 | */ |
||
241 | 1 | public function logError($message, $id=null, $path=null) { |
|
252 | } |
||
253 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.