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