Completed
Push — master ( 0f1d39...28c19e )
by Joas
13s
created

Status::parseResponse()   C

Complexity

Conditions 15
Paths 23

Size

Total Lines 57
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 15.2842

Importance

Changes 0
Metric Value
dl 0
loc 57
ccs 33
cts 37
cp 0.8919
rs 6.5498
c 0
b 0
f 0
cc 15
eloc 39
nc 23
nop 2
crap 15.2842

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