Completed
Push — master ( 096cd1...7d72c0 )
by Nils
02:39
created

FilterExtension::isFilteredByFilter()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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