Completed
Push — master ( 6b2d7c...9b8114 )
by Nils
02:18
created

Scanner::initRules()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
c 0
b 0
f 0
rs 9.6666
cc 3
eloc 5
nc 3
nop 2
1
<?php
2
3
namespace whm\Smoke\Scanner;
4
5
use Ivory\HttpAdapter\HttpAdapterInterface;
6
use phmLabs\Components\Annovent\Dispatcher;
7
use phmLabs\Components\Annovent\Event\Event;
8
use whm\Smoke\Extensions\SmokeResponseRetriever\Retriever\Retriever;
9
use whm\Smoke\Http\ClientAware;
10
use whm\Smoke\Http\Response;
11
use whm\Smoke\Rules\ValidationFailedException;
12
13
class Scanner
14
{
15
    const ERROR = 'error';
16
    const PASSED = 'passed';
17
18
    private $rules;
19
    private $eventDispatcher;
20
21
    private $responseRetriever;
22
23
    private $status = 0;
24
25
    public function __construct(array $rules, HttpAdapterInterface $client, Dispatcher $eventDispatcher, Retriever $responseRetriever)
26
    {
27
        $eventDispatcher->simpleNotify('Scanner.Init', array('rules' => $rules, 'httpClient' => $client, 'dispatcher' => $eventDispatcher));
28
29
        $this->initRules($rules, $client);
30
31
        $this->eventDispatcher = $eventDispatcher;
32
33
        $this->responseRetriever = $responseRetriever;
34
35
        $this->eventDispatcher->simpleNotify('Scanner.Init.ResponseRetriever', array('responseRetriever' => $this->responseRetriever));
36
    }
37
38
    private function initRules($rules, HttpAdapterInterface $client)
39
    {
40
        $this->rules = $rules;
41
        foreach ($this->rules as $rule) {
42
            if ($rule instanceof ClientAware) {
43
                $rule->setClient($client);
44
            }
45
        }
46
    }
47
48
    public function scan()
49
    {
50
        $this->eventDispatcher->simpleNotify('Scanner.Scan.Begin');
51
52
        while (($response = $this->responseRetriever->next()) && !$this->eventDispatcher->notifyUntil(new Event('Scanner.Scan.isStopped'))) {
53
54
            // this is the url filter
55
            if ($this->eventDispatcher->notifyUntil(new Event('Scanner.ProcessHtml.isFiltered', array('uri' => $response->getUri())))) {
56
                continue;
57
            }
58
59
            $resultArray = $this->checkResponse($response);
60
61
            $result = new Result($response->getUri(),
62
                $resultArray['type'],
63
                $response,
64
                '',
65
                $resultArray['time']);
66
67
            if ($result->isFailure()) {
68
                $result->setMessages($resultArray['messages']);
69
                $this->status = 1;
70
            }
71
72
            $this->eventDispatcher->simpleNotify('Scanner.Scan.Validate', array('result' => $result));
73
        }
74
75
        $this->eventDispatcher->simpleNotify('Scanner.Scan.Finish');
76
    }
77
78
    public function getStatus()
79
    {
80
        return $this->status;
81
    }
82
83
    private function checkResponse(Response $response)
84
    {
85
        $messages = [];
86
87
        $startTime = microtime(true);
88
        foreach ($this->rules as $name => $rule) {
89
            if ($this->eventDispatcher->notifyUntil(new Event('Scanner.CheckResponse.isFiltered', array('ruleName' => $name, 'rule' => $rule, 'response' => $response)))) {
90
                continue;
91
            }
92
            try {
93
                $rule->validate($response);
94
            } catch (ValidationFailedException $e) {
95
                $messages[$name] = $e->getMessage();
96
            }
97
        }
98
        $endTime = microtime(true);
99
100
        // calculate time in seconds
101
        $time = round(($endTime - $startTime) * 1000, 5);
102
103
        if (count($messages) > 0) {
104
            $resultArray = ['messages' => $messages, 'time' => $time, 'type' => self::ERROR];
105
        } else {
106
            $resultArray = ['messages' => [], 'time' => $time, 'type' => self::PASSED];
107
        }
108
109
        return $resultArray;
110
    }
111
}
112