Completed
Push — master ( f8b57c...5fa6d3 )
by Phil
11s
created

Status::parseResponse()   C

Complexity

Conditions 15
Paths 23

Size

Total Lines 60

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 42
CRAP Score 15.6565

Importance

Changes 0
Metric Value
dl 0
loc 60
ccs 42
cts 49
cp 0.8571
rs 5.9166
c 0
b 0
f 0
cc 15
nc 23
nop 2
crap 15.6565

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * ownCloud - files_antivirus
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Viktar Dubiniuk <[email protected]>
9
 *
10
 * @copyright Viktar Dubiniuk 2014-2018
11
 * @license AGPL-3.0
12
 */
13
14
namespace OCA\Files_Antivirus;
15
16
class Status {
17
	
18
	/*
19
	 *  The file was not checked (e.g. because the AV daemon wasn't running).
20
	 */
21
	const SCANRESULT_UNCHECKED = -1;
22
23
	/*
24
	 *  The file was checked and found to be clean.
25
	 */
26
	const SCANRESULT_CLEAN = 0;
27
28
	/*
29
	 *  The file was checked and found to be infected.
30
	 */
31
	const SCANRESULT_INFECTED = 1;
32
	
33
	/*
34
	 * Should be SCANRESULT_UNCHECKED | SCANRESULT_INFECTED | SCANRESULT_CLEAN
35
	 */
36
	protected $numericStatus;
37
	
38
	/*
39
	 * Virus name or error message
40
	 */
41
	protected $details = "";
42
	
43
	protected $ruleMapper;
44
	
45 10
	public function __construct() {
46 10
		$this->numericStatus = self::SCANRESULT_UNCHECKED;
47 10
		$this->ruleMapper = new Db\RuleMapper(\OC::$server->getDb());
48 10
	}
49
	
50
	/**
51
	 * Get scan status as integer
52
	 *
53
	 * @return int
54
	 */
55 8
	public function getNumericStatus() {
56 8
		return $this->numericStatus;
57
	}
58
	
59
	/**
60
	 * Get scan status as string
61
	 *
62
	 * @return string
63
	 */
64 4
	public function getDetails() {
65 4
		return $this->details;
66
	}
67
	
68
	/**
69
	 * @param string $rawResponse
70
	 * @param integer $result
71
	 */
72 8
	public function parseResponse($rawResponse, $result = null) {
73 8
		$matches = [];
74 8
		$ruleMapper = new Db\RuleMapper(\OC::$server->getDb());
75 8
		if ($result === null) { // Daemon or socket mode
76
			try {
77 5
				$allRules = $this->getResponseRules();
78 5
			} catch (\Exception $e) {
79
				\OCP\Util::writeLog(
80
					'files_antivirus',
81
					__METHOD__.', exception: '.$e->getMessage(),
82
					\OCP\Util::ERROR
83
				);
84
				return;
85
			}
86
			
87 5
			$isMatched = false;
88 5
			foreach ($allRules as $rule) {
89 5
				if (\preg_match($rule->getMatch(), $rawResponse, $matches)) {
90 4
					$isMatched = true;
91 4
					$this->numericStatus = \intval($rule->getStatus());
92 4
					if (\intval($rule->getStatus()) === self::SCANRESULT_CLEAN) {
93 1
						$this->details = '';
94 1
					} else {
95 4
						$this->details = isset($matches[1]) ? $matches[1] : 'unknown';
96
					}
97 4
					break;
98
				}
99 5
			}
100
			
101 5
			if (!$isMatched) {
102 3
				$this->numericStatus = self::SCANRESULT_UNCHECKED;
103 3
				$this->details = 'No matching rules. Please check antivirus rules.';
104 3
			}
105 5
		} else { // Executable mode
106 4
			$scanStatus = $ruleMapper->findByResult($result);
107 4
			if (\is_array($scanStatus) && \count($scanStatus)) {
108 4
				$this->numericStatus = \intval($scanStatus[0]->getStatus());
109 4
				$this->details = $scanStatus[0]->getDescription();
110 4
			}
111
			
112 4
			switch ($this->numericStatus) {
113 4
				case self::SCANRESULT_INFECTED:
114 2
					$report = [];
115 2
					$rawResponse = \explode("\n", $rawResponse);
116
					
117 2
					foreach ($rawResponse as $line) {
118 2
						if (\preg_match('/.*: (.*) FOUND\s*$/', $line, $matches)) {
119 2
							$report[] = $matches[1];
120 2
						}
121 2
					}
122 2
					$this->details = \implode(', ', $report);
123
					
124 2
					break;
125 4
				case self::SCANRESULT_UNCHECKED:
126 1
					if (!$this->details) {
127
						$this->details = 'No matching rule for exit code ' .  $this->numericStatus .'. Please check antivirus rules configuration.' ;
128
					}
129 4
			}
130
		}
131 8
	}
132
	
133 5
	protected function getResponseRules() {
134 5
		$infectedRules = $this->ruleMapper->findAllMatchedByStatus(self::SCANRESULT_INFECTED);
135 5
		$uncheckedRules = $this->ruleMapper->findAllMatchedByStatus(self::SCANRESULT_UNCHECKED);
136 5
		$cleanRules = $this->ruleMapper->findAllMatchedByStatus(self::SCANRESULT_CLEAN);
137
		
138 5
		$infectedRules = $infectedRules ? $infectedRules : [];
139 5
		$uncheckedRules = $uncheckedRules ? $uncheckedRules : [];
140 5
		$cleanRules = $cleanRules ? $cleanRules : [];
141
		
142
		// order: clean, infected, try to guess error
143 5
		$allRules = \array_merge($cleanRules, $infectedRules, $uncheckedRules);
144 5
		return $allRules;
145
	}
146
	
147
	public function dispatch($item, $isBackground = false) {
148
		switch ($this->getNumericStatus()) {
149
			case self::SCANRESULT_UNCHECKED:
150
				$item->processUnchecked($this, $isBackground);
151
				break;
152
			case self::SCANRESULT_INFECTED:
153
				$item->processInfected($this, $isBackground);
154
				break;
155
			case self::SCANRESULT_CLEAN:
156
				$item->processClean($this, $isBackground);
157
				break;
158
		}
159
	}
160
}
161