Completed
Push — master ( 4fe26b...4d8bf0 )
by
unknown
03:55
created

Status   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 140
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 77.63%

Importance

Changes 0
Metric Value
wmc 26
lcom 1
cbo 1
dl 0
loc 140
ccs 59
cts 76
cp 0.7763
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getNumericStatus() 0 3 1
A getDetails() 0 3 1
A getResponseRules() 0 13 4
C parseResponse() 0 57 15
A dispatch() 0 13 4
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
	 * @return int
48
	 */
49 8
	public function getNumericStatus(){
50 8
		return $this->numericStatus;
51
	}
52
	
53
	/**
54
	 * Get scan status as string
55
	 * @return string
56
	 */
57 4
	public function getDetails(){
58 4
		return $this->details;
59
	}
60
	
61
	/**
62
	 * @param string $rawResponse
63
	 * @param integer $result
64
	 */
65 8
	public function parseResponse($rawResponse, $result = null){
66 8
		$matches = array();
67 8
		$ruleMapper = new Db\RuleMapper(\OC::$server->getDb());
68 8
		if (is_null($result)){ // Daemon or socket mode
69
			try{
70 5
				$allRules = $this->getResponseRules();
71 5
			} catch (\Exception $e){
72
				\OCP\Util::writeLog('files_antivirus', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR);
73
				return;
74
			}
75
			
76 5
			$isMatched = false;
77 5
			foreach ($allRules as $rule){
78 5
				if (preg_match($rule->getMatch(), $rawResponse, $matches)){
79 4
					$isMatched = true;
80 4
					$this->numericStatus = intval($rule->getStatus());
81 4
					if (intval($rule->getStatus())===self::SCANRESULT_CLEAN){
82 1
						$this->details = '';
83 1
					} else {
84 4
						$this->details = isset($matches[1]) ? $matches[1] : 'unknown';
85
					}
86 4
					break;
87
				}
88 5
			}
89
			
90 5
			if (!$isMatched){
91 3
				$this->numericStatus = self::SCANRESULT_UNCHECKED;
92 3
				$this->details = 'No matching rules. Please check antivirus rules.';
93 3
			}
94
			
95 5
		} else { // Executable mode
96 4
			$scanStatus = $ruleMapper->findByResult($result);
97 4
			if (is_array($scanStatus) && count($scanStatus)){
98 4
				$this->numericStatus = intval($scanStatus[0]->getStatus());
99 4
				$this->details = $scanStatus[0]->getDescription();
100 4
			}
101
			
102 4
			switch($this->numericStatus) {
103 4
				case self::SCANRESULT_INFECTED:
104 2
					$report = array();
105 2
					$rawResponse = explode("\n", $rawResponse);
106
					
107 2
					foreach ($rawResponse as $line){	
108 2
						if (preg_match('/.*: (.*) FOUND\s*$/', $line, $matches)) {
109 2
							$report[] = $matches[1];
110 2
						}
111 2
					}
112 2
					$this->details = implode(', ', $report);
113
					
114 2
					break;
115 4
				case self::SCANRESULT_UNCHECKED:
116 1
					if (!$this->details) {
117
						$this->details = 'No matching rule for exit code ' .  $this->numericStatus .'. Please check antivirus rules configuration.' ;
118
					}
119 4
			}
120
		}
121 8
	}
122
	
123 5
	protected function getResponseRules(){
124 5
		$infectedRules = $this->ruleMapper->findAllMatchedByStatus(self::SCANRESULT_INFECTED);
125 5
		$uncheckedRules = $this->ruleMapper->findAllMatchedByStatus(self::SCANRESULT_UNCHECKED);
126 5
		$cleanRules = $this->ruleMapper->findAllMatchedByStatus(self::SCANRESULT_CLEAN);
127
		
128 5
		$infectedRules = $infectedRules ? $infectedRules : array();
129 5
		$uncheckedRules = $uncheckedRules ? $uncheckedRules : array();
130 5
		$cleanRules = $cleanRules ? $cleanRules : array();
131
		
132
		// order: clean, infected, try to guess error
133 5
		$allRules = array_merge($cleanRules, $infectedRules, $uncheckedRules);
134 5
		return $allRules;
135
	}
136
	
137
	public function dispatch($item, $isBackground = false){
138
		switch($this->getNumericStatus()) {
139
			case self::SCANRESULT_UNCHECKED:
140
				$item->processUnchecked($this, $isBackground);
141
				break;
142
			case self::SCANRESULT_INFECTED:
143
				$item->processInfected($this, $isBackground);
144
				break;
145
			case self::SCANRESULT_CLEAN:
146
				$item->processClean($this, $isBackground);
147
				break;
148
		}
149
	}
150
}
151