1 : <?php
2 :
3 : /**
4 : * PHPIDS
5 : *
6 : * Requirements: PHP5, SimpleXML
7 : *
8 : * Copyright (c) 2007 PHPIDS group (http://php-ids.org)
9 : *
10 : * This program is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation; version 2 of the license.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * PHP version 5.1.6+
20 : *
21 : * @category Security
22 : * @package PHPIDS
23 : * @author Mario Heiderich <mario.heiderich@gmail.com>
24 : * @author Christian Matthies <ch0012@gmail.com>
25 : * @author Lars Strojny <lars@strojny.net>
26 : * @license http://www.gnu.org/licenses/lgpl.html LGPL
27 : * @link http://php-ids.org/
28 : */
29 :
30 : /**
31 : * PHPIDS report object
32 : *
33 : * The report objects collects a number of events and thereby presents the
34 : * detected results. It provides a convenient API to work with the results.
35 : *
36 : * Note that this class implements Countable, IteratorAggregate and
37 : * a __toString() method
38 : *
39 : * @category Security
40 : * @package PHPIDS
41 : * @author Christian Matthies <ch0012@gmail.com>
42 : * @author Mario Heiderich <mario.heiderich@gmail.com>
43 : * @author Lars Strojny <lars@strojny.net>
44 : * @copyright 2007 The PHPIDS Group
45 : * @license http://www.gnu.org/licenses/lgpl.html LGPL
46 : * @version Release: $Id:Report.php 517 2007-09-15 15:04:13Z mario $
47 : * @link http://php-ids.org/
48 : */
49 : class IDS_Report implements Countable, IteratorAggregate
50 : {
51 :
52 : /**
53 : * Event container
54 : *
55 : * @var array
56 : */
57 : protected $events = array();
58 :
59 : /**
60 : * List of affected tags
61 : *
62 : * This list of tags is collected from the collected event objects on
63 : * demand when IDS_Report->getTags() is called
64 : *
65 : * @var array
66 : */
67 : protected $tags = array();
68 :
69 : /**
70 : * Impact level
71 : *
72 : * The impact level is calculated on demand by adding the results of the
73 : * event objects on IDS_Report->getImpact()
74 : *
75 : * @var integer
76 : */
77 : protected $impact = 0;
78 :
79 : /**
80 : * Centrifuge data
81 : *
82 : * This variable - initiated as an empty array - carries all information
83 : * about the centrifuge data if available
84 : *
85 : * @var array
86 : */
87 : protected $centrifuge = array();
88 :
89 : /**
90 : * Constructor
91 : *
92 : * @param array $events the events the report should include
93 : *
94 : * @return void
95 : */
96 : public function __construct(array $events = null)
97 : {
98 57 : if ($events) {
99 19 : foreach ($events as $event) {
100 19 : $this->addEvent($event);
101 19 : }
102 19 : }
103 57 : }
104 :
105 : /**
106 : * Adds an IDS_Event object to the report
107 : *
108 : * @param object $event IDS_Event
109 : *
110 : * @return object $this
111 : */
112 : public function addEvent(IDS_Event $event)
113 : {
114 51 : $this->clear();
115 51 : $this->events[$event->getName()] = $event;
116 :
117 51 : return $this;
118 : }
119 :
120 : /**
121 : * Get event by name
122 : *
123 : * In most cases an event is identified by the key of the variable that
124 : * contained maliciously appearing content
125 : *
126 : * @param scalar $name the event name
127 : *
128 : * @throws InvalidArgumentException if argument is invalid
129 : * @return mixed IDS_Event object or false if the event does not exist
130 : */
131 : public function getEvent($name)
132 : {
133 5 : if (!is_scalar($name)) {
134 1 : throw new InvalidArgumentException(
135 : 'Invalid argument type given'
136 1 : );
137 : }
138 :
139 4 : if ($this->hasEvent($name)) {
140 3 : return $this->events[$name];
141 : }
142 :
143 1 : return false;
144 : }
145 :
146 : /**
147 : * Returns list of affected tags
148 : *
149 : * @return array
150 : */
151 : public function getTags()
152 : {
153 3 : if (!$this->tags) {
154 3 : $this->tags = array();
155 :
156 3 : foreach ($this->events as $event) {
157 3 : $this->tags = array_merge($this->tags,
158 3 : $event->getTags());
159 3 : }
160 :
161 3 : $this->tags = array_values(array_unique($this->tags));
162 3 : }
163 :
164 3 : return $this->tags;
165 : }
166 :
167 : /**
168 : * Returns total impact
169 : *
170 : * Each stored IDS_Event object and its IDS_Filter sub-object are called
171 : * to calculate the overall impact level of this request
172 : *
173 : * @return integer
174 : */
175 : public function getImpact()
176 : {
177 35 : if (!$this->impact) {
178 35 : $this->impact = 0;
179 35 : foreach ($this->events as $event) {
180 33 : $this->impact += $event->getImpact();
181 33 : }
182 35 : }
183 :
184 35 : return $this->impact;
185 : }
186 :
187 : /**
188 : * Checks if a specific event with given name exists
189 : *
190 : * @param scalar $name the event name
191 : *
192 : * @throws InvalidArgumentException if argument is illegal
193 : *
194 : * @return boolean
195 : */
196 : public function hasEvent($name)
197 : {
198 11 : if (!is_scalar($name)) {
199 1 : throw new InvalidArgumentException('Invalid argument given');
200 : }
201 :
202 10 : return isset($this->events[$name]);
203 : }
204 :
205 : /**
206 : * Returns total amount of events
207 : *
208 : * @return integer
209 : */
210 : public function count()
211 : {
212 1 : return count($this->events);
213 : }
214 :
215 : /**
216 : * Return iterator object
217 : *
218 : * In order to provide the possibility to directly iterate over the
219 : * IDS_Event object the IteratorAggregate is implemented. One can easily
220 : * use foreach() to iterate through all stored IDS_Event objects.
221 : *
222 : * @return Iterator
223 : */
224 : public function getIterator()
225 : {
226 1 : return new ArrayObject($this->events);
227 : }
228 :
229 : /**
230 : * Checks if any events are registered
231 : *
232 : * @return boolean
233 : */
234 : public function isEmpty()
235 : {
236 4 : return empty($this->events);
237 : }
238 :
239 : /**
240 : * Clears calculated/collected values
241 : *
242 : * @return void
243 : */
244 : protected function clear()
245 : {
246 51 : $this->impact = 0;
247 51 : $this->tags = array();
248 51 : }
249 :
250 : /**
251 : * This method returns the centrifuge property or null if not
252 : * filled with data
253 : *
254 : * @return array/null
255 : */
256 : public function getCentrifuge()
257 : {
258 1 : return ($this->centrifuge && count($this->centrifuge) > 0)
259 1 : ? $this->centrifuge : null;
260 : }
261 :
262 : /**
263 : * This method sets the centrifuge property
264 : *
265 : * @param array $centrifuge the centrifuge data
266 : *
267 : * @throws InvalidArgumentException if argument is illegal
268 : *
269 : * @return boolean true is arguments were valid
270 : */
271 : public function setCentrifuge($centrifuge = array())
272 : {
273 17 : if (is_array($centrifuge) && $centrifuge) {
274 17 : $this->centrifuge = $centrifuge;
275 17 : return true;
276 : }
277 0 : throw new InvalidArgumentException('Invalid argument given');
278 : }
279 :
280 : /**
281 : * Directly outputs all available information
282 : *
283 : * @return string
284 : */
285 : public function __toString()
286 : {
287 2 : if (!$this->isEmpty()) {
288 1 : $output = '';
289 1 : $output .= 'Total impact: ' . $this->getImpact() . "<br/>\n";
290 1 : $output .= 'Affected tags: ' . join(', ', $this->getTags()) .
291 1 : "<br/>\n";
292 :
293 1 : foreach ($this->events as $event) {
294 : $output .= "<br/>\nVariable: " .
295 1 : htmlspecialchars($event->getName()) . ' | Value: ' .
296 1 : htmlspecialchars($event->getValue()) . "<br/>\n";
297 1 : $output .= 'Impact: ' . $event->getImpact() . ' | Tags: ' .
298 1 : join(', ', $event->getTags()) . "<br/>\n";
299 :
300 1 : foreach ($event as $filter) {
301 1 : $output .= 'Description: ' . $filter->getDescription() .
302 1 : ' | ';
303 1 : $output .= 'Tags: ' . join(', ', $filter->getTags()) .
304 1 : ' | ';
305 1 : $output .= 'ID: ' . $filter->getId() .
306 1 : "<br/>\n";
307 1 : }
308 1 : }
309 :
310 1 : $output .= '<br/>';
311 :
312 1 : if ($centrifuge = $this->getCentrifuge()) {
313 0 : $output .= 'Centrifuge detection data';
314 : $output .= '<br/> Threshold: ' .
315 0 : ((isset($centrifuge['threshold'])&&$centrifuge['threshold']) ?
316 0 : $centrifuge['threshold'] : '---');
317 : $output .= '<br/> Ratio: ' .
318 0 : ((isset($centrifuge['ratio'])&&$centrifuge['ratio']) ?
319 0 : $centrifuge['ratio'] : '---');
320 0 : if(isset($centrifuge['converted'])) {
321 0 : $output .= '<br/> Converted: ' . $centrifuge['converted'];
322 0 : }
323 0 : $output .= "<br/><br/>\n";
324 0 : }
325 1 : }
326 :
327 2 : return isset($output) ? $output : '';
328 : }
329 : }
330 :
331 : /*
332 : * Local variables:
333 : * tab-width: 4
334 : * c-basic-offset: 4
335 : * End:
336 : */
|