Completed
Pull Request — master (#155)
by Victor
12:24 queued 10:33
created

AvirWrapper   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 119
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 94.64%

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 9
lcom 1
cbo 2
dl 0
loc 119
ccs 53
cts 56
cp 0.9464
rs 10
c 6
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A isWritingMode() 0 9 1
B fopen() 0 64 7
1
<?php
2
/**
3
 * Copyright (c) 2014 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 OC\Files\Filesystem;
12
use OC\Files\Storage\Wrapper\Wrapper;
13
use \OCP\App;
14
use \OCP\IConfig;
15
use \OCP\IL10N;
16
use \OCP\ILogger;
17
use \OCP\Files\InvalidContentException;
18
use Icewind\Streams\CallbackWrapper;
19
20
21
class AvirWrapper extends Wrapper{
22
	
23
	/**
24
	 * Modes that are used for writing 
25
	 * @var array 
26
	 */
27
	private $writingModes = array('r+', 'w', 'w+', 'a', 'a+', 'x', 'x+', 'c', 'c+');
28
	
29
	/**
30
	 * @var \OCA\Files_Antivirus\ScannerFactory
31
	 */
32
	protected $scannerFactory;
33
	
34
	/**
35
	 * @var IL10N 
36
	 */
37
	protected $l10n;
38
	
39
	/**
40
	 * @var ILogger;
41
	 */
42
	protected $logger;
43
44
	/**
45
	 * @param array $parameters
46
	 */
47 2
	public function __construct($parameters) {
48 2
		parent::__construct($parameters);
49 2
		$this->scannerFactory = $parameters['scannerFactory'];
50 2
		$this->l10n = $parameters['l10n'];
51 2
		$this->logger = $parameters['logger'];
52 2
	}
53
	
54
	/**
55
	 * Asynchronously scan data that are written to the file
56
	 * @param string $path
57
	 * @param string $mode
58
	 * @return resource | bool
59
	 */
60 3
	public function fopen($path, $mode){
61 3
		$stream = $this->storage->fopen($path, $mode);
62 3
		if (is_resource($stream) && $this->isWritingMode($mode)) {
63
			try {
64 2
				$scanner = $this->scannerFactory->getScanner();
65 2
				$scanner->initScanner();
66 2
				return CallBackWrapper::wrap(
67
					$stream,
68 2
					null,
69
					function ($data) use ($scanner){
70 2
						$scanner->onAsyncData($data);
71 2
					}, 
72 2
					function () use ($scanner, $path) {
73 2
						$status = $scanner->completeAsyncScan();
74 2
						if (intval($status->getNumericStatus()) === \OCA\Files_Antivirus\Status::SCANRESULT_INFECTED){
75
							//prevent from going to trashbin
76 2
							if (App::isEnabled('files_trashbin')) {
77 2
								\OCA\Files_Trashbin\Storage::preRenameHook([
78 2
									Filesystem::signal_param_oldpath => '',
79
									Filesystem::signal_param_newpath => ''
80
								]);
81
							}
82
							
83 2
							$owner = $this->getOwner($path);
84 2
							$this->unlink($path);
85
86 2
							if (App::isEnabled('files_trashbin')) {
87 2
								\OCA\Files_Trashbin\Storage::postRenameHook([]);
88
							}
89 2
							$this->logger->warning(
90 2
								'Infected file deleted. ' . $status->getDetails()
91 2
								. ' Account: ' . $owner . ' Path: ' . $path,
92 2
								['app' => 'files_antivirus']
93
							);
94
95 2
							\OC::$server->getActivityManager()->publishActivity(
96 2
								'files_antivirus',
97 2
								Activity::SUBJECT_VIRUS_DETECTED,
98 2
								[$path, $status->getDetails()],
99 2
								Activity::MESSAGE_FILE_DELETED,
100 2
								[],
101
								$path,
102 2
								'',
103
								$owner,
104 2
								Activity::TYPE_VIRUS_DETECTED,
105 2
								Activity::PRIORITY_HIGH
106
							);
107
											
108 2
							throw new InvalidContentException(
109 2
								$this->l10n->t(
110 2
									'Virus %s is detected in the file. Upload cannot be completed.',
111 2
									$status->getDetails()
112
								)
113
							);
114
						}
115 2
					}
116
				);
117 2
			} catch (\Exception $e){
118 2
				$message = 	implode(' ', [ __CLASS__, __METHOD__, $e->getMessage()]);
119 2
				$this->logger->warning($message);
120
			}
121
		}
122 3
		return $stream;
123
	}
124
	
125
	/**
126
	 * Checks whether passed mode is suitable for writing 
127
	 * @param string $mode
128
	 * @return bool
129
	 */
130 3
	private function isWritingMode($mode){
131
		// Strip unessential binary/text flags
132 3
		$cleanMode = str_replace(
133 3
			['t', 'b'],
134 3
			['', ''],
135 3
			$mode
136
		);
137 3
		return in_array($cleanMode, $this->writingModes);
138
	}
139
}
140