Completed
Pull Request — master (#225)
by Victor
05:30 queued 04:01
created

Status::parseResponse()   C

Complexity

Conditions 15
Paths 23

Size

Total Lines 61
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 16.2058

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 61
ccs 33
cts 40
cp 0.825
rs 6.2274
c 1
b 0
f 0
cc 15
eloc 42
nc 23
nop 2
crap 16.2058

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