Completed
Pull Request — stable9 (#105)
by Victor
03:21
created

Status::getNumericStatus()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1
Metric Value
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
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
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 4
	public function __construct(){
41 4
		$this->numericStatus = self::SCANRESULT_UNCHECKED;
42 4
		$this->ruleMapper = new Db\RuleMapper(\OC::$server->getDb());
43 4
	}
44
	
45
	/**
46
	 * Get scan status as integer
47
	 * @return int
48
	 */
49 4
	public function getNumericStatus(){
50 4
		return $this->numericStatus;
51
	}
52
	
53
	/**
54
	 * Get scan status as string
55
	 * @return string
56
	 */
57 1
	public function getDetails(){
58 1
		return $this->details;
59
	}
60
	
61
	/**
62
	 * @param string $rawResponse
63
	 * @param integer $result
64
	 */
65 4
	public function parseResponse($rawResponse, $result = null){
66 4
		$matches = array();
67 4
		$ruleMapper = new Db\RuleMapper(\OC::$server->getDb());
68 4
		if (is_null($result)){ // Daemon or socket mode
69
			try{
70 1
				$allRules = $this->getResponseRules();
71 1
			} catch (\Exception $e){
72
				\OCP\Util::writeLog('files_antivirus', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR);
73
				return;
74
			}
75
			
76 1
			$isMatched = false;
77 1
			foreach ($allRules as $rule){
78 1
				if (preg_match($rule->getMatch(), $rawResponse, $matches)){
79 1
					$isMatched = true;
80 1
					$this->numericStatus = $rule->getStatus();
81 1
					if ($rule->getStatus()==self::SCANRESULT_CLEAN){
82 1
						$this->details = '';
83 1
					} else {
84 1
						$this->details = isset($matches[1]) ? $matches[1] : 'unknown';
85
					}
86 1
					break;
87
				}
88 1
			}
89
			
90 1
			if (!$isMatched){
91 1
				$this->numericStatus = self::SCANRESULT_UNCHECKED;
92 1
				$this->details = 'No matching rules. Please check antivirus rules.';
93 1
			}
94
			
95 1
		} else { // Executable mode
96 4
			$scanStatus = $ruleMapper->findByResult($result);
97 4
			if (is_array($scanStatus) && count($scanStatus)){
98 4
				$this->numericStatus = $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 3
				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 4
	}
122
	
123 1
	protected function getResponseRules(){
124 1
		$infectedRules = $this->ruleMapper->findAllMatchedByStatus(self::SCANRESULT_INFECTED);
125 1
		$uncheckedRules = $this->ruleMapper->findAllMatchedByStatus(self::SCANRESULT_UNCHECKED);
126 1
		$cleanRules = $this->ruleMapper->findAllMatchedByStatus(self::SCANRESULT_CLEAN);
127
		
128 1
		$infectedRules = $infectedRules ? $infectedRules : array();
129 1
		$uncheckedRules = $uncheckedRules ? $uncheckedRules : array();
130 1
		$cleanRules = $cleanRules ? $cleanRules : array();
131
		
132
		// order: clean, infected, try to guess error
133 1
		$allRules = array_merge($cleanRules, $infectedRules, $uncheckedRules);
134 1
		return $allRules;
135
	}
136
	
137 1
	public function dispatch($item, $isBackground = false){
138 1
		switch($this->getNumericStatus()) {
139 1
			case self::SCANRESULT_UNCHECKED:
140
				$item->processUnchecked($this, $isBackground);
141
				break;
142 1
			case self::SCANRESULT_INFECTED:
143
				$item->processInfected($this, $isBackground);
144
				break;
145 1
			case self::SCANRESULT_CLEAN:
146 1
				$item->processClean($this, $isBackground);
147 1
				break;
148 1
		}
149 1
	}
150
}
151