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

Revision 1019, 47.5 KB (checked in by lokkju, 7 years ago)

Fix for 'object passed as variable' error.

  • 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    $t = $pException->getTrace();
549    $eo->setContext($t);
550
551    self::stBroadcastEvent($eo);
552  }
553
554  public static function DieHandler() {
555    // is this normal program exit, or was there an error?
556    $eo = new EventObject("die()", EventObject::EVO_ERROR);
557
558    self::stBroadcastEvent($eo);
559  }
560
561  //***********************************************************************************
562
563  public static function CaptureErrors() {
564    error_reporting(E_ALL);
565    return set_error_handler(array('EventLogging', 'ErrorHandler'));
566  }
567
568  public static function CaptureExceptions() {
569    return set_exception_handler(array('EventLogging', 'ExceptionHandler'));
570  }
571
572  public static function CaptureDie() {
573    register_shutdown_function(array('EventLogging', 'DieHandler'));
574  }
575
576  public static function CaptureAll() {
577    self::CaptureExceptions();
578    self::CaptureErrors();
579    //self::CaptureDie();
580
581    return true;
582  }
583
584  public function bomb($pMessage=null) {
585    if (empty($pMessage))
586      $pMessage = "Bomb()";
587
588    $eo = new EventObject($pMessage, EventObject::EVO_ERROR);
589    $this->broadcastEvent($eo);
590
591    die($pMessage);
592  }
593
594  public static function stBomb($pMessage=null) {
595    if (func_num_args() > 0) {
596      // log $message
597    }
598
599    if (empty($pMessage))
600      $pMessage = "Bomb()";
601
602    $eo = new EventObject($pMessage, EventObject::EVO_ERROR);
603    self::stBroadcastEvent($eo);
604
605    die($pMessage);
606  }
607
608  public function addChannel($pObserver, $pName=null) {
609    if (empty($pName)) $pName = count($this->observers);
610
611    if ("$pName" == 'DEFAULT')
612      $this->defaultObserver = $pObserver;
613    else
614      $this->observers[$pName] = $pObserver;
615
616    return $pName;
617  }
618  public static function stAddChannel($pObserver) {
619    self::$globalTracker->addChannel($pObserver);
620  }
621
622  public function getChannel($pName) {
623    return $pName == 'DEFAULT' ? $this->defaultObserver : (empty($this->observers[$pName]) ? false : $this->observers[$pName]);
624  }
625
626  public function remChannel($pChannel) {
627    if (!is_object($pChannel))
628      $pName = $pChannel;
629    else {
630      foreach ($this->observers as $name => $observer) {
631                                if ($observer===$pChannel) {
632                                        $pName = $name;
633                                        break;
634                                }
635      }
636    }
637
638    if (!empty($pName))
639      if ($pName == 'DEFAULT')
640                                unset($this->defaultObserver);
641      else
642                                unset($this->observers[$pName]);
643  }
644
645  public static function stAddContextFilter($options) {
646    $context = array();
647
648    if (!empty($options['file'])) {
649      $context['file'] = $options['file'];
650    }
651    elseif (!empty($options['class'])) {
652      $context['class'] = $options['class'];
653      $context['function'] = $options['function'];
654    }
655    elseif (!empty($options['function'])) {
656      $context['class'] = '';
657      $context['function'] = $options['function'];
658    }
659    elseif (!empty($options['matchlevel'])) {
660      $context['matchlevel'] = $options['matchlevel'];
661      $context['matchpattern'] = $options['matchpattern'];
662    }
663
664    if (!empty($options['redirect'])) $context['redirect'] = $options['redirect'];
665    if (!empty($options['effectiveLevel'])) $context['effectiveLevel'] = $options['effectiveLevel'];
666
667    self::$globalTracker->contextFilters[] = $context;
668  }
669
670  public function filterContext(&$event) {
671    $needle =& $event;
672    $found = null;
673    foreach ($this->contextFilters as $haystack) {
674      $filename = $needle->getFilename();
675      $context = $needle->getContext();
676      if (!empty($haystack['matchlevel'])) {
677                                if ($haystack['matchlevel'] == $needle->getLayoutType()) {
678                                        if (preg_match($haystack['matchpattern'], $needle->getMessage())) {
679                                                $found = $haystack;
680                                        }
681                                }
682
683                                // print "\n<!-- filterContext haystack $haystack[matchlevel], $haystack[matchpattern], $haystack[effectiveLevel] ". "'".$needle->getMessage()."' ".(empty($found) ? "NOT FOUND" : "FOUND"). " -->\n";
684      }
685      elseif (!empty($haystack['file'])) {
686                                if ($filename == $haystack['file']) {
687                                        $found = $haystack;
688                                }
689                                else {
690                                        foreach ($context as $backtrace) {
691                                                if ($backtrace['file'] == $haystack['file']) {
692                                                        $found = $haystack;
693                                                        break;
694                                                }
695                                        }
696                                }
697      }
698      elseif (!empty($haystack['class'])) {
699                                foreach ($context as $backtrace) {
700                                        if (!empty($backtrace['class']) && $backtrace['class'] == $haystack['class'] &&
701                                                        (empty($haystack['function']) || $backtrace['function'] == $haystack['function'])) {
702                                                $found = $haystack;
703                                                break;
704                                        }
705                                }
706      }
707      elseif (!empty($haystack['function'])) {
708                                foreach ($context as $backtrace) {
709                                        if (!empty($backtrace['function']) && $backtrace['function'] == $haystack['function']) {
710                                                $found = $haystack;
711                                                break;
712                                        }
713                                }
714      }
715
716      if (!empty($found))
717                                break;
718    }
719
720    if (!empty($found)) {
721      if (!empty($found['effectiveLevel'])) {
722                                if ($found['effectiveLevel'] == 'on')
723                                        $needle->setOnFlag(true);
724                                elseif ($found['effectiveLevel'] == 'off')
725                                        $needle->setOnFlag(false);
726                                else
727                                        $needle->setImportance($found['effectiveLevel']);
728      }
729
730      if (!empty($found['redirect']))
731                                return $found['redirect'];
732
733      return true;
734    }
735
736    return false;
737  }
738
739  //"Class::Method(critical)"
740  //"Class::Method(off)"
741  //"strict~/var:\sDeprecated/(off)"
742  //"Function(critical) /this/path/file.php(debug)"
743  public function quickContextFilters($pString) {
744    if (empty($pString)) return 0;
745
746    $myCounter = 0;
747    $myList = preg_split('/\s+/', $pString, -1, PREG_SPLIT_NO_EMPTY);
748    foreach ($myList as $myItem) {
749      if (preg_match('/^([^()]+)\(([^()]+)\)$/', $myItem, $myMatches)) {
750                                $myContext = $myMatches[1];
751                                $myOverride = $myMatches[2];
752                                $filter = array();
753                                if (strpos($myContext, '::') !== false) {
754                                        // class
755                                        $tmp = explode('::', $myContext, 2);
756                                        $filter['class'] = trim($tmp[0]);
757                                        if (preg_match('/\S/', $tmp[1])) $filter['function'] = trim($tmp[1]);
758                                        $filter['effectiveLevel'] = trim($myOverride);
759                                }
760                                elseif (strpos($myContext, '~') !== false) {
761                                        // message match
762                                        $tmp = explode('~', $myContext, 2);
763                                        $filter['matchlevel'] = trim($tmp[0]);
764                                        $filter['matchpattern'] = trim($tmp[1]);
765                                        $filter['effectiveLevel'] = trim($myOverride);
766                                }
767                                elseif (strpos($myContext, '/') !== false) {
768                                        // file
769                                        $filter['file'] = trim($myContext);
770                                        $filter['effectiveLevel'] = trim($myOverride);
771                                }
772                                else {
773                                        // function
774                                        $filter['function'] = trim($myContext);
775                                        $filter['effectiveLevel'] = trim($myOverride);
776                                }
777
778                                if (EventObject::stClassifyErrorType($myOverride)) {
779                                        EventLogging::stAddContextFilter($filter);
780                                        $myCounter++;
781                                }
782      }
783    }
784
785    return $myCounter;
786  }
787}
788
789define('_EL_DEBUG', 'debug');
790define('_EL_INFO', 'info');
791define('_EL_CRITICAL', 'critical');
792
793define('_EL_ERROR', 'error');   // can't be captured
794define('_EL_WARNING', 'warning');
795define('_EL_PARSE', 'parse');   // can't be captured
796define('_EL_NOTICE', 'notice');
797define('_EL_CORE_ERROR', 'core error'); // can't be captured
798define('_EL_CORE_WARNING', 'core warning'); // can't be captured
799define('_EL_COMPILE_ERROR', 'compile error'); // can't be captured
800define('_EL_COMPILE_WARNING', 'compile warning'); // can't be captured
801define('_EL_USER_ERROR', 'user error');
802define('_EL_USER_WARNING', 'user warning');
803define('_EL_USER_NOTICE', 'user notice');
804define('_EL_STRICT', 'strict');
805
806/**
807 * @package    WiFiDogAuthServer
808 * @subpackage Eventlogging
809 * @author     Rob Janes <janes.rob@gmail.com>
810 * @copyright  2005-2006 Rob Janes
811 */
812class EventObject {
813  private $message;
814  private $layoutType;
815  private $filterImportance;
816  private $type;
817  private $context;
818
819  private $timestamp;
820
821  private $exception;
822  private $filename;
823  private $linenum;
824  private $code;
825
826  private $taskLabel;
827  private $actions;
828  private $undoActions;
829  private $onFlag;
830
831  const EVO_DEBUG = _EL_DEBUG;
832  const EVO_INFO = _EL_INFO;
833  const EVO_CRITICAL = _EL_CRITICAL;
834
835  const EVO_ERROR = _EL_ERROR;  // can't be captured
836  const EVO_WARNING = _EL_WARNING;
837  const EVO_PARSE = _EL_PARSE;  // can't be captured
838  const EVO_NOTICE = _EL_NOTICE;
839  const EVO_CORE_ERROR = _EL_CORE_ERROR; // can't be captured
840  const EVO_CORE_WARNING = _EL_CORE_WARNING; // can't be captured
841  const EVO_COMPILE_ERROR = _EL_COMPILE_ERROR; // can't be captured
842  const EVO_COMPILE_WARNING = _EL_COMPILE_WARNING; // can't be captured
843  const EVO_USER_ERROR = _EL_USER_ERROR;
844  const EVO_USER_WARNING = _EL_USER_WARNING;
845  const EVO_USER_NOTICE = _EL_USER_NOTICE;
846  const EVO_STRICT = _EL_STRICT;
847
848  public function __construct($pMessage = null, $pImportance = self::EVO_USER_NOTICE) {
849    $this->message = $pMessage;
850    $this->layoutType = $pImportance;
851    $this->filterImportance = $pImportance;
852    $this->type = 'log';
853    $this->taskLabel = 'global';        // 'log' types may be scoped to tasks
854    $this->context = debug_backtrace(); // context for 'log' type is a stack backtrace array
855    $this->actions = null;      // 'log' types have no action records
856    $this->undoActions = null;  // 'log' types have no rollback records
857    $this->timestamp = time();
858    $this->onFlag = null;
859  }
860
861  public function getTimestamp() {
862    return $this->timestamp;
863  }
864
865  public function setMessage(&$pMessage) {
866    $sav = $this->message;
867    $this->message = $pMessage;
868    return $sav;
869  }
870  public function getMessage() {
871    return $this->message;
872  }
873
874  public function setLayoutType(&$pLayoutType) {
875    $sav = $this->layoutType;
876    $this->layoutType = $pLayoutType;
877    return $sav;
878  }
879  public function getLayoutType() {
880    return $this->layoutType;
881  }
882
883  public function setImportance(&$pImportance) {
884    $sav = $this->filterImportance;
885    $this->filterImportance = $pImportance;
886    return $sav;
887  }
888  public function getImportance() {
889    return $this->filterImportance;
890  }
891
892  public function setException($pException) {
893    $this->exception = $pException;
894  }
895  public function getException() {
896    return $this->exception;
897  }
898  public function setFilename($pFilename) {
899    $this->filename = $pFilename;
900  }
901  public function getFilename() {
902    return $this->filename;
903  }
904  public function setLinenum($pLinenum) {
905    $this->linenum = $pLinenum;
906  }
907  public function getLinenum() {
908    return $this->linenum;
909  }
910  public function setCode($pCode) {
911    $this->code = $pCode;
912  }
913  public function getCode() {
914    return $this->code;
915  }
916  public function setOnFlag($pOnFlag) {
917    $this->onFlag = $pOnFlag;
918  }
919  public function getOnFlag() {
920    return $this->onFlag;
921  }
922
923  public function setType(&$pType) {
924    $sav = $this->type;
925    $this->type = $pType;
926    return $sav;
927  }
928  public function getType() {
929    return $this->type;
930  }
931
932  public function setContext(&$pContext) {
933    $sav = $this->context;
934    $this->context = $pContext;
935    return $sav;
936  }
937  public function getContext() {
938    return $this->context;
939  }
940  public function adjustContext($shifts=1) {
941    array_splice($this->context,0,$shifts);
942  }
943
944  public static $ClassifyErrorTypes =
945    array (
946                                         _EL_DEBUG           => 'debug',
947                                         _EL_INFO            => 'info',
948                                         _EL_CRITICAL        => 'critical',
949
950                                         _EL_ERROR           => 'error',
951                                         _EL_WARNING         => 'warning',
952                                         _EL_PARSE           => 'parse',
953                                         _EL_NOTICE          => 'notice',
954                                         _EL_CORE_ERROR      => 'error',
955                                         _EL_CORE_WARNING    => 'warning',
956                                         _EL_COMPILE_ERROR   => 'error',
957                                         _EL_COMPILE_WARNING => 'warning',
958                                         _EL_USER_ERROR      => 'error',
959                                         _EL_USER_WARNING    => 'warning',
960                                         _EL_USER_NOTICE     => 'notice',
961                                         _EL_STRICT          => 'notice',
962                                         'off'                     => 'off',
963                                         'on'                      => 'on',
964                                         'all'                     => 'all',
965                                         );
966
967  public static $GroupErrorTypes =
968    array (
969                                         'debug'    => array(_EL_DEBUG),
970                                         'info'     => array(_EL_INFO),
971                                         'critical' => array(_EL_CRITICAL),
972
973                                         'error'    => array(_EL_ERROR, _EL_CORE_ERROR, _EL_COMPILE_ERROR, _EL_USER_ERROR),
974                                         'warning'  => array(_EL_WARNING, _EL_CORE_WARNING, _EL_COMPILE_WARNING, _EL_USER_WARNING),
975                                         'notice'   => array(_EL_NOTICE, _EL_USER_NOTICE, _EL_STRICT),
976                                         'user'     => array(_EL_USER_ERROR, _EL_USER_WARNING, _EL_USER_NOTICE),
977                                         'core'     => array(_EL_CORE_ERROR, _EL_CORE_WARNING),
978                                         'compile'  => array(_EL_COMPILE_ERROR, _EL_COMPILE_WARNING, _EL_PARSE),
979                                         );
980
981  public static $SystemErrorTypes =
982    array (
983                                         E_ERROR           => _EL_ERROR,
984                                         E_WARNING         => _EL_WARNING,
985                                         E_PARSE           => _EL_PARSE,
986                                         E_NOTICE          => _EL_NOTICE,
987                                         E_CORE_ERROR      => _EL_CORE_ERROR,
988                                         E_CORE_WARNING    => _EL_CORE_WARNING,
989                                         E_COMPILE_ERROR   => _EL_COMPILE_ERROR,
990                                         E_COMPILE_WARNING => _EL_COMPILE_WARNING,
991                                         E_USER_ERROR      => _EL_USER_ERROR,
992                                         E_USER_WARNING    => _EL_USER_WARNING,
993                                         E_USER_NOTICE     => _EL_USER_NOTICE,
994                                         E_STRICT          => _EL_STRICT,
995                                         );
996
997  private static $PrettyErrorTypes =
998    array (
999                                         _EL_DEBUG           => "Debug",
1000                                         _EL_INFO            => "Info",
1001                                         _EL_ERROR           => "Error",
1002                                         _EL_WARNING         => "Warning",
1003                                         _EL_PARSE           => "Parsing Error",
1004                                         _EL_NOTICE          => "Notice",
1005                                         _EL_CORE_ERROR      => "Core Error",
1006                                         _EL_CORE_WARNING    => "Core Warning",
1007                                         _EL_COMPILE_ERROR   => "Compile Error",
1008                                         _EL_COMPILE_WARNING => "Compile Warning",
1009                                         _EL_USER_ERROR      => "User Error",
1010                                         _EL_USER_WARNING    => "User Warning",
1011                                         _EL_USER_NOTICE     => "User Notice",
1012                                         _EL_STRICT          => "Runtime Notice"
1013                                         );
1014
1015  /**
1016   * Present an error type for display in messages
1017   * @param $pErrorType the internal EVO_ error type
1018   * @return string phrase
1019   */
1020  public static function PrettyErrorType($pErrorType) {
1021    return empty(self::$PrettyErrorTypes[$pErrorType]) ? null : self::$PrettyErrorTypes[$pErrorType];
1022  }
1023
1024  /**
1025   * Classify an error type, stripping away the distinction between system, core and user
1026   * @param $pErrorType the internal EVO_ error type
1027   * @return string classification
1028   */
1029  public static function stClassifyErrorType($pErrorType) {
1030    return empty(self::$ClassifyErrorTypes[$pErrorType]) ? false : self::$ClassifyErrorTypes[$pErrorType];
1031  }
1032  public function classifyErrorType() {
1033    return empty(self::$ClassifyErrorTypes[$this->layoutType]) ? null : self::$ClassifyErrorTypes[$this->layoutType];
1034  }
1035
1036  /**
1037   * Convert a system error type to an EventObject error type
1038   * @param $pSystemErrorType the system E_ error integer
1039   * @return string , the EVO_ string error type
1040   */
1041  public static function ErrorType($pSystemErrorType) {
1042    return empty(self::$SystemErrorTypes[$pSystemErrorType]) ? null : self::$SystemErrorTypes[$pSystemErrorType];
1043  }
1044
1045  /**
1046   * @static method to convert a string of event levels to a hash of booleans
1047   *
1048   * The specific event levels correspond to php error types, @see the php function error_reporting() for
1049   * more details.
1050   *
1051   * The generic event levels are debug, info, notice, warning, error, critical, user, core and compile.
1052   *
1053   * Each event level in the list may be prefixed with a "=" or a "!" character.  If there is no prefix,
1054   * the range of message types matched is the generic level and upwards.  With the "=" character, just that
1055   * message type is matched.  Conversely, with the "!" character, the message type is specifically disallowed.
1056   *
1057   * "=debug" - EVO_DEBUG
1058   * "error" - E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR
1059   * "user,critical" - E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE, EVO_CRITICAL
1060   * "=notice,debug,!core" - EVO_NOTICE, EVO_USER_NOTICE, EVO_STRICT,
1061   *     EVO_DEBUG, EVO_INFO, E_WARNING, E_COMPILE_WARNING, E_USER_WARNING, E_ERROR, E_COMPILE_ERROR, E_USER_ERROR, EVO_CRITICAL
1062   *     !core turns E_CORE_ERROR and E_CORE_WARNING off, which would have been enabled by "debug"
1063   * "core error, compile error, critical" - E_CORE_ERROR, E_COMPILE_ERROR, EVO_CRITICAL
1064   *
1065   * @see error_reporting()
1066   * @param string $pThresholds a comma separated list of event levels
1067   * @return hash of booleans
1068   */
1069  public static function ConvertThresholds($pThresholds) {
1070    $basket = EventObject::$ClassifyErrorTypes;
1071    foreach ($basket as $type => $class) {
1072      $basket[$type] = false;
1073    }
1074
1075    $thresholds = explode(',', $pThresholds);
1076    foreach ($thresholds as $level) {
1077      $level = trim($level);
1078      // debug, info, notice, warning, error, critical
1079
1080      if (substr($level,0,1) == '=' || substr($level,0,1) == '!') {
1081                                $modifier = substr($level,0,1);
1082                                $level = substr($level,1);
1083      }
1084      else
1085                                $modifier = '';
1086
1087      if (preg_match('/^(?:all|debug|info|notice|warning|error|critical|user|core|compile)$/', $level)) {
1088                                if (!empty($modifier))
1089                                        $types = array($level);
1090                                elseif ($level=='all') {
1091                                        $types = array_keys($basket);
1092                                }
1093                                else {
1094                                        $order = 'debug|info|warning|error|critical';
1095                                        $pos = strpos($order, $level);
1096                                        if ($pos!==false)
1097                                                $types = explode('|', substr($order,$pos));
1098                                        else
1099                                                $types = array($level);
1100                                }
1101
1102                                foreach ($types as $type2) {
1103                                        $typegroups = empty(EventObject::$GroupErrorTypes[$type2]) ? array($type2) : EventObject::$GroupErrorTypes[$type2];
1104                                        foreach ($typegroups as $type3) {
1105                                                $basket[$type3] = empty($modifier) || $modifier=='=' ? true : false;
1106                                        }
1107                                }
1108      }
1109      elseif (array_key_exists($basket, $level)) {
1110                                $basket[$level] = empty($modifier) || $modifier=='=' ? true : false;
1111      }
1112      else {
1113                                // whatever
1114                                $basket[$level] = empty($modifier) || $modifier=='=' ? true : false;
1115      }
1116    }
1117
1118    return $basket;
1119  }
1120}
1121
1122/**
1123 * @package    WiFiDogAuthServer
1124 * @subpackage Eventlogging
1125 * @author     Rob Janes <janes.rob@gmail.com>
1126 * @copyright  2005-2006 Rob Janes
1127 */
1128class EventChannel {
1129  protected $formatter;
1130  protected $thresholds;
1131
1132  protected $holdFlag;
1133  protected $eventFifo;
1134
1135  protected $blockPercolation;
1136
1137  protected $name;
1138
1139        protected $formattingInfo;
1140
1141  public function __construct($pFormatter=null, $pThresholds=null, $pBlockPercolation=null, $pHoldFlag=null) {
1142    $this->formatter = $pFormatter;
1143    $this->thresholds = EventObject::ConvertThresholds($pThresholds);
1144    $this->eventFifo = array();
1145                $this->formattingInfo = array();
1146    $this->blockPercolation = empty($pBlockPercolation) ? false : true;
1147    if (isset($pHoldFlag)) $this->holdFlag = $pHoldFlag;
1148  }
1149
1150  function __destruct() {
1151    $this->flushEventQueue();
1152  }
1153
1154  public function setFormatter($obj) {
1155    $sav = $this->formatter;
1156    $this->formatter = $obj;
1157    return $sav;
1158  }
1159  public function getFormatter() {
1160    return $this->formatter;
1161  }
1162
1163  public function getHoldFlag() {
1164    return $this->holdFlag;
1165  }
1166  public function setHoldFlag($flag) {
1167    $sav = $this->holdFlag;
1168    $this->holdFlag = $flag;
1169    return $sav;
1170  }
1171
1172  public function getName() {
1173    return $this->name;
1174  }
1175  public function setName($pName) {
1176    $sav = $this->name;
1177    if (empty($sav)) $this->name = $pName;
1178    return $sav;
1179  }
1180
1181        public function getFormattingInfo($keyword) {
1182                if ($keyword===null) return null;
1183                return array_key_exists($this->formattingInfo[$keyword]) ? $this->formattingInfo[$keyword] : null;
1184        }
1185        public function setFormattingInfo($keyword, $value=null) {
1186                $sav = array_key_exists($this->formattingInfo[$keyword]) ? $this->formattingInfo[$keyword] : null;
1187
1188                if ($value===null)
1189                        unset( $this->formattingInfo[$keyword] );
1190                else
1191                        $this->formattingInfo[$keyword] = $value;
1192
1193                return $sav;
1194        }
1195        public function getAllFormattingInfo() {
1196                return $this->formattingInfo;
1197        }
1198
1199  public function checkType($event) {
1200    return $event->getType() == 'log' ? true : false;
1201  }
1202
1203  public function passesThresholds($event, $pEffectiveImportance=null) {
1204    $myImportance = !empty($pEffectiveImportance) ? $pEffectiveImportance : $event->getImportance();
1205    return empty($this->thresholds[$myImportance]) ? false : true;
1206  }
1207
1208  public function receiveEvent($event, $pEffectiveImportance=null) {
1209    if ($this->checkType($event) && $this->passesThresholds($event, $pEffectiveImportance)) {
1210      if ($this->holdFlag)
1211                                $this->queueEvent($event);
1212      else {
1213                                if (!empty($this->eventFifo) && count($this->eventFifo)>0) $this->flushEventQueue();
1214                                $this->processEvent($event);
1215      }
1216    }
1217
1218    return !empty($this->blockPercolation) ? false : true;
1219  }
1220
1221  public function processEvent($event) {
1222    // $dt = date("Y-m-d H:i:s (T)", $event->getTimestamp());
1223
1224    print $this->formatter->formatEvent($event, $this->formattingInfo);
1225
1226    return $this->blockPercolation;
1227  }
1228
1229  public function queueEvent($event) {
1230    array_push($this->eventFifo, $event);
1231  }
1232  public function dequeueEvent() {
1233    if (empty($this->eventFifo) || count($this->eventFifo)==0) return false;
1234    $this->processEvent(array_shift($this->eventFifo));
1235    return true;
1236  }
1237  public function flushEventQueue() {
1238    $counter = 0;
1239    while ($this->dequeueEvent()) {
1240      $counter++;
1241    }
1242    return $counter;
1243  }
1244  public function discardEventQueue() {
1245    $this->eventFifo = array();
1246  }
1247}
1248
1249/**
1250 * @package    WiFiDogAuthServer
1251 * @subpackage Eventlogging
1252 * @author     Rob Janes <janes.rob@gmail.com>
1253 * @copyright  2005-2006 Rob Janes
1254 */
1255class PrintChannel extends EventChannel {
1256  // an alias
1257}
1258
1259/**
1260 * @package    WiFiDogAuthServer
1261 * @subpackage Eventlogging
1262 * @author     Rob Janes <janes.rob@gmail.com>
1263 * @copyright  2005-2006 Rob Janes
1264 */
1265class NullChannel extends EventChannel {
1266  public function __construct($pThresholds=null, $pBlockPercolation=null) {
1267    parent::__construct(new EventFormatter(), $pThresholds, $pBlockPercolation);
1268  }
1269
1270  public function processEvent($event) {
1271    return $this->blockPercolation;
1272  }
1273}
1274
1275/**
1276 * @package    WiFiDogAuthServer
1277 * @subpackage Eventlogging
1278 * @author     Rob Janes <janes.rob@gmail.com>
1279 * @copyright  2005-2006 Rob Janes
1280 */
1281class ArrayChannel extends EventChannel {
1282  public function __construct($pFormatter=null, $pThresholds=null, $pBlockPercolation=null) {
1283    parent::__construct($pFormatter, $pThresholds, $pBlockPercolation);
1284    $this->holdFlag = true;
1285  }
1286  function __destruct() {
1287    $this->discardEventQueue();
1288  }
1289
1290  public function getHoldFlag() {
1291    return true;
1292  }
1293  public function setHoldFlag($flag) {
1294    return true;
1295  }
1296}
1297
1298/**
1299 * @package    WiFiDogAuthServer
1300 * @subpackage Eventlogging
1301 * @author     Rob Janes <janes.rob@gmail.com>
1302 * @copyright  2005-2006 Rob Janes
1303 */
1304class FileChannel extends EventChannel {
1305  private $filename;
1306  private $io;
1307
1308  public function __construct($pFilename, $pFormatter=null, $pThresholds=null, $pBlockPercolation=null, $pHoldFlag=null) {
1309    parent::__construct($pFormatter, $pThresholds, $pBlockPercolation, $pHoldFlag);
1310    $this->filename = $pFilename;
1311    $this->io = fopen($pFilename, "a"); // returns false if it fails, and issues E_WARNING message
1312  }
1313
1314  public function __destruct() {
1315    if (!empty($this->io)) fclose($this->io);
1316  }
1317
1318  public function processEvent($event) {
1319    // $dt = date("Y-m-d H:i:s (T)", $event->getTimestamp());
1320
1321    if (!empty($this->io)) fwrite($this->io, $this->formatter->formatEvent($event, $this->formattingInfo));
1322
1323    return $this->blockPercolation;
1324  }
1325}
1326
1327/**
1328 * @package    WiFiDogAuthServer
1329 * @subpackage Eventlogging
1330 * @author     Rob Janes <janes.rob@gmail.com>
1331 * @copyright  2005-2006 Rob Janes
1332 */
1333class EventFormatter {
1334  public function formatEvent($event, $info=null) {
1335    $myErrorClass = $event->classifyErrorType();
1336
1337    $myFilename = $event->getFilename();
1338    $myLinenum = $event->getLinenum();
1339
1340    $string = $this->formatMessage($myErrorClass,
1341                                                                                                                                         EventObject::PrettyErrorType($event->getLayoutType()),
1342                                                                                                                                         $event->getMessage(),
1343                                                                                                                                         $myFilename,
1344                                                                                                                                         $myLinenum);
1345
1346    if ($myErrorClass == 'error') {
1347      $string .= "<br/>\nStack Backtrace\n<pre>\n" .
1348                                self::FormatBacktrace($event->getContext()) .
1349                                "</pre>\n"
1350                                ;
1351    }
1352
1353    return $string;
1354  }
1355
1356  public function formatMessage($pCSSClass, $pMessageType, $pMessage, $pFilename, $pLinenum) {
1357    $string = (!empty($pCSSClass) ? "<span class='log_$pCSSClass'>" : '') .
1358      "<b>$pMessageType</b>: $pMessage" .
1359      (!empty($pFilename) ? " in <b>$pFilename</b>" . (!empty($pLinenum) ? " on line <b>$pLinenum</b>" : "") : "") .
1360      (!empty($pCSSClass) ? "</span>" : '') .
1361      "<br/>\n";
1362
1363    return $string;
1364  }
1365
1366  public static function FormatBacktrace($trace) {
1367    $string = '';
1368    for ($i=0; $i<count($trace); $i++) {
1369      $item = $trace[$i];
1370      // #0 eval() called at [/tmp/include.php:5]
1371      // #1 a() called at [/tmp/include.php:17]
1372      // #2 include(/tmp/include.php) called at [/tmp/test.php:3]
1373
1374      $string .= "   #$i ".(!empty($item['class']) ? $item['class'] . $item['type'] : '') . $item['function'] . '(';
1375      for ($j=0, $args = $item['args']; $j < count($args); $j++) {
1376                                if (is_null($args[$j])) $val = 'null';
1377                                elseif (is_bool($args[$j])) $val = $args[$j] ? 'true' : 'false';
1378                                elseif (is_numeric($args[$j])) $val = $args[$j];
1379                                else $val = "'" . $args[$j] . "'";
1380
1381                                $string .= ($j>0 ? ',' : '') . $val;
1382      }
1383
1384      $string .= ') called at [' . (empty($item['file']) ? "" : $item['file']) . ':' . (empty($item['line']) ? "" : $item['line']) . "]\n";
1385    }
1386    return $string;
1387  }
1388}
1389
1390/**
1391 * @package    WiFiDogAuthServer
1392 * @subpackage Eventlogging
1393 * @author     Rob Janes <janes.rob@gmail.com>
1394 * @copyright  2005-2006 Rob Janes
1395 */
1396class HTMLFormatter extends EventFormatter {
1397  // alias
1398}
1399
1400/**
1401 * @package    WiFiDogAuthServer
1402 * @subpackage Eventlogging
1403 * @author     Rob Janes <janes.rob@gmail.com>
1404 * @copyright  2005-2006 Rob Janes
1405 */
1406class SyslogFormatter extends EventFormatter {
1407  public function formatEvent($event, $info=null) {
1408    $dt = date("Y-m-d H:i:s (T)", $event->getTimestamp());
1409
1410    $myFilename = $event->getFilename();
1411    $myLinenum = $event->getLinenum();
1412
1413    $string = "$dt ".EventObject::PrettyErrorType($event->getLayoutType()).": "
1414                        . $event->getMessage()
1415                        . (!empty($myFilename) ? " in $myFilename". (!empty($myLinenum) ? " on line $myLinenum" : "") : "")
1416                        . "\n";
1417
1418    if ($event->classifyErrorType() == 'error') {
1419      $string .= "   Stack Backtrace\n" .
1420                                self::FormatBacktrace($event->getContext()) .
1421                                "\n"
1422                                ;
1423    }
1424
1425    return $string;
1426  }
1427}
1428
1429/**
1430 * @package    WiFiDogAuthServer
1431 * @subpackage Eventlogging
1432 * @author     Rob Janes <janes.rob@gmail.com>
1433 * @copyright  2005-2006 Rob Janes
1434 */
1435class HTMLCommentsFormatter extends EventFormatter {
1436  public function formatEvent($event, $info=null) {
1437    $myFilename = $event->getFilename();
1438    $myLinenum = $event->getLinenum();
1439
1440    $string = "<!-- ".EventObject::PrettyErrorType($event->getLayoutType()).": ".
1441      $event->getMessage().
1442      (!empty($myFilename) ? " in $myFilename" . (!empty($myLinenum) ? " on line $myLinenum" : "") : "");
1443
1444    if ($event->classifyErrorType() == 'error') {
1445      $string .= "\nStack Backtrace\n" .
1446                                self::FormatBacktrace($event->getContext()) .
1447                                "\n"
1448                                ;
1449    }
1450
1451    $string .= " -->\n";
1452
1453    return $string;
1454  }
1455}
1456
1457/**
1458 * @package    WiFiDogAuthServer
1459 * @subpackage Eventlogging
1460 * @author     Rob Janes <janes.rob@gmail.com>
1461 * @copyright  2005-2006 Rob Janes
1462 */
1463class HTMLTableFormatter extends EventFormatter {
1464  public function formatMessage($pCSSClass, $pMessageType, $pMessage, $pFilename, $pLinenum) {
1465    $pCSSClass = empty($pCSSClass) ? '' : "class='$pCSSClass'";
1466    $string = "<tr>" .
1467      "<td $pCSSClass>$pMessageType</td><td $pCSSClass>$pMessage</td>" .
1468      (!empty($pFilename) ? "<td $pCSSClass>$pFilename</td>" .
1469       (!empty($pLinenum) ? "<td $pCSSClass>$pLinenum</td>" : "") : "") .
1470      "</tr>\n";
1471
1472    return $string;
1473  }
1474}
1475
1476
1477function elBomb($pMessage=null) {
1478  if (func_num_args() > 0) EventLogging::stBomb($pMessage);
1479  else EventLogging::stBomb();
1480}
1481
1482function elLogMessage($errmsg, $errno=EventObject::EVO_USER_NOTICE) {
1483  EventLogging::stMessage($errmsg, $errno);
1484}
1485function elLogError($errmsg) {
1486  EventLogging::stMessage($errmsg, EventObject::EVO_USER_ERROR);
1487}
1488function elLogWarning($errmsg) {
1489  EventLogging::stMessage($errmsg, EventObject::EVO_USER_WARNING);
1490}
1491function elLogNotice($errmsg) {
1492  EventLogging::stMessage($errmsg, EventObject::EVO_USER_NOTICE);
1493}
1494function elLogDebug($errmsg) {
1495  EventLogging::stMessage($errmsg, EventObject::EVO_DEBUG);
1496}
1497function elLogInfo($errmsg) {
1498  EventLogging::stMessage($errmsg, EventObject::EVO_INFO);
1499}
1500
1501/*
1502 * Local variables:
1503 * tab-width: 2
1504 * c-basic-offset: 2
1505 * c-hanging-comment-ender-p: nil
1506 * End:
1507 */
1508
1509
Note: See TracBrowser for help on using the browser.