root/trunk/wifidog-auth/wifidog/classes/EventLogging.php @ 1013

Revision 1013, 47.5 KB (checked in by benoitg, 7 years ago)

* dump_initial_data_postgres.sh: Add the
content_available_display_pages table to the dump, can someone
re-generate the initial data from a working install
* Remove the ?> tags from all the classes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1<?php
2
3/* vim: set expandtab tabstop=2 shiftwidth=2 softtabstop=2: */
4
5// +-------------------------------------------------------------------+
6// | WiFiDog Authentication Server                                     |
7// | =============================                                     |
8// |                                                                   |
9// | The WiFiDog Authentication Server is part of the WiFiDog captive  |
10// | portal suite.                                                     |
11// +-------------------------------------------------------------------+
12// | PHP version 5 required.                                           |
13// +-------------------------------------------------------------------+
14// | Homepage:     http://www.wifidog.org/                             |
15// | Source Forge: http://sourceforge.net/projects/wifidog/            |
16// +-------------------------------------------------------------------+
17// | This program is free software; you can redistribute it and/or     |
18// | modify it under the terms of the GNU General Public License as    |
19// | published by the Free Software Foundation; either version 2 of    |
20// | the License, or (at your option) any later version.               |
21// |                                                                   |
22// | This program is distributed in the hope that it will be useful,   |
23// | but WITHOUT ANY WARRANTY; without even the implied warranty of    |
24// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     |
25// | GNU General Public License for more details.                      |
26// |                                                                   |
27// | You should have received a copy of the GNU General Public License |
28// | along with this program; if not, contact:                         |
29// |                                                                   |
30// | Free Software Foundation           Voice:  +1-617-542-5942        |
31// | 59 Temple Place - Suite 330        Fax:    +1-617-542-2652        |
32// | Boston, MA  02111-1307,  USA       gnu@gnu.org                    |
33// |                                                                   |
34// +-------------------------------------------------------------------+
35
36/**
37 * EventLogging: a message logging class.
38 *
39 * Logging messages of various levels, from debug to critical, from
40 * php or generated by the program, can be formatted and directed to
41 * a file, be displayed on the html page, as comments or as a table,
42 * or be held and collected for display later in a special <div>
43 * block.
44 *
45 * Logging messages once accepted at intake will be processed by all
46 * active output channels.  ie, the message will be written by all
47 * the output channels, not just one.
48 *
49 * Output channels currently supported:
50 *
51 * FileChannel - appends messages to a file
52 * NullChannel - discards all messages
53 * PrintChannel - writes messages via "echo" or "print"
54 * ArrayChannel - accumulates messages in an array.  It's like
55 *   PrintChannel, except that the hold flag is always on, and that
56 *   the only way to get messages out is to call the flush method.
57 *   PrintChannel will print any held messages at destruct time, but
58 *   ArrayChannel's destruct will discard any held messages.
59 *
60 * Output formats currently supported:
61 * SyslogFormatter - like syslog, with a datestamp prefixed
62 * HTMLTableFormatter - as table row elements
63 * HTMLCommentsFormatter - as html comments
64 *
65 * Collection of logging messages can be turned off temporarily,
66 * either by using the standard php '@' prefix, or by using the
67 * off() and on() methods, and their static equivalents,
68 * EventLogging::stOn() and EventLogging::stOff().
69 *
70 * Debugging of specific methods, functions, or files is supported
71 * by allowing messages from such contexts to be redirected to a
72 * unique channel, or the message can be catapulted to a different
73 * importance level, like critical, to make sure it gets written by
74 * one of the output channels.
75 *
76 * By using the addContextFilter method you can specify special
77 * treatment for messages based on the method, function or file the
78 * message came from.  debug_backtrace() is used to see if the context
79 * is on the stack.  If it is, then the special treatment is applied.
80 *
81 * @todo Extensible to a more general transactional processing system,
82 * useful in a context where the work to be done should have BEGIN
83 * WORK and COMMIT/ROLLBACK logic, but either the database in use
84 * does not support it, or the work being done is multiply facited,
85 * involving non-database elements that should be rolled back too.
86 *
87 *
88 * usage: at the start in mainline, to setup the logging environment
89 *
90 * $log = EventLogging::stGlobal($_ENV['DEBUG']);
91 *
92 *  Examples of strings to pass stGlobal:
93 *   "Class::Method(critical)" - matches messages from Class::Method, makes them critical
94 *   "Class::Method(off)" - matches messages from Class::Method, dumps them
95 *   "strict~/var:\sDeprecated/(off)" - matches message text with "strict" level, dumps them
96 *   "Function(critical) /this/path/file.php(debug)" - matches messages from Function, makes them critical,
97 *       and matches any messages by any code in /this/path/file.php, makes them debug level
98 * Separate multiple entries with spaces, not commas.
99 *
100 * Add output channels, globally.  All messages will pass to these channels, unless
101 * a function/method/file override comes into play.
102 *
103 * $log->addChannel(new FileChannel("logg.txt", new SyslogFormatter(), 'error,notice'));
104 * $log->addChannel(new PrintChannel(new HTMLCommentsFormatter(), '=debug'));
105 * $log->addChannel(new ArrayChannel(new HTMLFormatter(), 'warning,notice'));
106 *
107 * Or, start up logging all at once:
108 * EventLogging::SetupErrorHandling('notice~/Constant.+already\sdefined/(off)',
109 *      new PrintChannel(new HTMLCommentsFormatter(), '=debug'),
110 *     new PrintChannel(new HTMLFormatter(), 'warning,notice'));
111 *
112 *
113 * automatic intake/capture of system messages and exceptions
114 * elLogMessage("message", level)
115 * elLogError("message")
116 * elLogWarning("message")
117 * elLogNotice("message")
118 * elLogInfo("message")
119 * elLogDebug("message")
120 *
121 * or $log->message("message", EventObject::EVO_USER_WARNING)
122 * or EventLogging::stMessage("message", EventObject::EVO_USER_WARNING)
123 *
124 * or $log->error("message")
125 * or $log->warning("message")
126 * or $log->notice("message")
127 * or $log->info("message")
128 * or $log->debug("message")
129 *
130 * broadcastEvent(new Event( ... ))
131 * elLogEvent()
132 *
133 * access to the logging stuff is easy, global
134 * $log = EventLogging::getGlobal();
135 *
136 * Howto silence logging:
137 *   $log->off();
138 *   or EventLogging::stOff();
139 *   or put "@" in front of the expression (standard php trick)
140 *
141 *   then "blah blah blah stuff that emits annoying errors and won't shut up"
142 *
143 *   $log->on();
144 *   or EventLogging::stOn();
145 *
146 * Howto zero in on buggy routines, or in development
147 *
148 * Context filters are supposed to be applied at the global level,
149 * during the initialization phase.  They allow file, class or
150 * function overrides on logging behaviour.  Using context filters
151 * you can put all your special logging stuff in one place, rather
152 * than tracking down the subroutine you want to tweak and editing
153 * it.
154 *
155 * Note that the effectiveLevel controls how the log message passes
156 * through the channels, in that the channels typically screen out
157 * messages based on their level.
158 *
159 * The formatting of the message for display is taken to be a
160 * separate thing, so that you can override the effectiveLevel to
161 * critical so that the message will be printed by most channels,
162 * while not changing the printed message, so that it still says
163 * "debug" or whatever.
164 *
165 * EventLogging::stAddContextFilter(
166 *     array('class' => 'ClassName',
167 *           'function' => 'MethodName',
168 *           'effectiveLevel'=>'critical'));
169 *
170 * EventLogging::stAddContextFilter(
171 *     array('function' => 'FunctionName',
172 *           'redirect'=>new PrintChannel(new HTMLCommentsFormatter(), 'debug')));
173 *
174 * EventLogging::stAddContextFilter(
175 *     array('file' => 'FileName',
176 *           'redirect'=>new NullChannel('debug', 'blockPercolation')));
177 *
178 * This will do the same sort of thing as a context filter, but you
179 * have to put it in the method or function:
180 *
181 * $log = new EventLogging(); // knows it's a context change, context removed when $log __destruct is called
182 * $log->setEffectiveLevel('critical');
183 *
184 * Printing out log messages where you want them, in the style you want
185 * EventLogging::stFlushChannels()
186 * returns the number of messages flushed out.
187 *
188 * Finally,
189 * elBomb("message")
190 * since die("message") when caught by a handler gives no stack backtrace, use elBomb(..) instead of die(..).
191 * elBomb will give a stack trace.
192 *
193 * A complete example:
194 *
195 * require_once 'classes/EventLogging.php';
196 *
197 * class myHTMLTableFormatter extends EventFormatter {
198 *   public function formatMessage($pCSSClass, $pMessageType, $pMessage, $pFilename, $pLinenum) {
199 *     $pCSSClass = empty($pCSSClass) ? '' : "class='log_$pCSSClass'";
200 *     $string = "<tr>" .
201 *            "<td $pCSSClass>$pMessageType</td><td $pCSSClass>$pMessage</td>" .
202 *            (!empty($pFilename) ? "<td $pCSSClass>$pFilename</td>" .
203 *             (!empty($pLinenum) ? "<td $pCSSClass>$pLinenum</td>" : "") : "") .
204 *             "</tr>\n";
205 *
206 *     return $string;
207 *   }
208 * }
209 *
210 * EventLogging::SetupErrorHandling('notice~/Constant.+already\sdefined/(off)',
211 *      array( 'status' => new ArrayChannel(new myHTMLTableFormatter(), 'all,!debug', null, true),
212 *             'debug' => new PrintChannel(new HTMLCommentsFormatter(), '=debug', null, false)));
213 * ....
214 * ... @fopen(...) ...
215 * elLogError("failed to open file");
216 * ....
217 *
218 *  print "<div id='status'>\n";
219 * print "<table>\n";
220 * print "<tr><th>Type</th><th>Message</th><th>File</th><th>Line</th></tr>\n";
221 * if (!EventLogging::stFlushChannels('status'))
222 *   print "<tr><td colspan='4'>No Messages</td></tr>\n";
223 * print "</table>\n";
224 * print "</div>\n";
225 *
226 *
227 * @package    WiFiDogAuthServer
228 * @author     Rob Janes <janes.rob@gmail.com>
229 * @copyright  2005-2006 Rob Janes
230 * @version    Subversion $Id$
231 * @link       http://www.wifidog.org/
232 */
233
234/**
235 * @package    WiFiDogAuthServer
236 * @subpackage Eventlogging
237 * @author     Rob Janes <janes.rob@gmail.com>
238 * @copyright  2005-2006 Rob Janes
239 */
240class EventLogging {
241  private static $globalTracker;
242
243  private $observers; // with layout supervisors (formatters), these are a tee to write to files/sinks
244
245  private $contextFilters;
246
247  private $stackPtrMoreGlobal;
248  private $stackPtrMoreSpecific;
249
250  private $stackPtrMostSpecific;
251
252  private $defaultObserver;
253
254  private $on;
255  private $debug;
256  private $effectiveLevel;
257
258  private function __construct() {
259    $this->observers = array();
260    $this->contextFilters = array();
261
262    $this->stackPtrMostSpecific = null;
263
264    $this->stackPtrMoreSpecific = null;
265
266    $this->stackPtrMoreGlobal = empty(self::$globalTracker) ? null : $this->enchain();
267  }
268
269  function __destruct() {
270    $this->unchain();
271  }
272
273  private function enchain() {
274    $end = self::$globalTracker->stackPtrMostSpecific;
275    $this->stackPtrMoreGlobal = $end;
276    $this->stackPtrMoreSpecific = null;
277
278    $end->stackPtrMoreSpecific = $this;
279    self::$globalTracker->stackPtrMostSpecific = $this;
280  }
281
282  private function unchain() {
283    $before = $this->stackPtrMoreGlobal;
284    $after = $this->stackPtrMoreSpecific;
285
286    if (!empty($before)) $before->stackPtrMoreSpecific = $after;
287    if (!empty($after)) $after->stackPtrMoreGlobal = $before;
288
289    $this->stackPtrMoreGlobal = $this->stackPtrMoreSpecific = null;
290    if (empty($after) && !empty(self::$globalTracker)) self::$globalTracker->stackPtrMostSpecific = $before;
291  }
292
293  public static function SetupErrorHandling($pString=null) {
294    if (empty(self::$globalTracker)) {
295      $obj = new self();
296      self::$globalTracker = $obj;
297      $obj->stackPtrMostspecific = $obj;
298
299      //$obj->on = true;
300
301      if (!empty($pString)) $obj->quickContextFilters($pString);
302
303      //$what = array();
304      if (($n = func_num_args()) > 1) {
305                                // process channels
306                                for ($i=1; $i<$n; $i++) {
307                                        $channel = func_get_arg($i);
308                                        if (!is_array($channel)) {
309                                                $obj->addChannel($channel);
310                                                //$what[] = $i;
311                                        }
312                                        else {
313                                                foreach ($channel as $name=>$channel2) {
314                                                        $obj->addChannel($channel2, $name);
315                                                        //$what[] = $name;
316                                                }
317                                        }
318                                }
319      }
320
321      self::CaptureAll();
322
323      //print "<!-- $n ".implode(", ", $what)."\n";
324      //print_r($obj);
325      //print "\n-->\n";
326    }
327
328    return self::$globalTracker;
329  }
330
331  public static function stGlobal($pString=null) {
332    return self::SetupErrorHandling($pString);
333  }
334
335  //***********************************************************************************
336
337  public function broadcastEvent($pEvent, $pOn=null, $pDebug=null, $pEffectiveImportance=null) {
338    if (isset($this->on)) $pOn = $this->on;
339    if (isset($this->debug)) $pDebug = $this->debug;
340    if (isset($this->effectiveLevel)) $pEffectiveImportance = $this->effectiveLevel;
341
342    $myBlockPercolation = false;
343
344    $myCountSinks = 0;
345
346    $myWatchpoint = null;
347    $myForceOnEvent = null;
348    if (!empty($this->contextFilters) && count($this->contextFilters)>0) {
349      // logging is supposed to be quick.  this is slow, but is most useful for debugging.
350      $myCountSinks++;
351
352      $myWatchpoint = $this->filterContext($pEvent); // returns true or false or a channel object
353
354      $myForceOnEvent = $pEvent->getOnFlag();
355      if (isset($myForceOnEvent)) $pOn = $myForceOnEvent;
356
357      if (is_object($myWatchpoint))
358                                if ($myWatchpoint->receiveEvent($pEvent)) {
359                                        // since this is a specific match at this level
360                                        // allow this section here the ability to override the more general stuff
361                                        // ie, if this specific match results in a "don't let any other channels run" flag, do it immediately
362                                        $myBlockPercolation = true;
363                                        return $myBlockPercolation;
364                                }
365    }
366
367    if (!empty($this->stackPtrMoreSpecific)) {
368      $myCountSinks++;
369      $myBlockPercolation = $this->stackPtrMoreSpecific->broadcastEvent($pEvent, $pOn, $pDebug, $pEffectiveImportance);
370    }
371
372    if ((error_reporting()==0 && empty($pDebug)) || $myBlockPercolation)
373      return $myBlockPercolation;
374
375    if (!isset($pOn) || $pOn) {
376      $myWatchers =& $this->observers;
377
378      if (count($myWatchers)==0 && $this===self::$globalTracker && $myCountSinks==0) {
379                                // the out-of-the box behaviour of EventLogging should be the same as PHP
380                                if (empty($this->defaultObserver))
381                                        $this->defaultObserver = new PrintChannel(new HTMLFormatter(), 'error,notice');
382
383                                if (!empty($this->defaultObserver))
384                                        $myWatchers = array($this->defaultObserver);
385      }
386
387      foreach ($myWatchers as $watcher) {
388                                $myCountSinks++;
389                                if ($watcher->receiveEvent($pEvent, $pEffectiveImportance))
390                                        $myBlockPercolation = true;;
391      }
392    }
393
394    return $myBlockPercolation;
395  }
396
397  public static function stBroadcastEvent($event) {
398    if (empty(self::$globalTracker)) return null;
399    $beginning = self::$globalTracker;
400    $beginning->broadcastEvent($event, $beginning->getOn(), $beginning->getDebugFlag());
401  }
402
403  public function flushChannels($pName=null) {
404    $myMessagesFlushedCounter = 0;
405    if (!empty($this->stackPtrMoreSpecific))
406      $myMessagesFlushedCounter += $this->stackPtrMoreSpecific->flushChannels($pName);
407
408    if (!empty($this->defaultObserver) && (empty($pName) || $pName==='DEFAULT'))
409      $myMessagesFlushedCounter += $this->defaultObserver->flushEventQueue();
410
411    if (!empty($pName)) {
412      $watcher = $this->getChannel($pName);
413      if (!empty($watcher)) $watcher->flushEventQueue();
414    }
415    elseif (!empty($this->observers)) {
416                        foreach ($this->observers as $watcher)
417                                $myMessagesFlushedCounter += $watcher->flushEventQueue();
418    }
419
420    return $myMessagesFlushedCounter;
421  }
422
423  public static function stFlushChannels($pName=null) {
424    if (empty(self::$globalTracker)) return null;
425    $beginning = self::$globalTracker;
426    return $beginning->flushChannels($pName);
427  }
428
429  public static function stOn() {
430    $obj = self::$globalTracker;
431    if (empty($obj)) return null;
432
433    $sav = isset($obj->on) ? $obj->on : null;
434    $obj->on = true;
435    return $sav;
436  }
437
438  public static function stOff() {
439    if (empty(self::$globalTracker)) return null;
440
441    $obj = self::$globalTracker;
442
443    $sav = isset($obj->on) ? $obj->on : null;
444    $obj->on = false;
445    return $sav;
446  }
447
448  public static function stRestore($flag) {
449    if (empty(self::$globalTracker)) return null;
450
451    self::$globalTracker->on = $flag;
452  }
453
454  public function on() {
455    $sav = isset($this->on) ? $this->on : null;
456    $this->on = true;
457    return $sav;
458  }
459  public function off() {
460    $sav = isset($this->on) ? $this->on : null;
461    $this->on = false;
462    return $sav;
463  }
464  public function restore($flag) {
465    $this->on = $flag;
466  }
467  public function getOn() {
468    return isset($this->on) ? $this->on : null;
469  }
470  public function isOn() {
471    if (error_reporting()==0 && empty($this->debug)) return false;
472    return isset($this->on) ? $this->on : (isset(self::$globalTracker->on) ? self::$globalTracker->on : false);
473  }
474  public function isOff() {
475    return $this->isOn() ? false : true;
476  }
477
478  public function getDebugFlag() {
479    return isset($this->debug) ? $this->debug : null;
480  }
481  public function setDebugFlag($flag) {
482    $sav = $this->debug;
483    $this->debug = $flag ? true : false;
484    return $sav;
485  }
486  public function setEffectiveLevel($level) {
487    $sav = $this->effectiveLevel;
488    $this->effectiveLevel = $level;
489    return $sav;
490  }
491  public function getEffectiveLevel() {
492    return $this->effectiveLevel;
493  }
494
495  public static function stMessage($pMessage, $pErrorType=EventObject::EVO_USER_NOTICE) {
496    global $elDefaultLogging;
497
498    if (empty(self::$globalTracker)) {
499      if (empty($elDefaultLogging))
500                                $elDefaultLogging = new PrintChannel(new HTMLFormatter(), 'warning,notice');
501
502      $elDefaultLogging->receiveEvent(new EventObject($pMessage, $pErrorType));
503    }
504    else
505      self::stBroadcastEvent(new EventObject($pMessage, $pErrorType));
506  }
507
508  public function message($pMessage, $pErrorType=EventObject::EVO_USER_NOTICE) {
509    $this->broadcastEvent(new EventObject($pMessage, $pErrorType));
510  }
511  public function error($pMessage) {
512    $this->broadcastEvent(new EventObject($pMessage, EventObject::EVO_USER_ERROR));
513  }
514  public function warning($pMessage) {
515    $this->broadcastEvent(new EventObject($pMessage, EventObject::EVO_USER_WARNING));
516  }
517  public function notice($pMessage) {
518    $this->broadcastEvent(new EventObject($pMessage, EventObject::EVO_USER_NOTICE));
519  }
520  public function info($pMessage) {
521    $this->broadcastEvent(new EventObject($pMessage, EventObject::EVO_INFO));
522  }
523  public function debug($pMessage) {
524    $this->broadcastEvent(new EventObject($pMessage, EventObject::EVO_DEBUG));
525  }
526
527  //***********************************************************************************
528
529  public static function ErrorHandler($pSystemErrorType, $pMessage, $pFilename, $pLinenum, $pVars) {
530    $myErrorReportingOn = error_reporting(); // is 0 if '@' prepends statement
531
532    if ($myErrorReportingOn || (isset(self::$globalTracker) && self::$globalTracker->debug)) {
533      $eo = new EventObject($pMessage, EventObject::ErrorType($pSystemErrorType));
534      $eo->setFilename($pFilename);
535      $eo->setLinenum($pLinenum);
536
537      self::stBroadcastEvent($eo);
538    }
539
540    // if ($pSystemErrorType == E_ERROR) die($pMessage); // i don't think php passes E_ERROR to a user error handler
541    // if ($pSystemErrorType == E_USER_ERROR) die($pMessage); // die if E_USER_ERROR
542  }
543
544  public static function ExceptionHandler($pException) {
545    $eo = new EventObject($pException->getMessage());
546    $eo->setFilename($pException->getFile());
547    $eo->setLinenum($pException->getLine());
548    $eo->setContext($t = $pException->getTrace());
549
550    self::stBroadcastEvent($eo);
551  }
552
553  public static function DieHandler() {
554    // is this normal program exit, or was there an error?
555    $eo = new EventObject("die()", EventObject::EVO_ERROR);
556
557    self::stBroadcastEvent($eo);
558  }
559
560  //***********************************************************************************
561
562  public static function CaptureErrors() {
563    error_reporting(E_ALL);
564    return set_error_handler(array('EventLogging', 'ErrorHandler'));
565  }
566
567  public static function CaptureExceptions() {
568    return set_exception_handler(array('EventLogging', 'ExceptionHandler'));
569  }
570
571  public static function CaptureDie() {
572    register_shutdown_function(array('EventLogging', 'DieHandler'));
573  }
574
575  public static function CaptureAll() {
576    self::CaptureExceptions();
577    self::CaptureErrors();
578    //self::CaptureDie();
579
580    return true;
581  }
582
583  public function bomb($pMessage=null) {
584    if (empty($pMessage))
585      $pMessage = "Bomb()";
586
587    $eo = new EventObject($pMessage, EventObject::EVO_ERROR);
588    $this->broadcastEvent($eo);
589
590    die($pMessage);
591  }
592
593  public static function stBomb($pMessage=null) {
594    if (func_num_args() > 0) {
595      // log $message
596    }
597
598    if (empty($pMessage))
599      $pMessage = "Bomb()";
600
601    $eo = new EventObject($pMessage, EventObject::EVO_ERROR);
602    self::stBroadcastEvent($eo);
603
604    die($pMessage);
605  }
606
607  public function addChannel($pObserver, $pName=null) {
608    if (empty($pName)) $pName = count($this->observers);
609
610    if ("$pName" == 'DEFAULT')
611      $this->defaultObserver = $pObserver;
612    else
613      $this->observers[$pName] = $pObserver;
614
615    return $pName;
616  }
617  public static function stAddChannel($pObserver) {
618    self::$globalTracker->addChannel($pObserver);
619  }
620
621  public function getChannel($pName) {
622    return $pName == 'DEFAULT' ? $this->defaultObserver : (empty($this->observers[$pName]) ? false : $this->observers[$pName]);
623  }
624
625  public function remChannel($pChannel) {
626    if (!is_object($pChannel))
627      $pName = $pChannel;
628    else {
629      foreach ($this->observers as $name => $observer) {
630                                if ($observer===$pChannel) {
631                                        $pName = $name;
632                                        break;
633                                }
634      }
635    }
636
637    if (!empty($pName))
638      if ($pName == 'DEFAULT')
639                                unset($this->defaultObserver);
640      else
641                                unset($this->observers[$pName]);
642  }
643
644  public static function stAddContextFilter($options) {
645    $context = array();
646
647    if (!empty($options['file'])) {
648      $context['file'] = $options['file'];
649    }
650    elseif (!empty($options['class'])) {
651      $context['class'] = $options['class'];
652      $context['function'] = $options['function'];
653    }
654    elseif (!empty($options['function'])) {
655      $context['class'] = '';
656      $context['function'] = $options['function'];
657    }
658    elseif (!empty($options['matchlevel'])) {
659      $context['matchlevel'] = $options['matchlevel'];
660      $context['matchpattern'] = $options['matchpattern'];
661    }
662
663    if (!empty($options['redirect'])) $context['redirect'] = $options['redirect'];
664    if (!empty($options['effectiveLevel'])) $context['effectiveLevel'] = $options['effectiveLevel'];
665
666    self::$globalTracker->contextFilters[] = $context;
667  }
668
669  public function filterContext(&$event) {
670    $needle =& $event;
671    $found = null;
672    foreach ($this->contextFilters as $haystack) {
673      $filename = $needle->getFilename();
674      $context = $needle->getContext();
675      if (!empty($haystack['matchlevel'])) {
676                                if ($haystack['matchlevel'] == $needle->getLayoutType()) {
677                                        if (preg_match($haystack['matchpattern'], $needle->getMessage())) {
678                                                $found = $haystack;
679                                        }
680                                }
681
682                                // print "\n<!-- filterContext haystack $haystack[matchlevel], $haystack[matchpattern], $haystack[effectiveLevel] ". "'".$needle->getMessage()."' ".(empty($found) ? "NOT FOUND" : "FOUND"). " -->\n";
683      }
684      elseif (!empty($haystack['file'])) {
685                                if ($filename == $haystack['file']) {
686                                        $found = $haystack;
687                                }
688                                else {
689                                        foreach ($context as $backtrace) {
690                                                if ($backtrace['file'] == $haystack['file']) {
691                                                        $found = $haystack;
692                                                        break;
693                                                }
694                                        }
695                                }
696      }
697      elseif (!empty($haystack['class'])) {
698                                foreach ($context as $backtrace) {
699                                        if (!empty($backtrace['class']) && $backtrace['class'] == $haystack['class'] &&
700                                                        (empty($haystack['function']) || $backtrace['function'] == $haystack['function'])) {
701                                                $found = $haystack;
702                                                break;
703                                        }
704                                }
705      }
706      elseif (!empty($haystack['function'])) {
707                                foreach ($context as $backtrace) {
708                                        if (!empty($backtrace['function']) && $backtrace['function'] == $haystack['function']) {
709                                                $found = $haystack;
710                                                break;
711                                        }
712                                }
713      }
714
715      if (!empty($found))
716                                break;
717    }
718
719    if (!empty($found)) {
720      if (!empty($found['effectiveLevel'])) {
721                                if ($found['effectiveLevel'] == 'on')
722                                        $needle->setOnFlag(true);
723                                elseif ($found['effectiveLevel'] == 'off')
724                                        $needle->setOnFlag(false);
725                                else
726                                        $needle->setImportance($found['effectiveLevel']);
727      }
728
729      if (!empty($found['redirect']))
730                                return $found['redirect'];
731
732      return true;
733    }
734
735    return false;
736  }
737
738  //"Class::Method(critical)"
739  //"Class::Method(off)"
740  //"strict~/var:\sDeprecated/(off)"
741  //"Function(critical) /this/path/file.php(debug)"
742  public function quickContextFilters($pString) {
743    if (empty($pString)) return 0;
744
745    $myCounter = 0;
746    $myList = preg_split('/\s+/', $pString, -1, PREG_SPLIT_NO_EMPTY);
747    foreach ($myList as $myItem) {
748      if (preg_match('/^([^()]+)\(([^()]+)\)$/', $myItem, $myMatches)) {
749                                $myContext = $myMatches[1];
750                                $myOverride = $myMatches[2];
751                                $filter = array();
752                                if (strpos($myContext, '::') !== false) {
753                                        // class
754                                        $tmp = explode('::', $myContext, 2);
755                                        $filter['class'] = trim($tmp[0]);
756                                        if (preg_match('/\S/', $tmp[1])) $filter['function'] = trim($tmp[1]);
757                                        $filter['effectiveLevel'] = trim($myOverride);
758                                }
759                                elseif (strpos($myContext, '~') !== false) {
760                                        // message match
761                                        $tmp = explode('~', $myContext, 2);
762                                        $filter['matchlevel'] = trim($tmp[0]);
763                                        $filter['matchpattern'] = trim($tmp[1]);
764                                        $filter['effectiveLevel'] = trim($myOverride);
765                                }
766                                elseif (strpos($myContext, '/') !== false) {
767                                        // file
768                                        $filter['file'] = trim($myContext);
769                                        $filter['effectiveLevel'] = trim($myOverride);
770                                }
771                                else {
772                                        // function
773                                        $filter['function'] = trim($myContext);
774                                        $filter['effectiveLevel'] = trim($myOverride);
775                                }
776
777                                if (EventObject::stClassifyErrorType($myOverride)) {
778                                        EventLogging::stAddContextFilter($filter);
779                                        $myCounter++;
780                                }
781      }
782    }
783
784    return $myCounter;
785  }
786}
787
788define('_EL_DEBUG', 'debug');
789define('_EL_INFO', 'info');
790define('_EL_CRITICAL', 'critical');
791
792define('_EL_ERROR', 'error');   // can't be captured
793define('_EL_WARNING', 'warning');
794define('_EL_PARSE', 'parse');   // can't be captured
795define('_EL_NOTICE', 'notice');
796define('_EL_CORE_ERROR', 'core error'); // can't be captured
797define('_EL_CORE_WARNING', 'core warning'); // can't be captured
798define('_EL_COMPILE_ERROR', 'compile error'); // can't be captured
799define('_EL_COMPILE_WARNING', 'compile warning'); // can't be captured
800define('_EL_USER_ERROR', 'user error');
801define('_EL_USER_WARNING', 'user warning');
802define('_EL_USER_NOTICE', 'user notice');
803define('_EL_STRICT', 'strict');
804
805/**
806 * @package    WiFiDogAuthServer
807 * @subpackage Eventlogging
808 * @author     Rob Janes <janes.rob@gmail.com>
809 * @copyright  2005-2006 Rob Janes
810 */
811class EventObject {
812  private $message;
813  private $layoutType;
814  private $filterImportance;
815  private $type;
816  private $context;
817
818  private $timestamp;
819
820  private $exception;
821  private $filename;
822  private $linenum;
823  private $code;
824
825  private $taskLabel;
826  private $actions;
827  private $undoActions;
828  private $onFlag;
829
830  const EVO_DEBUG = _EL_DEBUG;
831  const EVO_INFO = _EL_INFO;
832  const EVO_CRITICAL = _EL_CRITICAL;
833
834  const EVO_ERROR = _EL_ERROR;  // can't be captured
835  const EVO_WARNING = _EL_WARNING;
836  const EVO_PARSE = _EL_PARSE;  // can't be captured
837  const EVO_NOTICE = _EL_NOTICE;
838  const EVO_CORE_ERROR = _EL_CORE_ERROR; // can't be captured
839  const EVO_CORE_WARNING = _EL_CORE_WARNING; // can't be captured
840  const EVO_COMPILE_ERROR = _EL_COMPILE_ERROR; // can't be captured
841  const EVO_COMPILE_WARNING = _EL_COMPILE_WARNING; // can't be captured
842  const EVO_USER_ERROR = _EL_USER_ERROR;
843  const EVO_USER_WARNING = _EL_USER_WARNING;
844  const EVO_USER_NOTICE = _EL_USER_NOTICE;
845  const EVO_STRICT = _EL_STRICT;
846
847  public function __construct($pMessage = null, $pImportance = self::EVO_USER_NOTICE) {
848    $this->message = $pMessage;
849    $this->layoutType = $pImportance;
850    $this->filterImportance = $pImportance;
851    $this->type = 'log';
852    $this->taskLabel = 'global';        // 'log' types may be scoped to tasks
853    $this->context = debug_backtrace(); // context for 'log' type is a stack backtrace array
854    $this->actions = null;      // 'log' types have no action records
855    $this->undoActions = null;  // 'log' types have no rollback records
856    $this->timestamp = time();
857    $this->onFlag = null;
858  }
859
860  public function getTimestamp() {
861    return $this->timestamp;
862  }
863
864  public function setMessage(&$pMessage) {
865    $sav = $this->message;
866    $this->message = $pMessage;
867    return $sav;
868  }
869  public function getMessage() {
870    return $this->message;
871  }
872
873  public function setLayoutType(&$pLayoutType) {
874    $sav = $this->layoutType;
875    $this->layoutType = $pLayoutType;
876    return $sav;
877  }
878  public function getLayoutType() {
879    return $this->layoutType;
880  }
881
882  public function setImportance(&$pImportance) {
883    $sav = $this->filterImportance;
884    $this->filterImportance = $pImportance;
885    return $sav;
886  }
887  public function getImportance() {
888    return $this->filterImportance;
889  }
890
891  public function setException($pException) {
892    $this->exception = $pException;
893  }
894  public function getException() {
895    return $this->exception;
896  }
897  public function setFilename($pFilename) {
898    $this->filename = $pFilename;
899  }
900  public function getFilename() {
901    return $this->filename;
902  }
903  public function setLinenum($pLinenum) {
904    $this->linenum = $pLinenum;
905  }
906  public function getLinenum() {
907    return $this->linenum;
908  }
909  public function setCode($pCode) {
910    $this->code = $pCode;
911  }
912  public function getCode() {
913    return $this->code;
914  }
915  public function setOnFlag($pOnFlag) {
916    $this->onFlag = $pOnFlag;
917  }
918  public function getOnFlag() {
919    return $this->onFlag;
920  }
921
922  public function setType(&$pType) {
923    $sav = $this->type;
924    $this->type = $pType;
925    return $sav;
926  }
927  public function getType() {
928    return $this->type;
929  }
930
931  public function setContext(&$pContext) {
932    $sav = $this->context;
933    $this->context = $pContext;
934    return $sav;
935  }
936  public function getContext() {
937    return $this->context;
938  }
939  public function adjustContext($shifts=1) {
940    array_splice($this->context,0,$shifts);
941  }
942
943  public static $ClassifyErrorTypes =
944    array (
945                                         _EL_DEBUG           => 'debug',
946                                         _EL_INFO            => 'info',
947                                         _EL_CRITICAL        => 'critical',
948
949                                         _EL_ERROR           => 'error',
950                                         _EL_WARNING         => 'warning',
951                                         _EL_PARSE           => 'parse',
952                                         _EL_NOTICE          => 'notice',
953                                         _EL_CORE_ERROR      => 'error',
954                                         _EL_CORE_WARNING    => 'warning',
955                                         _EL_COMPILE_ERROR   => 'error',
956                                         _EL_COMPILE_WARNING => 'warning',
957                                         _EL_USER_ERROR      => 'error',
958                                         _EL_USER_WARNING    => 'warning',
959                                         _EL_USER_NOTICE     => 'notice',
960                                         _EL_STRICT          => 'notice',
961                                         'off'                     => 'off',
962                                         'on'                      => 'on',
963                                         'all'                     => 'all',
964                                         );
965
966  public static $GroupErrorTypes =
967    array (
968                                         'debug'    => array(_EL_DEBUG),
969                                         'info'     => array(_EL_INFO),
970                                         'critical' => array(_EL_CRITICAL),
971
972                                         'error'    => array(_EL_ERROR, _EL_CORE_ERROR, _EL_COMPILE_ERROR, _EL_USER_ERROR),
973                                         'warning'  => array(_EL_WARNING, _EL_CORE_WARNING, _EL_COMPILE_WARNING, _EL_USER_WARNING),
974                                         'notice'   => array(_EL_NOTICE, _EL_USER_NOTICE, _EL_STRICT),
975                                         'user'     => array(_EL_USER_ERROR, _EL_USER_WARNING, _EL_USER_NOTICE),
976                                         'core'     => array(_EL_CORE_ERROR, _EL_CORE_WARNING),
977                                         'compile'  => array(_EL_COMPILE_ERROR, _EL_COMPILE_WARNING, _EL_PARSE),
978                                         );
979
980  public static $SystemErrorTypes =
981    array (
982                                         E_ERROR           => _EL_ERROR,
983                                         E_WARNING         => _EL_WARNING,
984                                         E_PARSE           => _EL_PARSE,
985                                         E_NOTICE          => _EL_NOTICE,
986                                         E_CORE_ERROR      => _EL_CORE_ERROR,
987                                         E_CORE_WARNING    => _EL_CORE_WARNING,
988                                         E_COMPILE_ERROR   => _EL_COMPILE_ERROR,
989                                         E_COMPILE_WARNING => _EL_COMPILE_WARNING,
990                                         E_USER_ERROR      => _EL_USER_ERROR,
991                                         E_USER_WARNING    => _EL_USER_WARNING,
992                                         E_USER_NOTICE     => _EL_USER_NOTICE,
993                                         E_STRICT          => _EL_STRICT,
994                                         );
995
996  private static $PrettyErrorTypes =
997    array (
998                                         _EL_DEBUG           => "Debug",
999                                         _EL_INFO            => "Info",
1000                                         _EL_ERROR           => "Error",
1001                                         _EL_WARNING         => "Warning",
1002                                         _EL_PARSE           => "Parsing Error",
1003                                         _EL_NOTICE          => "Notice",
1004                                         _EL_CORE_ERROR      => "Core Error",
1005                                         _EL_CORE_WARNING    => "Core Warning",
1006                                         _EL_COMPILE_ERROR   => "Compile Error",
1007                                         _EL_COMPILE_WARNING => "Compile Warning",
1008                                         _EL_USER_ERROR      => "User Error",
1009                                         _EL_USER_WARNING    => "User Warning",
1010                                         _EL_USER_NOTICE     => "User Notice",
1011                                         _EL_STRICT          => "Runtime Notice"
1012                                         );
1013
1014  /**
1015   * Present an error type for display in messages
1016   * @param $pErrorType the internal EVO_ error type
1017   * @return string phrase
1018   */
1019  public static function PrettyErrorType($pErrorType) {
1020    return empty(self::$PrettyErrorTypes[$pErrorType]) ? null : self::$PrettyErrorTypes[$pErrorType];
1021  }
1022
1023  /**
1024   * Classify an error type, stripping away the distinction between system, core and user
1025   * @param $pErrorType the internal EVO_ error type
1026   * @return string classification
1027   */
1028  public static function stClassifyErrorType($pErrorType) {
1029    return empty(self::$ClassifyErrorTypes[$pErrorType]) ? false : self::$ClassifyErrorTypes[$pErrorType];
1030  }
1031  public function classifyErrorType() {
1032    return empty(self::$ClassifyErrorTypes[$this->layoutType]) ? null : self::$ClassifyErrorTypes[$this->layoutType];
1033  }
1034
1035  /**
1036   * Convert a system error type to an EventObject error type
1037   * @param $pSystemErrorType the system E_ error integer
1038   * @return string , the EVO_ string error type
1039   */
1040  public static function ErrorType($pSystemErrorType) {
1041    return empty(self::$SystemErrorTypes[$pSystemErrorType]) ? null : self::$SystemErrorTypes[$pSystemErrorType];
1042  }
1043
1044  /**
1045   * @static method to convert a string of event levels to a hash of booleans
1046   *
1047   * The specific event levels correspond to php error types, @see the php function error_reporting() for
1048   * more details.
1049   *
1050   * The generic event levels are debug, info, notice, warning, error, critical, user, core and compile.
1051   *
1052   * Each event level in the list may be prefixed with a "=" or a "!" character.  If there is no prefix,
1053   * the range of message types matched is the generic level and upwards.  With the "=" character, just that
1054   * message type is matched.  Conversely, with the "!" character, the message type is specifically disallowed.
1055   *
1056   * "=debug" - EVO_DEBUG
1057   * "error" - E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR
1058   * "user,critical" - E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE, EVO_CRITICAL
1059   * "=notice,debug,!core" - EVO_NOTICE, EVO_USER_NOTICE, EVO_STRICT,
1060   *     EVO_DEBUG, EVO_INFO, E_WARNING, E_COMPILE_WARNING, E_USER_WARNING, E_ERROR, E_COMPILE_ERROR, E_USER_ERROR, EVO_CRITICAL
1061   *     !core turns E_CORE_ERROR and E_CORE_WARNING off, which would have been enabled by "debug"
1062   * "core error, compile error, critical" - E_CORE_ERROR, E_COMPILE_ERROR, EVO_CRITICAL
1063   *
1064   * @see error_reporting()
1065   * @param string $pThresholds a comma separated list of event levels
1066   * @return hash of booleans
1067   */
1068  public static function ConvertThresholds($pThresholds) {
1069    $basket = EventObject::$ClassifyErrorTypes;
1070    foreach ($basket as $type => $class) {
1071      $basket[$type] = false;
1072    }
1073
1074    $thresholds = explode(',', $pThresholds);
1075    foreach ($thresholds as $level) {
1076      $level = trim($level);
1077      // debug, info, notice, warning, error, critical
1078
1079      if (substr($level,0,1) == '=' || substr($level,0,1) == '!') {
1080                                $modifier = substr($level,0,1);
1081                                $level = substr($level,1);
1082      }
1083      else
1084                                $modifier = '';
1085
1086      if (preg_match('/^(?:all|debug|info|notice|warning|error|critical|user|core|compile)$/', $level)) {
1087                                if (!empty($modifier))
1088                                        $types = array($level);
1089                                elseif ($level=='all') {
1090                                        $types = array_keys($basket);
1091                                }
1092                                else {
1093                                        $order = 'debug|info|warning|error|critical';
1094                                        $pos = strpos($order, $level);
1095                                        if ($pos!==false)
1096                                                $types = explode('|', substr($order,$pos));
1097                                        else
1098                                                $types = array($level);
1099                                }
1100
1101                                foreach ($types as $type2) {
1102                                        $typegroups = empty(EventObject::$GroupErrorTypes[$type2]) ? array($type2) : EventObject::$GroupErrorTypes[$type2];
1103                                        foreach ($typegroups as $type3) {
1104                                                $basket[$type3] = empty($modifier) || $modifier=='=' ? true : false;
1105                                        }
1106                                }
1107      }
1108      elseif (array_key_exists($basket, $level)) {
1109                                $basket[$level] = empty($modifier) || $modifier=='=' ? true : false;
1110      }
1111      else {
1112                                // whatever
1113                                $basket[$level] = empty($modifier) || $modifier=='=' ? true : false;
1114      }
1115    }
1116
1117    return $basket;
1118  }
1119}
1120
1121/**
1122 * @package    WiFiDogAuthServer
1123 * @subpackage Eventlogging
1124 * @author     Rob Janes <janes.rob@gmail.com>
1125 * @copyright  2005-2006 Rob Janes
1126 */
1127class EventChannel {
1128  protected $formatter;
1129  protected $thresholds;
1130
1131  protected $holdFlag;
1132  protected $eventFifo;
1133
1134  protected $blockPercolation;
1135
1136  protected $name;
1137
1138        protected $formattingInfo;
1139
1140  public function __construct($pFormatter=null, $pThresholds=null, $pBlockPercolation=null, $pHoldFlag=null) {
1141    $this->formatter = $pFormatter;
1142    $this->thresholds = EventObject::ConvertThresholds($pThresholds);
1143    $this->eventFifo = array();
1144                $this->formattingInfo = array();
1145    $this->blockPercolation = empty($pBlockPercolation) ? false : true;
1146    if (isset($pHoldFlag)) $this->holdFlag = $pHoldFlag;
1147  }
1148
1149  function __destruct() {
1150    $this->flushEventQueue();
1151  }
1152
1153  public function setFormatter($obj) {
1154    $sav = $this->formatter;
1155    $this->formatter = $obj;
1156    return $sav;
1157  }
1158  public function getFormatter() {
1159    return $this->formatter;
1160  }
1161
1162  public function getHoldFlag() {
1163    return $this->holdFlag;
1164  }
1165  public function setHoldFlag($flag) {
1166    $sav = $this->holdFlag;
1167    $this->holdFlag = $flag;
1168    return $sav;
1169  }
1170
1171  public function getName() {
1172    return $this->name;
1173  }
1174  public function setName($pName) {
1175    $sav = $this->name;
1176    if (empty($sav)) $this->name = $pName;
1177    return $sav;
1178  }
1179
1180        public function getFormattingInfo($keyword) {
1181                if ($keyword===null) return null;
1182                return array_key_exists($this->formattingInfo[$keyword]) ? $this->formattingInfo[$keyword] : null;
1183        }
1184        public function setFormattingInfo($keyword, $value=null) {
1185                $sav = array_key_exists($this->formattingInfo[$keyword]) ? $this->formattingInfo[$keyword] : null;
1186
1187                if ($value===null)
1188                        unset( $this->formattingInfo[$keyword] );
1189                else
1190                        $this->formattingInfo[$keyword] = $value;
1191
1192                return $sav;
1193        }
1194        public function getAllFormattingInfo() {
1195                return $this->formattingInfo;
1196        }
1197
1198  public function checkType($event) {
1199    return $event->getType() == 'log' ? true : false;
1200  }
1201
1202  public function passesThresholds($event, $pEffectiveImportance=null) {
1203    $myImportance = !empty($pEffectiveImportance) ? $pEffectiveImportance : $event->getImportance();
1204    return empty($this->thresholds[$myImportance]) ? false : true;
1205  }
1206
1207  public function receiveEvent($event, $pEffectiveImportance=null) {
1208    if ($this->checkType($event) && $this->passesThresholds($event, $pEffectiveImportance)) {
1209      if ($this->holdFlag)
1210                                $this->queueEvent($event);
1211      else {
1212                                if (!empty($this->eventFifo) && count($this->eventFifo)>0) $this->flushEventQueue();
1213                                $this->processEvent($event);
1214      }
1215    }
1216
1217    return !empty($this->blockPercolation) ? false : true;
1218  }
1219
1220  public function processEvent($event) {
1221    // $dt = date("Y-m-d H:i:s (T)", $event->getTimestamp());
1222
1223    print $this->formatter->formatEvent($event, $this->formattingInfo);
1224
1225    return $this->blockPercolation;
1226  }
1227
1228  public function queueEvent($event) {
1229    array_push($this->eventFifo, $event);
1230  }
1231  public function dequeueEvent() {
1232    if (empty($this->eventFifo) || count($this->eventFifo)==0) return false;
1233    $this->processEvent(array_shift($this->eventFifo));
1234    return true;
1235  }
1236  public function flushEventQueue() {
1237    $counter = 0;
1238    while ($this->dequeueEvent()) {
1239      $counter++;
1240    }
1241    return $counter;
1242  }
1243  public function discardEventQueue() {
1244    $this->eventFifo = array();
1245  }
1246}
1247
1248/**
1249 * @package    WiFiDogAuthServer
1250 * @subpackage Eventlogging
1251 * @author     Rob Janes <janes.rob@gmail.com>
1252 * @copyright  2005-2006 Rob Janes
1253 */
1254class PrintChannel extends EventChannel {
1255  // an alias
1256}
1257
1258/**
1259 * @package    WiFiDogAuthServer
1260 * @subpackage Eventlogging
1261 * @author     Rob Janes <janes.rob@gmail.com>
1262 * @copyright  2005-2006 Rob Janes
1263 */
1264class NullChannel extends EventChannel {
1265  public function __construct($pThresholds=null, $pBlockPercolation=null) {
1266    parent::__construct(new EventFormatter(), $pThresholds, $pBlockPercolation);
1267  }
1268
1269  public function processEvent($event) {
1270    return $this->blockPercolation;
1271  }
1272}
1273
1274/**
1275 * @package    WiFiDogAuthServer
1276 * @subpackage Eventlogging
1277 * @author     Rob Janes <janes.rob@gmail.com>
1278 * @copyright  2005-2006 Rob Janes
1279 */
1280class ArrayChannel extends EventChannel {
1281  public function __construct($pFormatter=null, $pThresholds=null, $pBlockPercolation=null) {
1282    parent::__construct($pFormatter, $pThresholds, $pBlockPercolation);
1283    $this->holdFlag = true;
1284  }
1285  function __destruct() {
1286    $this->discardEventQueue();
1287  }
1288
1289  public function getHoldFlag() {
1290    return true;
1291  }
1292  public function setHoldFlag($flag) {
1293    return true;
1294  }
1295}
1296
1297/**
1298 * @package    WiFiDogAuthServer
1299 * @subpackage Eventlogging
1300 * @author     Rob Janes <janes.rob@gmail.com>
1301 * @copyright  2005-2006 Rob Janes
1302 */
1303class FileChannel extends EventChannel {
1304  private $filename;
1305  private $io;
1306
1307  public function __construct($pFilename, $pFormatter=null, $pThresholds=null, $pBlockPercolation=null, $pHoldFlag=null) {
1308    parent::__construct($pFormatter, $pThresholds, $pBlockPercolation, $pHoldFlag);
1309    $this->filename = $pFilename;
1310    $this->io = fopen($pFilename, "a"); // returns false if it fails, and issues E_WARNING message
1311  }
1312
1313  public function __destruct() {
1314    if (!empty($this->io)) fclose($this->io);
1315  }
1316
1317  public function processEvent($event) {
1318    // $dt = date("Y-m-d H:i:s (T)", $event->getTimestamp());
1319
1320    if (!empty($this->io)) fwrite($this->io, $this->formatter->formatEvent($event, $this->formattingInfo));
1321
1322    return $this->blockPercolation;
1323  }
1324}
1325
1326/**
1327 * @package    WiFiDogAuthServer
1328 * @subpackage Eventlogging
1329 * @author     Rob Janes <janes.rob@gmail.com>
1330 * @copyright  2005-2006 Rob Janes
1331 */
1332class EventFormatter {
1333  public function formatEvent($event, $info=null) {
1334    $myErrorClass = $event->classifyErrorType();
1335
1336    $myFilename = $event->getFilename();
1337    $myLinenum = $event->getLinenum();
1338
1339    $string = $this->formatMessage($myErrorClass,
1340                                                                                                                                         EventObject::PrettyErrorType($event->getLayoutType()),
1341                                                                                                                                         $event->getMessage(),
1342                                                                                                                                         $myFilename,
1343                                                                                                                                         $myLinenum);
1344
1345    if ($myErrorClass == 'error') {
1346      $string .= "<br/>\nStack Backtrace\n<pre>\n" .
1347                                self::FormatBacktrace($event->getContext()) .
1348                                "</pre>\n"
1349                                ;
1350    }
1351
1352    return $string;
1353  }
1354
1355  public function formatMessage($pCSSClass, $pMessageType, $pMessage, $pFilename, $pLinenum) {
1356    $string = (!empty($pCSSClass) ? "<span class='log_$pCSSClass'>" : '') .
1357      "<b>$pMessageType</b>: $pMessage" .
1358      (!empty($pFilename) ? " in <b>$pFilename</b>" . (!empty($pLinenum) ? " on line <b>$pLinenum</b>" : "") : "") .
1359      (!empty($pCSSClass) ? "</span>" : '') .
1360      "<br/>\n";
1361
1362    return $string;
1363  }
1364
1365  public static function FormatBacktrace($trace) {
1366    $string = '';
1367    for ($i=0; $i<count($trace); $i++) {
1368      $item = $trace[$i];
1369      // #0 eval() called at [/tmp/include.php:5]
1370      // #1 a() called at [/tmp/include.php:17]
1371      // #2 include(/tmp/include.php) called at [/tmp/test.php:3]
1372
1373      $string .= "   #$i ".(!empty($item['class']) ? $item['class'] . $item['type'] : '') . $item['function'] . '(';
1374      for ($j=0, $args = $item['args']; $j < count($args); $j++) {
1375                                if (is_null($args[$j])) $val = 'null';
1376                                elseif (is_bool($args[$j])) $val = $args[$j] ? 'true' : 'false';
1377                                elseif (is_numeric($args[$j])) $val = $args[$j];
1378                                else $val = "'" . $args[$j] . "'";
1379
1380                                $string .= ($j>0 ? ',' : '') . $val;
1381      }
1382
1383      $string .= ') called at [' . (empty($item['file']) ? "" : $item['file']) . ':' . (empty($item['line']) ? "" : $item['line']) . "]\n";
1384    }
1385    return $string;
1386  }
1387}
1388
1389/**
1390 * @package    WiFiDogAuthServer
1391 * @subpackage Eventlogging
1392 * @author     Rob Janes <janes.rob@gmail.com>
1393 * @copyright  2005-2006 Rob Janes
1394 */
1395class HTMLFormatter extends EventFormatter {
1396  // alias
1397}
1398
1399/**
1400 * @package    WiFiDogAuthServer
1401 * @subpackage Eventlogging
1402 * @author     Rob Janes <janes.rob@gmail.com>
1403 * @copyright  2005-2006 Rob Janes
1404 */
1405class SyslogFormatter extends EventFormatter {
1406  public function formatEvent($event, $info=null) {
1407    $dt = date("Y-m-d H:i:s (T)", $event->getTimestamp());
1408
1409    $myFilename = $event->getFilename();
1410    $myLinenum = $event->getLinenum();
1411
1412    $string = "$dt ".EventObject::PrettyErrorType($event->getLayoutType()).": "
1413                        . $event->getMessage()
1414                        . (!empty($myFilename) ? " in $myFilename". (!empty($myLinenum) ? " on line $myLinenum" : "") : "")
1415                        . "\n";
1416
1417    if ($event->classifyErrorType() == 'error') {
1418      $string .= "   Stack Backtrace\n" .
1419                                self::FormatBacktrace($event->getContext()) .
1420                                "\n"
1421                                ;
1422    }
1423
1424    return $string;
1425  }
1426}
1427
1428/**
1429 * @package    WiFiDogAuthServer
1430 * @subpackage Eventlogging
1431 * @author     Rob Janes <janes.rob@gmail.com>
1432 * @copyright  2005-2006 Rob Janes
1433 */
1434class HTMLCommentsFormatter extends EventFormatter {
1435  public function formatEvent($event, $info=null) {
1436    $myFilename = $event->getFilename();
1437    $myLinenum = $event->getLinenum();
1438
1439    $string = "<!-- ".EventObject::PrettyErrorType($event->getLayoutType()).": ".
1440      $event->getMessage().
1441      (!empty($myFilename) ? " in $myFilename" . (!empty($myLinenum) ? " on line $myLinenum" : "") : "");
1442
1443    if ($event->classifyErrorType() == 'error') {
1444      $string .= "\nStack Backtrace\n" .
1445                                self::FormatBacktrace($event->getContext()) .
1446                                "\n"
1447                                ;
1448    }
1449
1450    $string .= " -->\n";
1451
1452    return $string;
1453  }
1454}
1455
1456/**
1457 * @package    WiFiDogAuthServer
1458 * @subpackage Eventlogging
1459 * @author     Rob Janes <janes.rob@gmail.com>
1460 * @copyright  2005-2006 Rob Janes
1461 */
1462class HTMLTableFormatter extends EventFormatter {
1463  public function formatMessage($pCSSClass, $pMessageType, $pMessage, $pFilename, $pLinenum) {
1464    $pCSSClass = empty($pCSSClass) ? '' : "class='$pCSSClass'";
1465    $string = "<tr>" .
1466      "<td $pCSSClass>$pMessageType</td><td $pCSSClass>$pMessage</td>" .
1467      (!empty($pFilename) ? "<td $pCSSClass>$pFilename</td>" .
1468       (!empty($pLinenum) ? "<td $pCSSClass>$pLinenum</td>" : "") : "") .
1469      "</tr>\n";
1470
1471    return $string;
1472  }
1473}
1474
1475
1476function elBomb($pMessage=null) {
1477  if (func_num_args() > 0) EventLogging::stBomb($pMessage);
1478  else EventLogging::stBomb();
1479}
1480
1481function elLogMessage($errmsg, $errno=EventObject::EVO_USER_NOTICE) {
1482  EventLogging::stMessage($errmsg, $errno);
1483}
1484function elLogError($errmsg) {
1485  EventLogging::stMessage($errmsg, EventObject::EVO_USER_ERROR);
1486}
1487function elLogWarning($errmsg) {
1488  EventLogging::stMessage($errmsg, EventObject::EVO_USER_WARNING);
1489}
1490function elLogNotice($errmsg) {
1491  EventLogging::stMessage($errmsg, EventObject::EVO_USER_NOTICE);
1492}
1493function elLogDebug($errmsg) {
1494  EventLogging::stMessage($errmsg, EventObject::EVO_DEBUG);
1495}
1496function elLogInfo($errmsg) {
1497  EventLogging::stMessage($errmsg, EventObject::EVO_INFO);
1498}
1499
1500/*
1501 * Local variables:
1502 * tab-width: 2
1503 * c-basic-offset: 2
1504 * c-hanging-comment-ender-p: nil
1505 * End:
1506 */
1507
1508
Note: See TracBrowser for help on using the browser.