Completed
Branch master (1f9106)
by Nils
02:44
created

FilterExtension::isFiltered()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 12
Bugs 1 Features 2
Metric Value
c 12
b 1
f 2
dl 0
loc 18
rs 9.4285
cc 3
eloc 11
nc 4
nop 3
1
<?php
2
3
namespace whm\Smoke\Extensions\SmokeFilter;
4
5
use phmLabs\Components\Annovent\Event\Event;
6
use whm\Smoke\Extensions\SmokeResponseRetriever\Retriever\Retriever;
7
use whm\Smoke\Http\Response;
8
use whm\Smoke\Yaml\EnvAwareYaml;
9
10
/**
11
 * Class FilterExtension.
12
 *
13
 * @example for filter file
14
 *
15
 * filters:
16
 *   _HttpHeaderSuccessStatus:
17
 *     - http://www.wunderweib.de/tag/
18
 *     - http://www.amilio.de/old-but-mandatory-file/
19
 *     - http://www.amilio.de/images/(.*)
20
 *
21
 * exclusive:
22
 *   _HttpHeaderSuccessStatus:
23
 *     - http://www.wunderweib.de/tag/
24
 *     - http://www.amilio.de/old-but-mandatory-file/
25
 */
26
class FilterExtension
27
{
28
    /**
29
     * @var Retriever
30
     */
31
    private $retriever;
32
33
    private $filters = array();
34
    private $exclusives = array();
35
36
    private $currentModus = self::MODUS_FILTER;
37
38
    const MODUS_FILTER = 'filter';
39
    const MODUS_EXCLUSIVE = 'exclusive';
40
41
    public function init($filters = array(), $filterFile = '', $exclusive = array())
42
    {
43
        if (count($exclusive) > 0 && (count($filters) > 0 || $filterFile !== '')) {
44
            throw new \RuntimeException("It's not possible to define filter lists and an exclusive list at the same time [Extension: " . get_class($this) . '].');
45
        }
46
47
        if ($filterFile !== '') {
48
            if (!file_exists($filterFile)) {
49
                throw new \RuntimeException('Filter file not found: ' . $filterFile);
50
            }
51
52
            $filterElements = EnvAwareYaml::parse(file_get_contents($filterFile));
53
54
            foreach ($filterElements['filters'] as $rule => $uris) {
55
                foreach ($uris as $uri) {
56
                    $this->filters[] = array('rule' => $rule, 'uri' => $uri);
57
                }
58
            }
59
        } elseif (!is_null($filters)) {
60
            foreach ($filters as $rule => $filteredUrls) {
61
                if (!is_null($filteredUrls)) {
62
                    foreach ($filteredUrls as $uri) {
63
                        $this->filters[] = array('rule' => $rule, 'uri' => $uri);
64
                    }
65
                }
66
            }
67
        }
68
69
        if (count($exclusive) > 0) {
70
            $this->exclusives = $exclusive;
71
            $this->currentModus = self::MODUS_EXCLUSIVE;
72
        }
73
    }
74
75
    /**
76
     * @Event("Scanner.Init.ResponseRetriever")
77
     */
78
    public function getResponseRetriever(Retriever $responseRetriever)
79
    {
80
        $this->retriever = $responseRetriever;
81
    }
82
83
    /**
84
     * @Event("Scanner.CheckResponse.isFiltered")
85
     */
86
    public function isFiltered(Event $event, $ruleName, Response $response)
87
    {
88
        $uri = (string) $this->retriever->getOriginUri($response->getUri());
89
90
        if ($this->currentModus === self::MODUS_FILTER) {
91
            $isFiltered = $this->isFilteredByFilter($ruleName, $uri);
92
        } else {
93
            $isFiltered = $this->isFilteredByExclusives($ruleName, $uri);
94
        }
95
96
        if ($isFiltered) {
97
            $event->setProcessed();
98
99
            return true;
100
        } else {
101
            return false;
102
        }
103
    }
104
105
    private function isFilteredByFilter($ruleName, $uri)
106
    {
107
        foreach ($this->filters as $filter) {
108
            if ($ruleName === $filter['rule'] && 0 < preg_match('$' . $filter['uri'] . '$', $uri)) {
109
                return true;
110
            }
111
        }
112
113
        return false;
114
    }
115
116
    private function isFilteredByExclusives($ruleName, $uri)
117
    {
118
        if (array_key_exists($ruleName, $this->exclusives)) {
119
            if (is_array($this->exclusives[$ruleName])) {
120
                if (in_array($uri, $this->exclusives[$ruleName], true)) {
121
                    return false;
122
                }
123
            }
124
        }
125
126
        return true;
127
    }
128
}
129