Completed
Pull Request — master (#133)
by Victor
03:28
created

AvirWrapper   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 111
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 9
c 4
b 0
f 0
lcom 1
cbo 2
dl 0
loc 111
ccs 47
cts 47
cp 1
rs 10

3 Methods

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