define('SMARTY_VERSION', '2.6.26');
define('ZEND_VERSION', '1.11.9');
define('PEAR_VERSION', '1.9.4');
-define('LOG_VERSION', '1.12.6');
+define('LOG_VERSION', '1.12.7');
define('TCPDF_VERSION', '5.9.088');
define('JQUERY_VERSION', '1.6.2');
define('JQUERY_UI_VERSION', '1.8.14');
+++ /dev/null
-<?php
-/**
- * $Header$
- * $Horde: horde/lib/Log.php,v 1.15 2000/06/29 23:39:45 jon Exp $
- *
- * @version $Revision: 310238 $
- * @package Log
- */
-
-define('PEAR_LOG_EMERG', 0); /* System is unusable */
-define('PEAR_LOG_ALERT', 1); /* Immediate action required */
-define('PEAR_LOG_CRIT', 2); /* Critical conditions */
-define('PEAR_LOG_ERR', 3); /* Error conditions */
-define('PEAR_LOG_WARNING', 4); /* Warning conditions */
-define('PEAR_LOG_NOTICE', 5); /* Normal but significant */
-define('PEAR_LOG_INFO', 6); /* Informational */
-define('PEAR_LOG_DEBUG', 7); /* Debug-level messages */
-
-define('PEAR_LOG_ALL', 0xffffffff); /* All messages */
-define('PEAR_LOG_NONE', 0x00000000); /* No message */
-
-/* Log types for PHP's native error_log() function. */
-define('PEAR_LOG_TYPE_SYSTEM', 0); /* Use PHP's system logger */
-define('PEAR_LOG_TYPE_MAIL', 1); /* Use PHP's mail() function */
-define('PEAR_LOG_TYPE_DEBUG', 2); /* Use PHP's debugging connection */
-define('PEAR_LOG_TYPE_FILE', 3); /* Append to a file */
-define('PEAR_LOG_TYPE_SAPI', 4); /* Use the SAPI logging handler */
-
-/**
- * The Log:: class implements both an abstraction for various logging
- * mechanisms and the Subject end of a Subject-Observer pattern.
- *
- * @author Chuck Hagenbuch <chuck@horde.org>
- * @author Jon Parise <jon@php.net>
- * @since Horde 1.3
- * @package Log
- */
-class Log
-{
- /**
- * Indicates whether or not the log can been opened / connected.
- *
- * @var boolean
- * @access protected
- */
- var $_opened = false;
-
- /**
- * Instance-specific unique identification number.
- *
- * @var integer
- * @access protected
- */
- var $_id = 0;
-
- /**
- * The label that uniquely identifies this set of log messages.
- *
- * @var string
- * @access protected
- */
- var $_ident = '';
-
- /**
- * The default priority to use when logging an event.
- *
- * @var integer
- * @access protected
- */
- var $_priority = PEAR_LOG_INFO;
-
- /**
- * The bitmask of allowed log levels.
- *
- * @var integer
- * @access protected
- */
- var $_mask = PEAR_LOG_ALL;
-
- /**
- * Holds all Log_observer objects that wish to be notified of new messages.
- *
- * @var array
- * @access protected
- */
- var $_listeners = array();
-
- /**
- * Starting depth to use when walking a backtrace in search of the
- * function that invoked the log system.
- *
- * @var integer
- * @access protected
- */
- var $_backtrace_depth = 0;
-
- /**
- * Maps canonical format keys to position arguments for use in building
- * "line format" strings.
- *
- * @var array
- * @access protected
- */
- var $_formatMap = array('%{timestamp}' => '%1$s',
- '%{ident}' => '%2$s',
- '%{priority}' => '%3$s',
- '%{message}' => '%4$s',
- '%{file}' => '%5$s',
- '%{line}' => '%6$s',
- '%{function}' => '%7$s',
- '%{class}' => '%8$s',
- '%\{' => '%%{');
-
- /**
- * Attempts to return a concrete Log instance of type $handler.
- *
- * @param string $handler The type of concrete Log subclass to return.
- * Attempt to dynamically include the code for
- * this subclass. Currently, valid values are
- * 'console', 'syslog', 'sql', 'file', and 'mcal'.
- *
- * @param string $name The name of the actually log file, table, or
- * other specific store to use. Defaults to an
- * empty string, with which the subclass will
- * attempt to do something intelligent.
- *
- * @param string $ident The identity reported to the log system.
- *
- * @param array $conf A hash containing any additional configuration
- * information that a subclass might need.
- *
- * @param int $level Log messages up to and including this level.
- *
- * @return object Log The newly created concrete Log instance, or
- * null on an error.
- * @access public
- * @since Log 1.0
- */
- public static function factory($handler, $name = '', $ident = '',
- $conf = array(), $level = PEAR_LOG_DEBUG)
- {
- $handler = strtolower($handler);
- $class = 'Log_' . $handler;
- $classfile = 'Log/' . $handler . '.php';
-
- /*
- * Attempt to include our version of the named class, but don't treat
- * a failure as fatal. The caller may have already included their own
- * version of the named class.
- */
- if (!class_exists($class, false)) {
- include_once $classfile;
- }
-
- /* If the class exists, return a new instance of it. */
- if (class_exists($class, false)) {
- $obj = new $class($name, $ident, $conf, $level);
- return $obj;
- }
-
- $null = null;
- return $null;
- }
-
- /**
- * Attempts to return a reference to a concrete Log instance of type
- * $handler, only creating a new instance if no log instance with the same
- * parameters currently exists.
- *
- * You should use this if there are multiple places you might create a
- * logger, you don't want to create multiple loggers, and you don't want to
- * check for the existance of one each time. The singleton pattern does all
- * the checking work for you.
- *
- * <b>You MUST call this method with the $var = &Log::singleton() syntax.
- * Without the ampersand (&) in front of the method name, you will not get
- * a reference, you will get a copy.</b>
- *
- * @param string $handler The type of concrete Log subclass to return.
- * Attempt to dynamically include the code for
- * this subclass. Currently, valid values are
- * 'console', 'syslog', 'sql', 'file', and 'mcal'.
- *
- * @param string $name The name of the actually log file, table, or
- * other specific store to use. Defaults to an
- * empty string, with which the subclass will
- * attempt to do something intelligent.
- *
- * @param string $ident The identity reported to the log system.
- *
- * @param array $conf A hash containing any additional configuration
- * information that a subclass might need.
- *
- * @param int $level Log messages up to and including this level.
- *
- * @return object Log The newly created concrete Log instance, or
- * null on an error.
- * @access public
- * @since Log 1.0
- */
- public static function singleton($handler, $name = '', $ident = '',
- $conf = array(), $level = PEAR_LOG_DEBUG)
- {
- static $instances;
- if (!isset($instances)) $instances = array();
-
- $signature = serialize(array($handler, $name, $ident, $conf, $level));
- if (!isset($instances[$signature])) {
- $instances[$signature] = Log::factory($handler, $name, $ident,
- $conf, $level);
- }
-
- return $instances[$signature];
- }
-
- /**
- * Abstract implementation of the open() method.
- * @since Log 1.0
- */
- function open()
- {
- return false;
- }
-
- /**
- * Abstract implementation of the close() method.
- * @since Log 1.0
- */
- function close()
- {
- return false;
- }
-
- /**
- * Abstract implementation of the flush() method.
- * @since Log 1.8.2
- */
- function flush()
- {
- return false;
- }
-
- /**
- * Abstract implementation of the log() method.
- * @since Log 1.0
- */
- function log($message, $priority = null)
- {
- return false;
- }
-
- /**
- * A convenience function for logging a emergency event. It will log a
- * message at the PEAR_LOG_EMERG log level.
- *
- * @param mixed $message String or object containing the message
- * to log.
- *
- * @return boolean True if the message was successfully logged.
- *
- * @access public
- * @since Log 1.7.0
- */
- function emerg($message)
- {
- return $this->log($message, PEAR_LOG_EMERG);
- }
-
- /**
- * A convenience function for logging an alert event. It will log a
- * message at the PEAR_LOG_ALERT log level.
- *
- * @param mixed $message String or object containing the message
- * to log.
- *
- * @return boolean True if the message was successfully logged.
- *
- * @access public
- * @since Log 1.7.0
- */
- function alert($message)
- {
- return $this->log($message, PEAR_LOG_ALERT);
- }
-
- /**
- * A convenience function for logging a critical event. It will log a
- * message at the PEAR_LOG_CRIT log level.
- *
- * @param mixed $message String or object containing the message
- * to log.
- *
- * @return boolean True if the message was successfully logged.
- *
- * @access public
- * @since Log 1.7.0
- */
- function crit($message)
- {
- return $this->log($message, PEAR_LOG_CRIT);
- }
-
- /**
- * A convenience function for logging a error event. It will log a
- * message at the PEAR_LOG_ERR log level.
- *
- * @param mixed $message String or object containing the message
- * to log.
- *
- * @return boolean True if the message was successfully logged.
- *
- * @access public
- * @since Log 1.7.0
- */
- function err($message)
- {
- return $this->log($message, PEAR_LOG_ERR);
- }
-
- /**
- * A convenience function for logging a warning event. It will log a
- * message at the PEAR_LOG_WARNING log level.
- *
- * @param mixed $message String or object containing the message
- * to log.
- *
- * @return boolean True if the message was successfully logged.
- *
- * @access public
- * @since Log 1.7.0
- */
- function warning($message)
- {
- return $this->log($message, PEAR_LOG_WARNING);
- }
-
- /**
- * A convenience function for logging a notice event. It will log a
- * message at the PEAR_LOG_NOTICE log level.
- *
- * @param mixed $message String or object containing the message
- * to log.
- *
- * @return boolean True if the message was successfully logged.
- *
- * @access public
- * @since Log 1.7.0
- */
- function notice($message)
- {
- return $this->log($message, PEAR_LOG_NOTICE);
- }
-
- /**
- * A convenience function for logging a information event. It will log a
- * message at the PEAR_LOG_INFO log level.
- *
- * @param mixed $message String or object containing the message
- * to log.
- *
- * @return boolean True if the message was successfully logged.
- *
- * @access public
- * @since Log 1.7.0
- */
- function info($message)
- {
- return $this->log($message, PEAR_LOG_INFO);
- }
-
- /**
- * A convenience function for logging a debug event. It will log a
- * message at the PEAR_LOG_DEBUG log level.
- *
- * @param mixed $message String or object containing the message
- * to log.
- *
- * @return boolean True if the message was successfully logged.
- *
- * @access public
- * @since Log 1.7.0
- */
- function debug($message)
- {
- return $this->log($message, PEAR_LOG_DEBUG);
- }
-
- /**
- * Returns the string representation of the message data.
- *
- * If $message is an object, _extractMessage() will attempt to extract
- * the message text using a known method (such as a PEAR_Error object's
- * getMessage() method). If a known method, cannot be found, the
- * serialized representation of the object will be returned.
- *
- * If the message data is already a string, it will be returned unchanged.
- *
- * @param mixed $message The original message data. This may be a
- * string or any object.
- *
- * @return string The string representation of the message.
- *
- * @access protected
- */
- function _extractMessage($message)
- {
- /*
- * If we've been given an object, attempt to extract the message using
- * a known method. If we can't find such a method, default to the
- * "human-readable" version of the object.
- *
- * We also use the human-readable format for arrays.
- */
- if (is_object($message)) {
- if (method_exists($message, 'getmessage')) {
- $message = $message->getMessage();
- } else if (method_exists($message, 'tostring')) {
- $message = $message->toString();
- } else if (method_exists($message, '__tostring')) {
- $message = (string)$message;
- } else {
- $message = var_export($message, true);
- }
- } else if (is_array($message)) {
- if (isset($message['message'])) {
- if (is_scalar($message['message'])) {
- $message = $message['message'];
- } else {
- $message = var_export($message['message'], true);
- }
- } else {
- $message = var_export($message, true);
- }
- } else if (is_bool($message) || $message === NULL) {
- $message = var_export($message, true);
- }
-
- /* Otherwise, we assume the message is a string. */
- return $message;
- }
-
- /**
- * Using debug_backtrace(), returns the file, line, and enclosing function
- * name of the source code context from which log() was invoked.
- *
- * @param int $depth The initial number of frames we should step
- * back into the trace.
- *
- * @return array Array containing four strings: the filename, the line,
- * the function name, and the class name from which log()
- * was called.
- *
- * @access private
- * @since Log 1.9.4
- */
- function _getBacktraceVars($depth)
- {
- /* Start by generating a backtrace from the current call (here). */
- $bt = debug_backtrace();
-
- /* Store some handy shortcuts to our previous frames. */
- $bt0 = isset($bt[$depth]) ? $bt[$depth] : null;
- $bt1 = isset($bt[$depth + 1]) ? $bt[$depth + 1] : null;
-
- /*
- * If we were ultimately invoked by the composite handler, we need to
- * increase our depth one additional level to compensate.
- */
- $class = isset($bt1['class']) ? $bt1['class'] : null;
- if ($class !== null && strcasecmp($class, 'Log_composite') == 0) {
- $depth++;
- $bt0 = isset($bt[$depth]) ? $bt[$depth] : null;
- $bt1 = isset($bt[$depth + 1]) ? $bt[$depth + 1] : null;
- $class = isset($bt1['class']) ? $bt1['class'] : null;
- }
-
- /*
- * We're interested in the frame which invoked the log() function, so
- * we need to walk back some number of frames into the backtrace. The
- * $depth parameter tells us where to start looking. We go one step
- * further back to find the name of the encapsulating function from
- * which log() was called.
- */
- $file = isset($bt0) ? $bt0['file'] : null;
- $line = isset($bt0) ? $bt0['line'] : 0;
- $func = isset($bt1) ? $bt1['function'] : null;
-
- /*
- * However, if log() was called from one of our "shortcut" functions,
- * we're going to need to go back an additional step.
- */
- if (in_array($func, array('emerg', 'alert', 'crit', 'err', 'warning',
- 'notice', 'info', 'debug'))) {
- $bt2 = isset($bt[$depth + 2]) ? $bt[$depth + 2] : null;
-
- $file = is_array($bt1) ? $bt1['file'] : null;
- $line = is_array($bt1) ? $bt1['line'] : 0;
- $func = is_array($bt2) ? $bt2['function'] : null;
- $class = isset($bt2['class']) ? $bt2['class'] : null;
- }
-
- /*
- * If we couldn't extract a function name (perhaps because we were
- * executed from the "main" context), provide a default value.
- */
- if ($func === null) {
- $func = '(none)';
- }
-
- /* Return a 4-tuple containing (file, line, function, class). */
- return array($file, $line, $func, $class);
- }
-
- /**
- * Sets the starting depth to use when walking a backtrace in search of
- * the function that invoked the log system. This is used on conjunction
- * with the 'file', 'line', 'function', and 'class' formatters.
- *
- * @param int $depth The new backtrace depth.
- *
- * @access public
- * @since Log 1.12.7
- */
- public function setBacktraceDepth($depth)
- {
- $this->_backtrace_depth = $depth;
- }
-
- /**
- * Produces a formatted log line based on a format string and a set of
- * variables representing the current log record and state.
- *
- * @return string Formatted log string.
- *
- * @access protected
- * @since Log 1.9.4
- */
- function _format($format, $timestamp, $priority, $message)
- {
- /*
- * If the format string references any of the backtrace-driven
- * variables (%5 %6,%7,%8), generate the backtrace and fetch them.
- */
- if (preg_match('/%[5678]/', $format)) {
- /* Plus 2 to account for our internal function calls. */
- $d = $this->_backtrace_depth + 2;
- list($file, $line, $func, $class) = $this->_getBacktraceVars($d);
- }
-
- /*
- * Build the formatted string. We use the sprintf() function's
- * "argument swapping" capability to dynamically select and position
- * the variables which will ultimately appear in the log string.
- */
- return sprintf($format,
- $timestamp,
- $this->_ident,
- $this->priorityToString($priority),
- $message,
- isset($file) ? $file : '',
- isset($line) ? $line : '',
- isset($func) ? $func : '',
- isset($class) ? $class : '');
- }
-
- /**
- * Returns the string representation of a PEAR_LOG_* integer constant.
- *
- * @param int $priority A PEAR_LOG_* integer constant.
- *
- * @return string The string representation of $level.
- *
- * @access public
- * @since Log 1.0
- */
- function priorityToString($priority)
- {
- $levels = array(
- PEAR_LOG_EMERG => 'emergency',
- PEAR_LOG_ALERT => 'alert',
- PEAR_LOG_CRIT => 'critical',
- PEAR_LOG_ERR => 'error',
- PEAR_LOG_WARNING => 'warning',
- PEAR_LOG_NOTICE => 'notice',
- PEAR_LOG_INFO => 'info',
- PEAR_LOG_DEBUG => 'debug'
- );
-
- return $levels[$priority];
- }
-
- /**
- * Returns the the PEAR_LOG_* integer constant for the given string
- * representation of a priority name. This function performs a
- * case-insensitive search.
- *
- * @param string $name String containing a priority name.
- *
- * @return string The PEAR_LOG_* integer contstant corresponding
- * the the specified priority name.
- *
- * @access public
- * @since Log 1.9.0
- */
- function stringToPriority($name)
- {
- $levels = array(
- 'emergency' => PEAR_LOG_EMERG,
- 'alert' => PEAR_LOG_ALERT,
- 'critical' => PEAR_LOG_CRIT,
- 'error' => PEAR_LOG_ERR,
- 'warning' => PEAR_LOG_WARNING,
- 'notice' => PEAR_LOG_NOTICE,
- 'info' => PEAR_LOG_INFO,
- 'debug' => PEAR_LOG_DEBUG
- );
-
- return $levels[strtolower($name)];
- }
-
- /**
- * Calculate the log mask for the given priority.
- *
- * This method may be called statically.
- *
- * @param integer $priority The priority whose mask will be calculated.
- *
- * @return integer The calculated log mask.
- *
- * @access public
- * @since Log 1.7.0
- */
- public static function MASK($priority)
- {
- return (1 << $priority);
- }
-
- /**
- * Calculate the log mask for all priorities up to the given priority.
- *
- * This method may be called statically.
- *
- * @param integer $priority The maximum priority covered by this mask.
- *
- * @return integer The resulting log mask.
- *
- * @access public
- * @since Log 1.7.0
- *
- * @deprecated deprecated since Log 1.9.4; use Log::MAX() instead
- */
- public static function UPTO($priority)
- {
- return Log::MAX($priority);
- }
-
- /**
- * Calculate the log mask for all priorities greater than or equal to the
- * given priority. In other words, $priority will be the lowest priority
- * matched by the resulting mask.
- *
- * This method may be called statically.
- *
- * @param integer $priority The minimum priority covered by this mask.
- *
- * @return integer The resulting log mask.
- *
- * @access public
- * @since Log 1.9.4
- */
- public static function MIN($priority)
- {
- return PEAR_LOG_ALL ^ ((1 << $priority) - 1);
- }
-
- /**
- * Calculate the log mask for all priorities less than or equal to the
- * given priority. In other words, $priority will be the highests priority
- * matched by the resulting mask.
- *
- * This method may be called statically.
- *
- * @param integer $priority The maximum priority covered by this mask.
- *
- * @return integer The resulting log mask.
- *
- * @access public
- * @since Log 1.9.4
- */
- public static function MAX($priority)
- {
- return ((1 << ($priority + 1)) - 1);
- }
-
- /**
- * Set and return the level mask for the current Log instance.
- *
- * @param integer $mask A bitwise mask of log levels.
- *
- * @return integer The current level mask.
- *
- * @access public
- * @since Log 1.7.0
- */
- function setMask($mask)
- {
- $this->_mask = $mask;
-
- return $this->_mask;
- }
-
- /**
- * Returns the current level mask.
- *
- * @return interger The current level mask.
- *
- * @access public
- * @since Log 1.7.0
- */
- function getMask()
- {
- return $this->_mask;
- }
-
- /**
- * Check if the given priority is included in the current level mask.
- *
- * @param integer $priority The priority to check.
- *
- * @return boolean True if the given priority is included in the current
- * log mask.
- *
- * @access protected
- * @since Log 1.7.0
- */
- function _isMasked($priority)
- {
- return (Log::MASK($priority) & $this->_mask);
- }
-
- /**
- * Returns the current default priority.
- *
- * @return integer The current default priority.
- *
- * @access public
- * @since Log 1.8.4
- */
- function getPriority()
- {
- return $this->_priority;
- }
-
- /**
- * Sets the default priority to the specified value.
- *
- * @param integer $priority The new default priority.
- *
- * @access public
- * @since Log 1.8.4
- */
- function setPriority($priority)
- {
- $this->_priority = $priority;
- }
-
- /**
- * Adds a Log_observer instance to the list of observers that are listening
- * for messages emitted by this Log instance.
- *
- * @param object $observer The Log_observer instance to attach as a
- * listener.
- *
- * @param boolean True if the observer is successfully attached.
- *
- * @access public
- * @since Log 1.0
- */
- function attach(&$observer)
- {
- if (!is_a($observer, 'Log_observer')) {
- return false;
- }
-
- $this->_listeners[$observer->_id] = &$observer;
-
- return true;
- }
-
- /**
- * Removes a Log_observer instance from the list of observers.
- *
- * @param object $observer The Log_observer instance to detach from
- * the list of listeners.
- *
- * @param boolean True if the observer is successfully detached.
- *
- * @access public
- * @since Log 1.0
- */
- function detach($observer)
- {
- if (!is_a($observer, 'Log_observer') ||
- !isset($this->_listeners[$observer->_id])) {
- return false;
- }
-
- unset($this->_listeners[$observer->_id]);
-
- return true;
- }
-
- /**
- * Informs each registered observer instance that a new message has been
- * logged.
- *
- * @param array $event A hash describing the log event.
- *
- * @access protected
- */
- function _announce($event)
- {
- foreach ($this->_listeners as $id => $listener) {
- if ($event['priority'] <= $this->_listeners[$id]->_priority) {
- $this->_listeners[$id]->notify($event);
- }
- }
- }
-
- /**
- * Indicates whether this is a composite class.
- *
- * @return boolean True if this is a composite class.
- *
- * @access public
- * @since Log 1.0
- */
- function isComposite()
- {
- return false;
- }
-
- /**
- * Sets this Log instance's identification string.
- *
- * @param string $ident The new identification string.
- *
- * @access public
- * @since Log 1.6.3
- */
- function setIdent($ident)
- {
- $this->_ident = $ident;
- }
-
- /**
- * Returns the current identification string.
- *
- * @return string The current Log instance's identification string.
- *
- * @access public
- * @since Log 1.6.3
- */
- function getIdent()
- {
- return $this->_ident;
- }
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- * $Horde: horde/lib/Log/composite.php,v 1.2 2000/06/28 21:36:13 jon Exp $
- *
- * @version $Revision: 305990 $
- * @package Log
- */
-
-/**
- * The Log_composite:: class implements a Composite pattern which
- * allows multiple Log implementations to receive the same events.
- *
- * @author Chuck Hagenbuch <chuck@horde.org>
- * @author Jon Parise <jon@php.net>
- *
- * @since Horde 1.3
- * @since Log 1.0
- * @package Log
- *
- * @example composite.php Using the composite handler.
- */
-class Log_composite extends Log
-{
- /**
- * Array holding all of the Log instances to which log events should be
- * sent.
- *
- * @var array
- * @access private
- */
- var $_children = array();
-
-
- /**
- * Constructs a new composite Log object.
- *
- * @param boolean $name This parameter is ignored.
- * @param boolean $ident This parameter is ignored.
- * @param boolean $conf This parameter is ignored.
- * @param boolean $level This parameter is ignored.
- *
- * @access public
- */
- function Log_composite($name, $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- $this->_ident = $ident;
- }
-
- /**
- * Opens all of the child instances.
- *
- * @return True if all of the child instances were successfully opened.
- *
- * @access public
- */
- function open()
- {
- /* Attempt to open each of our children. */
- $this->_opened = true;
- foreach ($this->_children as $child) {
- $this->_opened &= $child->open();
- }
-
- /* If all children were opened, return success. */
- return $this->_opened;
- }
-
- /**
- * Closes all open child instances.
- *
- * @return True if all of the opened child instances were successfully
- * closed.
- *
- * @access public
- */
- function close()
- {
- /* If we haven't been opened, there's nothing more to do. */
- if (!$this->_opened) {
- return true;
- }
-
- /* Attempt to close each of our children. */
- $closed = true;
- foreach ($this->_children as $child) {
- if ($child->_opened) {
- $closed &= $child->close();
- }
- }
-
- /* Clear the opened state for consistency. */
- $this->_opened = false;
-
- /* If all children were closed, return success. */
- return $closed;
- }
-
- /**
- * Flushes all child instances. It is assumed that all of the children
- * have been successfully opened.
- *
- * @return True if all of the child instances were successfully flushed.
- *
- * @access public
- * @since Log 1.8.2
- */
- function flush()
- {
- /* Attempt to flush each of our children. */
- $flushed = true;
- foreach ($this->_children as $child) {
- $flushed &= $child->flush();
- }
-
- /* If all children were flushed, return success. */
- return $flushed;
- }
-
- /**
- * Sends $message and $priority to each child of this composite. If the
- * appropriate children aren't already open, they will be opened here.
- *
- * @param mixed $message String or object containing the message
- * to log.
- * @param string $priority (optional) The priority of the message.
- * Valid values are: PEAR_LOG_EMERG,
- * PEAR_LOG_ALERT, PEAR_LOG_CRIT,
- * PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and
- * PEAR_LOG_DEBUG.
- *
- * @return boolean True if the entry is successfully logged.
- *
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /*
- * Abort early if the priority is above the composite handler's
- * maximum logging level.
- *
- * XXX: Consider whether or not introducing this change would break
- * backwards compatibility. Some users may be expecting composite
- * handlers to pass on all events to their children regardless of
- * their own priority.
- */
- #if (!$this->_isMasked($priority)) {
- # return false;
- #}
-
- /*
- * Iterate over all of our children. If a unopened child will respond
- * to this log event, we attempt to open it immediately. The composite
- * handler's opened state will be enabled as soon as the first child
- * handler is successfully opened.
- *
- * We track an overall success state that indicates whether or not all
- * of the relevant child handlers were opened and successfully logged
- * the event. If one handler fails, we still attempt any remaining
- * children, but we consider the overall result a failure.
- */
- $success = true;
- foreach ($this->_children as $child) {
- /* If this child won't respond to this event, skip it. */
- if (!$child->_isMasked($priority)) {
- continue;
- }
-
- /* If this child has yet to be opened, attempt to do so now. */
- if (!$child->_opened) {
- $success &= $child->open();
-
- /*
- * If we've successfully opened our first handler, the
- * composite handler itself is considered to be opened.
- */
- if (!$this->_opened && $success) {
- $this->_opened = true;
- }
- }
-
- /* Finally, attempt to log the message to the child handler. */
- if ($child->_opened) {
- $success &= $child->log($message, $priority);
- }
- }
-
- /* Notify the observers. */
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- /* Return success if all of the open children logged the event. */
- return $success;
- }
-
- /**
- * Returns true if this is a composite.
- *
- * @return boolean True if this is a composite class.
- *
- * @access public
- */
- function isComposite()
- {
- return true;
- }
-
- /**
- * Sets this identification string for all of this composite's children.
- *
- * @param string $ident The new identification string.
- *
- * @access public
- * @since Log 1.6.7
- */
- function setIdent($ident)
- {
- /* Call our base class's setIdent() method. */
- parent::setIdent($ident);
-
- /* ... and then call setIdent() on all of our children. */
- foreach ($this->_children as $child) {
- $child->setIdent($ident);
- }
- }
-
- /**
- * Adds a Log instance to the list of children.
- *
- * @param object $child The Log instance to add.
- *
- * @return boolean True if the Log instance was successfully added.
- *
- * @access public
- */
- function addChild(&$child)
- {
- /* Make sure this is a Log instance. */
- if (!is_a($child, 'Log')) {
- return false;
- }
-
- $this->_children[$child->_id] = $child;
-
- return true;
- }
-
- /**
- * Removes a Log instance from the list of children.
- *
- * @param object $child The Log instance to remove.
- *
- * @return boolean True if the Log instance was successfully removed.
- *
- * @access public
- */
- function removeChild($child)
- {
- if (!is_a($child, 'Log') || !isset($this->_children[$child->_id])) {
- return false;
- }
-
- unset($this->_children[$child->_id]);
-
- return true;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- *
- * @version $Revision: 306594 $
- * @package Log
- */
-
-/**
- * The Log_console class is a concrete implementation of the Log::
- * abstract class which writes message to the text console.
- *
- * @author Jon Parise <jon@php.net>
- * @since Log 1.1
- * @package Log
- *
- * @example console.php Using the console handler.
- */
-class Log_console extends Log
-{
- /**
- * Handle to the current output stream.
- * @var resource
- * @access private
- */
- var $_stream = null;
-
- /**
- * Is this object responsible for closing the stream resource?
- * @var bool
- * @access private
- */
- var $_closeResource = false;
-
- /**
- * Should the output be buffered or displayed immediately?
- * @var string
- * @access private
- */
- var $_buffering = false;
-
- /**
- * String holding the buffered output.
- * @var string
- * @access private
- */
- var $_buffer = '';
-
- /**
- * String containing the format of a log line.
- * @var string
- * @access private
- */
- var $_lineFormat = '%1$s %2$s [%3$s] %4$s';
-
- /**
- * String containing the timestamp format. It will be passed directly to
- * strftime(). Note that the timestamp string will generated using the
- * current locale.
- * @var string
- * @access private
- */
- var $_timeFormat = '%b %d %H:%M:%S';
-
- /**
- * Constructs a new Log_console object.
- *
- * @param string $name Ignored.
- * @param string $ident The identity string.
- * @param array $conf The configuration array.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_console($name, $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- $this->_id = md5(microtime());
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
-
- if (!empty($conf['stream'])) {
- $this->_stream = $conf['stream'];
- } elseif (defined('STDOUT')) {
- $this->_stream = STDOUT;
- } else {
- $this->_stream = fopen('php://output', 'a');
- $this->_closeResource = true;
- }
-
- if (isset($conf['buffering'])) {
- $this->_buffering = $conf['buffering'];
- }
-
- if (!empty($conf['lineFormat'])) {
- $this->_lineFormat = str_replace(array_keys($this->_formatMap),
- array_values($this->_formatMap),
- $conf['lineFormat']);
- }
-
- if (!empty($conf['timeFormat'])) {
- $this->_timeFormat = $conf['timeFormat'];
- }
-
- /*
- * If output buffering has been requested, we need to register a
- * shutdown function that will dump the buffer upon termination.
- */
- if ($this->_buffering) {
- register_shutdown_function(array(&$this, '_Log_console'));
- }
- }
-
- /**
- * Destructor
- */
- function _Log_console()
- {
- $this->close();
- }
-
- /**
- * Open the output stream.
- *
- * @access public
- * @since Log 1.9.7
- */
- function open()
- {
- $this->_opened = true;
- return true;
- }
-
- /**
- * Closes the output stream.
- *
- * This results in a call to flush().
- *
- * @access public
- * @since Log 1.9.0
- */
- function close()
- {
- $this->flush();
- $this->_opened = false;
- if ($this->_closeResource === true && is_resource($this->_stream)) {
- fclose($this->_stream);
- }
- return true;
- }
-
- /**
- * Flushes all pending ("buffered") data to the output stream.
- *
- * @access public
- * @since Log 1.8.2
- */
- function flush()
- {
- /*
- * If output buffering is enabled, dump the contents of the buffer to
- * the output stream.
- */
- if ($this->_buffering && (strlen($this->_buffer) > 0)) {
- fwrite($this->_stream, $this->_buffer);
- $this->_buffer = '';
- }
-
- if (is_resource($this->_stream)) {
- return fflush($this->_stream);
- }
-
- return false;
- }
-
- /**
- * Writes $message to the text console. Also, passes the message
- * along to any Log_observer instances that are observing this Log.
- *
- * @param mixed $message String or object containing the message to log.
- * @param string $priority The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* Extract the string representation of the message. */
- $message = $this->_extractMessage($message);
-
- /* Build the string containing the complete log line. */
- $line = $this->_format($this->_lineFormat,
- strftime($this->_timeFormat),
- $priority, $message) . "\n";
-
- /*
- * If buffering is enabled, append this line to the output buffer.
- * Otherwise, print the line to the output stream immediately.
- */
- if ($this->_buffering) {
- $this->_buffer .= $line;
- } else {
- fwrite($this->_stream, $line);
- }
-
- /* Notify observers about this log message. */
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return true;
- }
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- *
- * @version $Revision: 250926 $
- * @package Log
- */
-
-/**
- * The Log_daemon class is a concrete implementation of the Log::
- * abstract class which sends messages to syslog daemon on UNIX-like machines.
- * This class uses the syslog protocol: http://www.ietf.org/rfc/rfc3164.txt
- *
- * @author Bart van der Schans <schans@dds.nl>
- * @version $Revision: 250926 $
- * @package Log
- */
-class Log_daemon extends Log
-{
- /**
- * Integer holding the log facility to use.
- * @var string
- */
- var $_name = LOG_DAEMON;
-
- /**
- * Var holding the resource pointer to the socket
- * @var resource
- */
- var $_socket;
-
- /**
- * The ip address or servername
- * @see http://www.php.net/manual/en/transports.php
- * @var string
- */
- var $_ip = '127.0.0.1';
-
- /**
- * Protocol to use (tcp, udp, etc.)
- * @see http://www.php.net/manual/en/transports.php
- * @var string
- */
- var $_proto = 'udp';
-
- /**
- * Port to connect to
- * @var int
- */
- var $_port = 514;
-
- /**
- * Maximum message length in bytes
- * @var int
- */
- var $_maxsize = 4096;
-
- /**
- * Socket timeout in seconds
- * @var int
- */
- var $_timeout = 1;
-
-
- /**
- * Constructs a new syslog object.
- *
- * @param string $name The syslog facility.
- * @param string $ident The identity string.
- * @param array $conf The configuration array.
- * @param int $maxLevel Maximum level at which to log.
- * @access public
- */
- function Log_daemon($name, $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- /* Ensure we have a valid integer value for $name. */
- if (empty($name) || !is_int($name)) {
- $name = LOG_SYSLOG;
- }
-
- $this->_id = md5(microtime());
- $this->_name = $name;
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
-
- if (isset($conf['ip'])) {
- $this->_ip = $conf['ip'];
- }
- if (isset($conf['proto'])) {
- $this->_proto = $conf['proto'];
- }
- if (isset($conf['port'])) {
- $this->_port = $conf['port'];
- }
- if (isset($conf['maxsize'])) {
- $this->_maxsize = $conf['maxsize'];
- }
- if (isset($conf['timeout'])) {
- $this->_timeout = $conf['timeout'];
- }
- $this->_proto = $this->_proto . '://';
-
- register_shutdown_function(array(&$this, '_Log_daemon'));
- }
-
- /**
- * Destructor.
- *
- * @access private
- */
- function _Log_daemon()
- {
- $this->close();
- }
-
- /**
- * Opens a connection to the system logger, if it has not already
- * been opened. This is implicitly called by log(), if necessary.
- * @access public
- */
- function open()
- {
- if (!$this->_opened) {
- $this->_opened = (bool)($this->_socket = @fsockopen(
- $this->_proto . $this->_ip,
- $this->_port,
- $errno,
- $errstr,
- $this->_timeout));
- }
- return $this->_opened;
- }
-
- /**
- * Closes the connection to the system logger, if it is open.
- * @access public
- */
- function close()
- {
- if ($this->_opened) {
- $this->_opened = false;
- return fclose($this->_socket);
- }
- return true;
- }
-
- /**
- * Sends $message to the currently open syslog connection. Calls
- * open() if necessary. Also passes the message along to any Log_observer
- * instances that are observing this Log.
- *
- * @param string $message The textual message to be logged.
- * @param int $priority (optional) The priority of the message. Valid
- * values are: LOG_EMERG, LOG_ALERT, LOG_CRIT,
- * LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO,
- * and LOG_DEBUG. The default is LOG_INFO.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* If the connection isn't open and can't be opened, return failure. */
- if (!$this->_opened && !$this->open()) {
- return false;
- }
-
- /* Extract the string representation of the message. */
- $message = $this->_extractMessage($message);
-
- /* Set the facility level. */
- $facility_level = intval($this->_name) +
- intval($this->_toSyslog($priority));
-
- /* Prepend ident info. */
- if (!empty($this->_ident)) {
- $message = $this->_ident . ' ' . $message;
- }
-
- /* Check for message length. */
- if (strlen($message) > $this->_maxsize) {
- $message = substr($message, 0, ($this->_maxsize) - 10) . ' [...]';
- }
-
- /* Write to socket. */
- fwrite($this->_socket, '<' . $facility_level . '>' . $message . "\n");
-
- $this->_announce(array('priority' => $priority, 'message' => $message));
- }
-
- /**
- * Converts a PEAR_LOG_* constant into a syslog LOG_* constant.
- *
- * This function exists because, under Windows, not all of the LOG_*
- * constants have unique values. Instead, the PEAR_LOG_* were introduced
- * for global use, with the conversion to the LOG_* constants kept local to
- * to the syslog driver.
- *
- * @param int $priority PEAR_LOG_* value to convert to LOG_* value.
- *
- * @return The LOG_* representation of $priority.
- *
- * @access private
- */
- function _toSyslog($priority)
- {
- static $priorities = array(
- PEAR_LOG_EMERG => LOG_EMERG,
- PEAR_LOG_ALERT => LOG_ALERT,
- PEAR_LOG_CRIT => LOG_CRIT,
- PEAR_LOG_ERR => LOG_ERR,
- PEAR_LOG_WARNING => LOG_WARNING,
- PEAR_LOG_NOTICE => LOG_NOTICE,
- PEAR_LOG_INFO => LOG_INFO,
- PEAR_LOG_DEBUG => LOG_DEBUG
- );
-
- /* If we're passed an unknown priority, default to LOG_INFO. */
- if (!is_int($priority) || !in_array($priority, $priorities)) {
- return LOG_INFO;
- }
-
- return $priorities[$priority];
- }
-
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- *
- * @version $Revision: 305290 $
- * @package Log
- */
-
-/**
- * The Log_display class is a concrete implementation of the Log::
- * abstract class which writes message into browser in usual PHP maner.
- * This may be useful because when you use PEAR::setErrorHandling in
- * PEAR_ERROR_CALLBACK mode error messages are not displayed by
- * PHP error handler.
- *
- * @author Paul Yanchenko <pusher@inaco.ru>
- * @since Log 1.8.0
- * @package Log
- *
- * @example display.php Using the display handler.
- */
-class Log_display extends Log
-{
- /**
- * String containing the format of a log line.
- * @var string
- * @access private
- */
- var $_lineFormat = '<b>%3$s</b>: %4$s';
-
- /**
- * String containing the timestamp format. It will be passed directly to
- * strftime(). Note that the timestamp string will generated using the
- * current locale.
- * @var string
- * @access private
- */
- var $_timeFormat = '%b %d %H:%M:%S';
-
- /**
- * Flag indicating whether raw message text should be passed directly to
- * the log system. Otherwise, the text will be converted to an HTML-safe
- * representation.
- * @var boolean
- * @access private
- */
- var $_rawText = false;
-
- /**
- * Constructs a new Log_display object.
- *
- * @param string $name Ignored.
- * @param string $ident The identity string.
- * @param array $conf The configuration array.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_display($name = '', $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- $this->_id = md5(microtime());
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
-
- /* Start by configuring the line format. */
- if (!empty($conf['lineFormat'])) {
- $this->_lineFormat = str_replace(array_keys($this->_formatMap),
- array_values($this->_formatMap),
- $conf['lineFormat']);
- }
-
- /* We may need to prepend a string to our line format. */
- $prepend = null;
- if (isset($conf['error_prepend'])) {
- $prepend = $conf['error_prepend'];
- } else {
- $prepend = ini_get('error_prepend_string');
- }
- if (!empty($prepend)) {
- $this->_lineFormat = $prepend . $this->_lineFormat;
- }
-
- /* We may also need to append a string to our line format. */
- $append = null;
- if (isset($conf['error_append'])) {
- $append = $conf['error_append'];
- } else {
- $append = ini_get('error_append_string');
- }
- if (!empty($append)) {
- $this->_lineFormat .= $append;
- }
-
- /* Lastly, the line ending sequence is also configurable. */
- if (isset($conf['linebreak'])) {
- $this->_lineFormat .= $conf['linebreak'];
- } else {
- $this->_lineFormat .= "<br />\n";
- }
-
- /* The user can also change the time format. */
- if (!empty($conf['timeFormat'])) {
- $this->_timeFormat = $conf['timeFormat'];
- }
-
- /* Message text conversion can be disabled. */
- if (isset($conf['rawText'])) {
- $this->_rawText = $conf['rawText'];
- }
- }
-
- /**
- * Opens the display handler.
- *
- * @access public
- * @since Log 1.9.6
- */
- function open()
- {
- $this->_opened = true;
- return true;
- }
-
- /**
- * Closes the display handler.
- *
- * @access public
- * @since Log 1.9.6
- */
- function close()
- {
- $this->_opened = false;
- return true;
- }
-
- /**
- * Writes $message to the text browser. Also, passes the message
- * along to any Log_observer instances that are observing this Log.
- *
- * @param mixed $message String or object containing the message to log.
- * @param string $priority The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* Extract the string representation of the message. */
- $message = $this->_extractMessage($message);
-
- /* Convert the message to an HTML-friendly represention unless raw
- * text has been requested. */
- if ($this->_rawText === false) {
- $message = nl2br(htmlspecialchars($message));
- }
-
- /* Build and output the complete log line. */
- echo $this->_format($this->_lineFormat,
- strftime($this->_timeFormat),
- $priority,
- $message);
-
- /* Notify observers about this log message. */
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return true;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- *
- * @version $Revision: 293927 $
- * @package Log
- */
-
-/**
- * The Log_error_log class is a concrete implementation of the Log abstract
- * class that logs messages using PHP's error_log() function.
- *
- * @author Jon Parise <jon@php.net>
- * @since Log 1.7.0
- * @package Log
- *
- * @example error_log.php Using the error_log handler.
- */
-class Log_error_log extends Log
-{
- /**
- * The error_log() log type.
- * @var integer
- * @access private
- */
- var $_type = PEAR_LOG_TYPE_SYSTEM;
-
- /**
- * The type-specific destination value.
- * @var string
- * @access private
- */
- var $_destination = '';
-
- /**
- * Additional headers to pass to the mail() function when the
- * PEAR_LOG_TYPE_MAIL type is used.
- * @var string
- * @access private
- */
- var $_extra_headers = '';
-
- /**
- * String containing the format of a log line.
- * @var string
- * @access private
- */
- var $_lineFormat = '%2$s: %4$s';
-
- /**
- * String containing the timestamp format. It will be passed directly to
- * strftime(). Note that the timestamp string will generated using the
- * current locale.
- * @var string
- * @access private
- */
- var $_timeFormat = '%b %d %H:%M:%S';
-
- /**
- * Constructs a new Log_error_log object.
- *
- * @param string $name One of the PEAR_LOG_TYPE_* constants.
- * @param string $ident The identity string.
- * @param array $conf The configuration array.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_error_log($name, $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- $this->_id = md5(microtime());
- $this->_type = $name;
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
-
- if (!empty($conf['destination'])) {
- $this->_destination = $conf['destination'];
- }
-
- if (!empty($conf['extra_headers'])) {
- $this->_extra_headers = $conf['extra_headers'];
- }
-
- if (!empty($conf['lineFormat'])) {
- $this->_lineFormat = str_replace(array_keys($this->_formatMap),
- array_values($this->_formatMap),
- $conf['lineFormat']);
- }
-
- if (!empty($conf['timeFormat'])) {
- $this->_timeFormat = $conf['timeFormat'];
- }
- }
-
- /**
- * Opens the handler.
- *
- * @access public
- * @since Log 1.9.6
- */
- function open()
- {
- $this->_opened = true;
- return true;
- }
-
- /**
- * Closes the handler.
- *
- * @access public
- * @since Log 1.9.6
- */
- function close()
- {
- $this->_opened = false;
- return true;
- }
-
- /**
- * Logs $message using PHP's error_log() function. The message is also
- * passed along to any Log_observer instances that are observing this Log.
- *
- * @param mixed $message String or object containing the message to log.
- * @param string $priority The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* Extract the string representation of the message. */
- $message = $this->_extractMessage($message);
-
- /* Build the string containing the complete log line. */
- $line = $this->_format($this->_lineFormat,
- strftime($this->_timeFormat),
- $priority, $message);
-
- /* Pass the log line and parameters to the error_log() function. */
- $success = error_log($line, $this->_type, $this->_destination,
- $this->_extra_headers);
-
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return $success;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- *
- * @version $Revision: 224513 $
- * @package Log
- */
-
-/**
- * The Log_file class is a concrete implementation of the Log abstract
- * class that logs messages to a text file.
- *
- * @author Jon Parise <jon@php.net>
- * @author Roman Neuhauser <neuhauser@bellavista.cz>
- * @since Log 1.0
- * @package Log
- *
- * @example file.php Using the file handler.
- */
-class Log_file extends Log
-{
- /**
- * String containing the name of the log file.
- * @var string
- * @access private
- */
- var $_filename = 'php.log';
-
- /**
- * Handle to the log file.
- * @var resource
- * @access private
- */
- var $_fp = false;
-
- /**
- * Should new log entries be append to an existing log file, or should the
- * a new log file overwrite an existing one?
- * @var boolean
- * @access private
- */
- var $_append = true;
-
- /**
- * Should advisory file locking (i.e., flock()) be used?
- * @var boolean
- * @access private
- */
- var $_locking = false;
-
- /**
- * Integer (in octal) containing the log file's permissions mode.
- * @var integer
- * @access private
- */
- var $_mode = 0644;
-
- /**
- * Integer (in octal) specifying the file permission mode that will be
- * used when creating directories that do not already exist.
- * @var integer
- * @access private
- */
- var $_dirmode = 0755;
-
- /**
- * String containing the format of a log line.
- * @var string
- * @access private
- */
- var $_lineFormat = '%1$s %2$s [%3$s] %4$s';
-
- /**
- * String containing the timestamp format. It will be passed directly to
- * strftime(). Note that the timestamp string will generated using the
- * current locale.
- * @var string
- * @access private
- */
- var $_timeFormat = '%b %d %H:%M:%S';
-
- /**
- * String containing the end-on-line character sequence.
- * @var string
- * @access private
- */
- var $_eol = "\n";
-
- /**
- * Constructs a new Log_file object.
- *
- * @param string $name Ignored.
- * @param string $ident The identity string.
- * @param array $conf The configuration array.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_file($name, $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- $this->_id = md5(microtime());
- $this->_filename = $name;
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
-
- if (isset($conf['append'])) {
- $this->_append = $conf['append'];
- }
-
- if (isset($conf['locking'])) {
- $this->_locking = $conf['locking'];
- }
-
- if (!empty($conf['mode'])) {
- if (is_string($conf['mode'])) {
- $this->_mode = octdec($conf['mode']);
- } else {
- $this->_mode = $conf['mode'];
- }
- }
-
- if (!empty($conf['dirmode'])) {
- if (is_string($conf['dirmode'])) {
- $this->_dirmode = octdec($conf['dirmode']);
- } else {
- $this->_dirmode = $conf['dirmode'];
- }
- }
-
- if (!empty($conf['lineFormat'])) {
- $this->_lineFormat = str_replace(array_keys($this->_formatMap),
- array_values($this->_formatMap),
- $conf['lineFormat']);
- }
-
- if (!empty($conf['timeFormat'])) {
- $this->_timeFormat = $conf['timeFormat'];
- }
-
- if (!empty($conf['eol'])) {
- $this->_eol = $conf['eol'];
- } else {
- $this->_eol = (strstr(PHP_OS, 'WIN')) ? "\r\n" : "\n";
- }
-
- register_shutdown_function(array(&$this, '_Log_file'));
- }
-
- /**
- * Destructor
- */
- function _Log_file()
- {
- if ($this->_opened) {
- $this->close();
- }
- }
-
- /**
- * Creates the given directory path. If the parent directories don't
- * already exist, they will be created, too.
- *
- * This implementation is inspired by Python's os.makedirs function.
- *
- * @param string $path The full directory path to create.
- * @param integer $mode The permissions mode with which the
- * directories will be created.
- *
- * @return True if the full path is successfully created or already
- * exists.
- *
- * @access private
- */
- function _mkpath($path, $mode = 0700)
- {
- /* Separate the last pathname component from the rest of the path. */
- $head = dirname($path);
- $tail = basename($path);
-
- /* Make sure we've split the path into two complete components. */
- if (empty($tail)) {
- $head = dirname($path);
- $tail = basename($path);
- }
-
- /* Recurse up the path if our current segment does not exist. */
- if (!empty($head) && !empty($tail) && !is_dir($head)) {
- $this->_mkpath($head, $mode);
- }
-
- /* Create this segment of the path. */
- return @mkdir($head, $mode);
- }
-
- /**
- * Opens the log file for output. If the specified log file does not
- * already exist, it will be created. By default, new log entries are
- * appended to the end of the log file.
- *
- * This is implicitly called by log(), if necessary.
- *
- * @access public
- */
- function open()
- {
- if (!$this->_opened) {
- /* If the log file's directory doesn't exist, create it. */
- if (!is_dir(dirname($this->_filename))) {
- $this->_mkpath($this->_filename, $this->_dirmode);
- }
-
- /* Determine whether the log file needs to be created. */
- $creating = !file_exists($this->_filename);
-
- /* Obtain a handle to the log file. */
- $this->_fp = fopen($this->_filename, ($this->_append) ? 'a' : 'w');
-
- /* We consider the file "opened" if we have a valid file pointer. */
- $this->_opened = ($this->_fp !== false);
-
- /* Attempt to set the file's permissions if we just created it. */
- if ($creating && $this->_opened) {
- chmod($this->_filename, $this->_mode);
- }
- }
-
- return $this->_opened;
- }
-
- /**
- * Closes the log file if it is open.
- *
- * @access public
- */
- function close()
- {
- /* If the log file is open, close it. */
- if ($this->_opened && fclose($this->_fp)) {
- $this->_opened = false;
- }
-
- return ($this->_opened === false);
- }
-
- /**
- * Flushes all pending data to the file handle.
- *
- * @access public
- * @since Log 1.8.2
- */
- function flush()
- {
- if (is_resource($this->_fp)) {
- return fflush($this->_fp);
- }
-
- return false;
- }
-
- /**
- * Logs $message to the output window. The message is also passed along
- * to any Log_observer instances that are observing this Log.
- *
- * @param mixed $message String or object containing the message to log.
- * @param string $priority The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* If the log file isn't already open, open it now. */
- if (!$this->_opened && !$this->open()) {
- return false;
- }
-
- /* Extract the string representation of the message. */
- $message = $this->_extractMessage($message);
-
- /* Build the string containing the complete log line. */
- $line = $this->_format($this->_lineFormat,
- strftime($this->_timeFormat),
- $priority, $message) . $this->_eol;
-
- /* If locking is enabled, acquire an exclusive lock on the file. */
- if ($this->_locking) {
- flock($this->_fp, LOCK_EX);
- }
-
- /* Write the log line to the log file. */
- $success = (fwrite($this->_fp, $line) !== false);
-
- /* Unlock the file now that we're finished writing to it. */
- if ($this->_locking) {
- flock($this->_fp, LOCK_UN);
- }
-
- /* Notify observers about this log message. */
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return $success;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- *
- * @version $Revision: 306582 $
- * @package Log
- */
-
-/**
- * The Log_firebug class is a concrete implementation of the Log::
- * abstract class which writes message into Firebug console.
- *
- * http://www.getfirebug.com/
- *
- * @author Mika Tuupola <tuupola@appelsiini.net>
- * @since Log 1.9.11
- * @package Log
- *
- * @example firebug.php Using the firebug handler.
- */
-class Log_firebug extends Log
-{
- /**
- * Should the output be buffered or displayed immediately?
- * @var string
- * @access private
- */
- var $_buffering = false;
-
- /**
- * String holding the buffered output.
- * @var string
- * @access private
- */
- var $_buffer = array();
-
- /**
- * String containing the format of a log line.
- * @var string
- * @access private
- */
- var $_lineFormat = '%2$s [%3$s] %4$s';
-
- /**
- * String containing the timestamp format. It will be passed directly to
- * strftime(). Note that the timestamp string will generated using the
- * current locale.
- *
- * Note! Default lineFormat of this driver does not display time.
- *
- * @var string
- * @access private
- */
- var $_timeFormat = '%b %d %H:%M:%S';
-
- /**
- * Mapping of log priorities to Firebug methods.
- * @var array
- * @access private
- */
- var $_methods = array(
- PEAR_LOG_EMERG => 'error',
- PEAR_LOG_ALERT => 'error',
- PEAR_LOG_CRIT => 'error',
- PEAR_LOG_ERR => 'error',
- PEAR_LOG_WARNING => 'warn',
- PEAR_LOG_NOTICE => 'info',
- PEAR_LOG_INFO => 'info',
- PEAR_LOG_DEBUG => 'debug'
- );
-
- /**
- * Constructs a new Log_firebug object.
- *
- * @param string $name Ignored.
- * @param string $ident The identity string.
- * @param array $conf The configuration array.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_firebug($name = '', $ident = 'PHP', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- $this->_id = md5(microtime());
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
- if (isset($conf['buffering'])) {
- $this->_buffering = $conf['buffering'];
- }
-
- if ($this->_buffering) {
- register_shutdown_function(array(&$this, '_Log_firebug'));
- }
-
- if (!empty($conf['lineFormat'])) {
- $this->_lineFormat = str_replace(array_keys($this->_formatMap),
- array_values($this->_formatMap),
- $conf['lineFormat']);
- }
-
- if (!empty($conf['timeFormat'])) {
- $this->_timeFormat = $conf['timeFormat'];
- }
- }
-
- /**
- * Opens the firebug handler.
- *
- * @access public
- */
- function open()
- {
- $this->_opened = true;
- return true;
- }
-
- /**
- * Destructor
- */
- function _Log_firebug()
- {
- $this->close();
- }
-
- /**
- * Closes the firebug handler.
- *
- * @access public
- */
- function close()
- {
- $this->flush();
- $this->_opened = false;
- return true;
- }
-
- /**
- * Flushes all pending ("buffered") data.
- *
- * @access public
- */
- function flush() {
- if (count($this->_buffer)) {
- print '<script type="text/javascript">';
- print "\nif (('console' in window) && ('firebug' in console)) {\n";
- foreach ($this->_buffer as $line) {
- print " $line\n";
- }
- print "}\n";
- print "</script>\n";
- };
- $this->_buffer = array();
- }
-
- /**
- * Writes $message to Firebug console. Also, passes the message
- * along to any Log_observer instances that are observing this Log.
- *
- * @param mixed $message String or object containing the message to log.
- * @param string $priority The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* Extract the string representation of the message. */
- $message = $this->_extractMessage($message);
- $method = $this->_methods[$priority];
-
- /* normalize line breaks and escape quotes*/
- $message = preg_replace("/\r?\n/", "\\n", addslashes($message));
-
- /* Build the string containing the complete log line. */
- $line = $this->_format($this->_lineFormat,
- strftime($this->_timeFormat),
- $priority,
- $message);
-
- if ($this->_buffering) {
- $this->_buffer[] = sprintf('console.%s("%s");', $method, $line);
- } else {
- print '<script type="text/javascript">';
- print "\nif (('console' in window) && ('firebug' in console)) {\n";
- /* Build and output the complete log line. */
- printf(' console.%s("%s");', $method, $line);
- print "\n}\n";
- print "</script>\n";
- }
- /* Notify observers about this log message. */
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return true;
- }
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- *
- * @version $Revision: 266658 $
- * @package Log
- */
-
-/**
- * The Log_mail class is a concrete implementation of the Log:: abstract class
- * which sends log messages to a mailbox.
- * The mail is actually sent when you close() the logger, or when the destructor
- * is called (when the script is terminated).
- *
- * PLEASE NOTE that you must create a Log_mail object using =&, like this :
- * $logger =& Log::factory("mail", "recipient@example.com", ...)
- *
- * This is a PEAR requirement for destructors to work properly.
- * See http://pear.php.net/manual/en/class.pear.php
- *
- * @author Ronnie Garcia <ronnie@mk2.net>
- * @author Jon Parise <jon@php.net>
- * @since Log 1.3
- * @package Log
- *
- * @example mail.php Using the mail handler.
- */
-class Log_mail extends Log
-{
- /**
- * String holding the recipients' email addresses. Multiple addresses
- * should be separated with commas.
- * @var string
- * @access private
- */
- var $_recipients = '';
-
- /**
- * String holding the sender's email address.
- * @var string
- * @access private
- */
- var $_from = '';
-
- /**
- * String holding the email's subject.
- * @var string
- * @access private
- */
- var $_subject = '[Log_mail] Log message';
-
- /**
- * String holding an optional preamble for the log messages.
- * @var string
- * @access private
- */
- var $_preamble = '';
-
- /**
- * String containing the format of a log line.
- * @var string
- * @access private
- */
- var $_lineFormat = '%1$s %2$s [%3$s] %4$s';
-
- /**
- * String containing the timestamp format. It will be passed directly to
- * strftime(). Note that the timestamp string will generated using the
- * current locale.
- * @var string
- * @access private
- */
- var $_timeFormat = '%b %d %H:%M:%S';
-
- /**
- * String holding the mail message body.
- * @var string
- * @access private
- */
- var $_message = '';
-
- /**
- * Flag used to indicated that log lines have been written to the message
- * body and the message should be sent on close().
- * @var boolean
- * @access private
- */
- var $_shouldSend = false;
-
- /**
- * String holding the backend name of PEAR::Mail
- * @var string
- * @access private
- */
- var $_mailBackend = '';
-
- /**
- * Array holding the params for PEAR::Mail
- * @var array
- * @access private
- */
- var $_mailParams = array();
-
- /**
- * Constructs a new Log_mail object.
- *
- * Here is how you can customize the mail driver with the conf[] hash :
- * $conf['from']: the mail's "From" header line,
- * $conf['subject']: the mail's "Subject" line.
- * $conf['mailBackend']: backend name of PEAR::Mail
- * $conf['mailParams']: parameters for the PEAR::Mail backend
- *
- * @param string $name The message's recipients.
- * @param string $ident The identity string.
- * @param array $conf The configuration array.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_mail($name, $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- $this->_id = md5(microtime());
- $this->_recipients = $name;
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
-
- if (!empty($conf['from'])) {
- $this->_from = $conf['from'];
- } else {
- $this->_from = ini_get('sendmail_from');
- }
-
- if (!empty($conf['subject'])) {
- $this->_subject = $conf['subject'];
- }
-
- if (!empty($conf['preamble'])) {
- $this->_preamble = $conf['preamble'];
- }
-
- if (!empty($conf['lineFormat'])) {
- $this->_lineFormat = str_replace(array_keys($this->_formatMap),
- array_values($this->_formatMap),
- $conf['lineFormat']);
- }
-
- if (!empty($conf['timeFormat'])) {
- $this->_timeFormat = $conf['timeFormat'];
- }
-
- if (!empty($conf['mailBackend'])) {
- $this->_mailBackend = $conf['mailBackend'];
- }
-
- if (!empty($conf['mailParams'])) {
- $this->_mailParams = $conf['mailParams'];
- }
-
- /* register the destructor */
- register_shutdown_function(array(&$this, '_Log_mail'));
- }
-
- /**
- * Destructor. Calls close().
- *
- * @access private
- */
- function _Log_mail()
- {
- $this->close();
- }
-
- /**
- * Starts a new mail message.
- * This is implicitly called by log(), if necessary.
- *
- * @access public
- */
- function open()
- {
- if (!$this->_opened) {
- if (!empty($this->_preamble)) {
- $this->_message = $this->_preamble . "\r\n\r\n";
- }
- $this->_opened = true;
- $_shouldSend = false;
- }
-
- return $this->_opened;
- }
-
- /**
- * Closes the message, if it is open, and sends the mail.
- * This is implicitly called by the destructor, if necessary.
- *
- * @access public
- */
- function close()
- {
- if ($this->_opened) {
- if ($this->_shouldSend && !empty($this->_message)) {
- if ($this->_mailBackend === '') { // use mail()
- $headers = "From: $this->_from\r\n";
- $headers .= 'User-Agent: PEAR Log Package';
- if (mail($this->_recipients, $this->_subject,
- $this->_message, $headers) == false) {
- return false;
- }
- } else { // use PEAR::Mail
- include_once 'Mail.php';
- $headers = array('From' => $this->_from,
- 'To' => $this->_recipients,
- 'User-Agent' => 'PEAR Log Package',
- 'Subject' => $this->_subject);
- $mailer = &Mail::factory($this->_mailBackend,
- $this->_mailParams);
- $res = $mailer->send($this->_recipients, $headers,
- $this->_message);
- if (PEAR::isError($res)) {
- return false;
- }
- }
-
- /* Clear the message string now that the email has been sent. */
- $this->_message = '';
- $this->_shouldSend = false;
- }
- $this->_opened = false;
- }
-
- return ($this->_opened === false);
- }
-
- /**
- * Flushes the log output by forcing the email message to be sent now.
- * Events that are logged after flush() is called will be appended to a
- * new email message.
- *
- * @access public
- * @since Log 1.8.2
- */
- function flush()
- {
- /*
- * It's sufficient to simply call close() to flush the output.
- * The next call to log() will cause the handler to be reopened.
- */
- return $this->close();
- }
-
- /**
- * Writes $message to the currently open mail message.
- * Calls open(), if necessary.
- *
- * @param mixed $message String or object containing the message to log.
- * @param string $priority The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* If the message isn't open and can't be opened, return failure. */
- if (!$this->_opened && !$this->open()) {
- return false;
- }
-
- /* Extract the string representation of the message. */
- $message = $this->_extractMessage($message);
-
- /* Append the string containing the complete log line. */
- $this->_message .= $this->_format($this->_lineFormat,
- strftime($this->_timeFormat),
- $priority, $message) . "\r\n";
- $this->_shouldSend = true;
-
- /* Notify observers about this log message. */
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return true;
- }
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- * $Horde: horde/lib/Log/mcal.php,v 1.2 2000/06/28 21:36:13 jon Exp $
- *
- * @version $Revision: 180836 $
- * @package Log
- */
-
-/**
- * The Log_mcal class is a concrete implementation of the Log::
- * abstract class which sends messages to a local or remote calendar
- * store accessed through MCAL.
- *
- * @author Chuck Hagenbuch <chuck@horde.org>
- * @since Horde 1.3
- * @since Log 1.0
- * @package Log
- */
-class Log_mcal extends Log
-{
- /**
- * holding the calendar specification to connect to.
- * @var string
- * @access private
- */
- var $_calendar = '{localhost/mstore}';
-
- /**
- * holding the username to use.
- * @var string
- * @access private
- */
- var $_username = '';
-
- /**
- * holding the password to use.
- * @var string
- * @access private
- */
- var $_password = '';
-
- /**
- * holding the options to pass to the calendar stream.
- * @var integer
- * @access private
- */
- var $_options = 0;
-
- /**
- * ResourceID of the MCAL stream.
- * @var string
- * @access private
- */
- var $_stream = '';
-
- /**
- * Integer holding the log facility to use.
- * @var string
- * @access private
- */
- var $_name = LOG_SYSLOG;
-
-
- /**
- * Constructs a new Log_mcal object.
- *
- * @param string $name The category to use for our events.
- * @param string $ident The identity string.
- * @param array $conf The configuration array.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_mcal($name, $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- $this->_id = md5(microtime());
- $this->_name = $name;
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
- $this->_calendar = $conf['calendar'];
- $this->_username = $conf['username'];
- $this->_password = $conf['password'];
- $this->_options = $conf['options'];
- }
-
- /**
- * Opens a calendar stream, if it has not already been
- * opened. This is implicitly called by log(), if necessary.
- * @access public
- */
- function open()
- {
- if (!$this->_opened) {
- $this->_stream = mcal_open($this->_calendar, $this->_username,
- $this->_password, $this->_options);
- $this->_opened = true;
- }
-
- return $this->_opened;
- }
-
- /**
- * Closes the calendar stream, if it is open.
- * @access public
- */
- function close()
- {
- if ($this->_opened) {
- mcal_close($this->_stream);
- $this->_opened = false;
- }
-
- return ($this->_opened === false);
- }
-
- /**
- * Logs $message and associated information to the currently open
- * calendar stream. Calls open() if necessary. Also passes the
- * message along to any Log_observer instances that are observing
- * this Log.
- *
- * @param mixed $message String or object containing the message to log.
- * @param string $priority The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* If the connection isn't open and can't be opened, return failure. */
- if (!$this->_opened && !$this->open()) {
- return false;
- }
-
- /* Extract the string representation of the message. */
- $message = $this->_extractMessage($message);
-
- $date_str = date('Y:n:j:G:i:s');
- $dates = explode(':', $date_str);
-
- mcal_event_init($this->_stream);
- mcal_event_set_title($this->_stream, $this->_ident);
- mcal_event_set_category($this->_stream, $this->_name);
- mcal_event_set_description($this->_stream, $message);
- mcal_event_add_attribute($this->_stream, 'priority', $priority);
- mcal_event_set_start($this->_stream, $dates[0], $dates[1], $dates[2],
- $dates[3], $dates[4], $dates[5]);
- mcal_event_set_end($this->_stream, $dates[0], $dates[1], $dates[2],
- $dates[3], $dates[4], $dates[5]);
- mcal_append_event($this->_stream);
-
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return true;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- *
- * @version $Revision: 204814 $
- * @package Log
- */
-
-/** PEAR's MDB2 package */
-require_once 'MDB2.php';
-MDB2::loadFile('Date');
-
-/**
- * The Log_mdb2 class is a concrete implementation of the Log:: abstract class
- * which sends messages to an SQL server. Each entry occupies a separate row
- * in the database.
- *
- * This implementation uses PEAR's MDB2 database abstraction layer.
- *
- * CREATE TABLE log_table (
- * id INT NOT NULL,
- * logtime TIMESTAMP NOT NULL,
- * ident CHAR(16) NOT NULL,
- * priority INT NOT NULL,
- * message VARCHAR(200),
- * PRIMARY KEY (id)
- * );
- *
- * @author Lukas Smith <smith@backendmedia.com>
- * @author Jon Parise <jon@php.net>
- * @since Log 1.9.0
- * @package Log
- */
-class Log_mdb2 extends Log
-{
- /**
- * Variable containing the DSN information.
- * @var mixed
- * @access private
- */
- var $_dsn = '';
-
- /**
- * Array containing our set of DB configuration options.
- * @var array
- * @access private
- */
- var $_options = array('persistent' => true);
-
- /**
- * Object holding the database handle.
- * @var object
- * @access private
- */
- var $_db = null;
-
- /**
- * Resource holding the prepared statement handle.
- * @var resource
- * @access private
- */
- var $_statement = null;
-
- /**
- * Flag indicating that we're using an existing database connection.
- * @var boolean
- * @access private
- */
- var $_existingConnection = false;
-
- /**
- * String holding the database table to use.
- * @var string
- * @access private
- */
- var $_table = 'log_table';
-
- /**
- * String holding the name of the ID sequence.
- * @var string
- * @access private
- */
- var $_sequence = 'log_id';
-
- /**
- * Maximum length of the $ident string. This corresponds to the size of
- * the 'ident' column in the SQL table.
- * @var integer
- * @access private
- */
- var $_identLimit = 16;
-
- /**
- * Set of field types used in the database table.
- * @var array
- * @access private
- */
- var $_types = array(
- 'id' => 'integer',
- 'logtime' => 'timestamp',
- 'ident' => 'text',
- 'priority' => 'text',
- 'message' => 'clob'
- );
-
- /**
- * Constructs a new sql logging object.
- *
- * @param string $name The target SQL table.
- * @param string $ident The identification field.
- * @param array $conf The connection configuration array.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_mdb2($name, $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- $this->_id = md5(microtime());
- $this->_table = $name;
- $this->_mask = Log::UPTO($level);
-
- /* If an options array was provided, use it. */
- if (isset($conf['options']) && is_array($conf['options'])) {
- $this->_options = $conf['options'];
- }
-
- /* If a specific sequence name was provided, use it. */
- if (!empty($conf['sequence'])) {
- $this->_sequence = $conf['sequence'];
- }
-
- /* If a specific sequence name was provided, use it. */
- if (isset($conf['identLimit'])) {
- $this->_identLimit = $conf['identLimit'];
- }
-
- /* Now that the ident limit is confirmed, set the ident string. */
- $this->setIdent($ident);
-
- /* If an existing database connection was provided, use it. */
- if (isset($conf['db'])) {
- $this->_db = &$conf['db'];
- $this->_existingConnection = true;
- $this->_opened = true;
- } elseif (isset($conf['singleton'])) {
- $this->_db = &MDB2::singleton($conf['singleton'], $this->_options);
- $this->_existingConnection = true;
- $this->_opened = true;
- } else {
- $this->_dsn = $conf['dsn'];
- }
- }
-
- /**
- * Opens a connection to the database, if it has not already
- * been opened. This is implicitly called by log(), if necessary.
- *
- * @return boolean True on success, false on failure.
- * @access public
- */
- function open()
- {
- if (!$this->_opened) {
- /* Use the DSN and options to create a database connection. */
- $this->_db = &MDB2::connect($this->_dsn, $this->_options);
- if (PEAR::isError($this->_db)) {
- return false;
- }
-
- /* Create a prepared statement for repeated use in log(). */
- if (!$this->_prepareStatement()) {
- return false;
- }
-
- /* We now consider out connection open. */
- $this->_opened = true;
- }
-
- return $this->_opened;
- }
-
- /**
- * Closes the connection to the database if it is still open and we were
- * the ones that opened it. It is the caller's responsible to close an
- * existing connection that was passed to us via $conf['db'].
- *
- * @return boolean True on success, false on failure.
- * @access public
- */
- function close()
- {
- /* If we have a statement object, free it. */
- if (is_object($this->_statement)) {
- $this->_statement->free();
- $this->_statement = null;
- }
-
- /* If we opened the database connection, disconnect it. */
- if ($this->_opened && !$this->_existingConnection) {
- $this->_opened = false;
- return $this->_db->disconnect();
- }
-
- return ($this->_opened === false);
- }
-
- /**
- * Sets this Log instance's identification string. Note that this
- * SQL-specific implementation will limit the length of the $ident string
- * to sixteen (16) characters.
- *
- * @param string $ident The new identification string.
- *
- * @access public
- * @since Log 1.8.5
- */
- function setIdent($ident)
- {
- $this->_ident = substr($ident, 0, $this->_identLimit);
- }
-
- /**
- * Inserts $message to the currently open database. Calls open(),
- * if necessary. Also passes the message along to any Log_observer
- * instances that are observing this Log.
- *
- * @param mixed $message String or object containing the message to log.
- * @param string $priority The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* If the connection isn't open and can't be opened, return failure. */
- if (!$this->_opened && !$this->open()) {
- return false;
- }
-
- /* If we don't already have a statement object, create one. */
- if (!is_object($this->_statement) && !$this->_prepareStatement()) {
- return false;
- }
-
- /* Extract the string representation of the message. */
- $message = $this->_extractMessage($message);
-
- /* Build our set of values for this log entry. */
- $values = array(
- 'id' => $this->_db->nextId($this->_sequence),
- 'logtime' => MDB2_Date::mdbNow(),
- 'ident' => $this->_ident,
- 'priority' => $priority,
- 'message' => $message
- );
-
- /* Execute the SQL query for this log entry insertion. */
- $this->_db->expectError(MDB2_ERROR_NOSUCHTABLE);
- $result = &$this->_statement->execute($values);
- $this->_db->popExpect();
-
- /* Attempt to handle any errors. */
- if (PEAR::isError($result)) {
- /* We can only handle MDB2_ERROR_NOSUCHTABLE errors. */
- if ($result->getCode() != MDB2_ERROR_NOSUCHTABLE) {
- return false;
- }
-
- /* Attempt to create the target table. */
- if (!$this->_createTable()) {
- return false;
- }
-
- /* Recreate our prepared statement resource. */
- $this->_statement->free();
- if (!$this->_prepareStatement()) {
- return false;
- }
-
- /* Attempt to re-execute the insertion query. */
- $result = $this->_statement->execute($values);
- if (PEAR::isError($result)) {
- return false;
- }
- }
-
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return true;
- }
-
- /**
- * Create the log table in the database.
- *
- * @return boolean True on success or false on failure.
- * @access private
- */
- function _createTable()
- {
- $this->_db->loadModule('Manager', null, true);
- $result = $this->_db->manager->createTable(
- $this->_table,
- array(
- 'id' => array('type' => $this->_types['id']),
- 'logtime' => array('type' => $this->_types['logtime']),
- 'ident' => array('type' => $this->_types['ident']),
- 'priority' => array('type' => $this->_types['priority']),
- 'message' => array('type' => $this->_types['message'])
- )
- );
- if (PEAR::isError($result)) {
- return false;
- }
-
- $result = $this->_db->manager->createIndex(
- $this->_table,
- 'unique_id',
- array('fields' => array('id' => true), 'unique' => true)
- );
- if (PEAR::isError($result)) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Prepare the SQL insertion statement.
- *
- * @return boolean True if the statement was successfully created.
- *
- * @access private
- * @since Log 1.9.0
- */
- function _prepareStatement()
- {
- $this->_statement = &$this->_db->prepare(
- 'INSERT INTO ' . $this->_table .
- ' (id, logtime, ident, priority, message)' .
- ' VALUES(:id, :logtime, :ident, :priority, :message)',
- $this->_types, MDB2_PREPARE_MANIP);
-
- /* Return success if we didn't generate an error. */
- return (PEAR::isError($this->_statement) === false);
- }
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- *
- * @version $Revision: 215527 $
- * @package Log
- */
-
-/**
- * The Log_null class is a concrete implementation of the Log:: abstract
- * class. It simply consumes log events.
- *
- * @author Jon Parise <jon@php.net>
- * @since Log 1.8.2
- * @package Log
- *
- * @example null.php Using the null handler.
- */
-class Log_null extends Log
-{
- /**
- * Constructs a new Log_null object.
- *
- * @param string $name Ignored.
- * @param string $ident The identity string.
- * @param array $conf The configuration array.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_null($name, $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- $this->_id = md5(microtime());
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
- }
-
- /**
- * Opens the handler.
- *
- * @access public
- * @since Log 1.9.6
- */
- function open()
- {
- $this->_opened = true;
- return true;
- }
-
- /**
- * Closes the handler.
- *
- * @access public
- * @since Log 1.9.6
- */
- function close()
- {
- $this->_opened = false;
- return true;
- }
-
- /**
- * Simply consumes the log event. The message will still be passed
- * along to any Log_observer instances that are observing this Log.
- *
- * @param mixed $message String or object containing the message to log.
- * @param string $priority The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return true;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- * $Horde: horde/lib/Log/observer.php,v 1.5 2000/06/28 21:36:13 jon Exp $
- *
- * @version $Revision: 211953 $
- * @package Log
- */
-
-/**
- * The Log_observer:: class implements the Observer end of a Subject-Observer
- * pattern for watching log activity and taking actions on exceptional events.
- *
- * @author Chuck Hagenbuch <chuck@horde.org>
- * @since Horde 1.3
- * @since Log 1.0
- * @package Log
- *
- * @example observer_mail.php An example Log_observer implementation.
- */
-class Log_observer
-{
- /**
- * Instance-specific unique identification number.
- *
- * @var integer
- * @access private
- */
- var $_id = 0;
-
- /**
- * The minimum priority level of message that we want to hear about.
- * PEAR_LOG_EMERG is the highest priority, so we will only hear messages
- * with an integer priority value less than or equal to ours. It defaults
- * to PEAR_LOG_INFO, which listens to everything except PEAR_LOG_DEBUG.
- *
- * @var string
- * @access private
- */
- var $_priority = PEAR_LOG_INFO;
-
- /**
- * Creates a new basic Log_observer instance.
- *
- * @param integer $priority The highest priority at which to receive
- * log event notifications.
- *
- * @access public
- */
- function Log_observer($priority = PEAR_LOG_INFO)
- {
- $this->_id = md5(microtime());
- $this->_priority = $priority;
- }
-
- /**
- * Attempts to return a new concrete Log_observer instance of the requested
- * type.
- *
- * @param string $type The type of concreate Log_observer subclass
- * to return.
- * @param integer $priority The highest priority at which to receive
- * log event notifications.
- * @param array $conf Optional associative array of additional
- * configuration values.
- *
- * @return object The newly created concrete Log_observer
- * instance, or null on an error.
- */
- function &factory($type, $priority = PEAR_LOG_INFO, $conf = array())
- {
- $type = strtolower($type);
- $class = 'Log_observer_' . $type;
-
- /*
- * If the desired class already exists (because the caller has supplied
- * it from some custom location), simply instantiate and return a new
- * instance.
- */
- if (class_exists($class)) {
- $object = &new $class($priority, $conf);
- return $object;
- }
-
- /* Support both the new-style and old-style file naming conventions. */
- $newstyle = true;
- $classfile = dirname(__FILE__) . '/observer_' . $type . '.php';
-
- if (!file_exists($classfile)) {
- $classfile = 'Log/' . $type . '.php';
- $newstyle = false;
- }
-
- /*
- * Attempt to include our version of the named class, but don't treat
- * a failure as fatal. The caller may have already included their own
- * version of the named class.
- */
- @include_once $classfile;
-
- /* If the class exists, return a new instance of it. */
- if (class_exists($class)) {
- /* Support both new-style and old-style construction. */
- if ($newstyle) {
- $object = &new $class($priority, $conf);
- } else {
- $object = &new $class($priority);
- }
- return $object;
- }
-
- $null = null;
- return $null;
- }
-
- /**
- * This is a stub method to make sure that Log_Observer classes do
- * something when they are notified of a message. The default behavior
- * is to just print the message, which is obviously not desireable in
- * practically any situation - which is why you need to override this
- * method. :)
- *
- * @param array $event A hash describing the log event.
- */
- function notify($event)
- {
- print_r($event);
- }
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- * $Horde: horde/lib/Log/sql.php,v 1.12 2000/08/16 20:27:34 chuck Exp $
- *
- * @version $Revision: 250926 $
- * @package Log
- */
-
-/**
- * We require the PEAR DB class. This is generally defined in the DB.php file,
- * but it's possible that the caller may have provided the DB class, or a
- * compatible wrapper (such as the one shipped with MDB2), so we first check
- * for an existing 'DB' class before including 'DB.php'.
- */
-if (!class_exists('DB')) {
- require_once 'DB.php';
-}
-
-/**
- * The Log_sql class is a concrete implementation of the Log::
- * abstract class which sends messages to an SQL server. Each entry
- * occupies a separate row in the database.
- *
- * This implementation uses PHP's PEAR database abstraction layer.
- *
- * CREATE TABLE log_table (
- * id INT NOT NULL,
- * logtime TIMESTAMP NOT NULL,
- * ident CHAR(16) NOT NULL,
- * priority INT NOT NULL,
- * message VARCHAR(200),
- * PRIMARY KEY (id)
- * );
- *
- * @author Jon Parise <jon@php.net>
- * @since Horde 1.3
- * @since Log 1.0
- * @package Log
- *
- * @example sql.php Using the SQL handler.
- */
-class Log_sql extends Log
-{
- /**
- * Variable containing the DSN information.
- * @var mixed
- * @access private
- */
- var $_dsn = '';
-
- /**
- * String containing the SQL insertion statement.
- *
- * @var string
- * @access private
- */
- var $_sql = '';
-
- /**
- * Array containing our set of DB configuration options.
- * @var array
- * @access private
- */
- var $_options = array('persistent' => true);
-
- /**
- * Object holding the database handle.
- * @var object
- * @access private
- */
- var $_db = null;
-
- /**
- * Resource holding the prepared statement handle.
- * @var resource
- * @access private
- */
- var $_statement = null;
-
- /**
- * Flag indicating that we're using an existing database connection.
- * @var boolean
- * @access private
- */
- var $_existingConnection = false;
-
- /**
- * String holding the database table to use.
- * @var string
- * @access private
- */
- var $_table = 'log_table';
-
- /**
- * String holding the name of the ID sequence.
- * @var string
- * @access private
- */
- var $_sequence = 'log_id';
-
- /**
- * Maximum length of the $ident string. This corresponds to the size of
- * the 'ident' column in the SQL table.
- * @var integer
- * @access private
- */
- var $_identLimit = 16;
-
-
- /**
- * Constructs a new sql logging object.
- *
- * @param string $name The target SQL table.
- * @param string $ident The identification field.
- * @param array $conf The connection configuration array.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_sql($name, $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- $this->_id = md5(microtime());
- $this->_table = $name;
- $this->_mask = Log::UPTO($level);
-
- /* Now that we have a table name, assign our SQL statement. */
- if (!empty($conf['sql'])) {
- $this->_sql = $conf['sql'];
- } else {
- $this->_sql = 'INSERT INTO ' . $this->_table .
- ' (id, logtime, ident, priority, message)' .
- ' VALUES(?, CURRENT_TIMESTAMP, ?, ?, ?)';
- }
-
- /* If an options array was provided, use it. */
- if (isset($conf['options']) && is_array($conf['options'])) {
- $this->_options = $conf['options'];
- }
-
- /* If a specific sequence name was provided, use it. */
- if (!empty($conf['sequence'])) {
- $this->_sequence = $conf['sequence'];
- }
-
- /* If a specific sequence name was provided, use it. */
- if (isset($conf['identLimit'])) {
- $this->_identLimit = $conf['identLimit'];
- }
-
- /* Now that the ident limit is confirmed, set the ident string. */
- $this->setIdent($ident);
-
- /* If an existing database connection was provided, use it. */
- if (isset($conf['db'])) {
- $this->_db = &$conf['db'];
- $this->_existingConnection = true;
- $this->_opened = true;
- } else {
- $this->_dsn = $conf['dsn'];
- }
- }
-
- /**
- * Opens a connection to the database, if it has not already
- * been opened. This is implicitly called by log(), if necessary.
- *
- * @return boolean True on success, false on failure.
- * @access public
- */
- function open()
- {
- if (!$this->_opened) {
- /* Use the DSN and options to create a database connection. */
- $this->_db = &DB::connect($this->_dsn, $this->_options);
- if (DB::isError($this->_db)) {
- return false;
- }
-
- /* Create a prepared statement for repeated use in log(). */
- if (!$this->_prepareStatement()) {
- return false;
- }
-
- /* We now consider out connection open. */
- $this->_opened = true;
- }
-
- return $this->_opened;
- }
-
- /**
- * Closes the connection to the database if it is still open and we were
- * the ones that opened it. It is the caller's responsible to close an
- * existing connection that was passed to us via $conf['db'].
- *
- * @return boolean True on success, false on failure.
- * @access public
- */
- function close()
- {
- if ($this->_opened && !$this->_existingConnection) {
- $this->_opened = false;
- $this->_db->freePrepared($this->_statement);
- return $this->_db->disconnect();
- }
-
- return ($this->_opened === false);
- }
-
- /**
- * Sets this Log instance's identification string. Note that this
- * SQL-specific implementation will limit the length of the $ident string
- * to sixteen (16) characters.
- *
- * @param string $ident The new identification string.
- *
- * @access public
- * @since Log 1.8.5
- */
- function setIdent($ident)
- {
- $this->_ident = substr($ident, 0, $this->_identLimit);
- }
-
- /**
- * Inserts $message to the currently open database. Calls open(),
- * if necessary. Also passes the message along to any Log_observer
- * instances that are observing this Log.
- *
- * @param mixed $message String or object containing the message to log.
- * @param string $priority The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* If the connection isn't open and can't be opened, return failure. */
- if (!$this->_opened && !$this->open()) {
- return false;
- }
-
- /* If we don't already have our statement object yet, create it. */
- if (!is_object($this->_statement) && !$this->_prepareStatement()) {
- return false;
- }
-
- /* Extract the string representation of the message. */
- $message = $this->_extractMessage($message);
-
- /* Build our set of values for this log entry. */
- $id = $this->_db->nextId($this->_sequence);
- $values = array($id, $this->_ident, $priority, $message);
-
- /* Execute the SQL query for this log entry insertion. */
- $result =& $this->_db->execute($this->_statement, $values);
- if (DB::isError($result)) {
- return false;
- }
-
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return true;
- }
-
- /**
- * Prepare the SQL insertion statement.
- *
- * @return boolean True if the statement was successfully created.
- *
- * @access private
- * @since Log 1.9.1
- */
- function _prepareStatement()
- {
- $this->_statement = $this->_db->prepare($this->_sql);
-
- /* Return success if we didn't generate an error. */
- return (DB::isError($this->_statement) === false);
- }
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- *
- * @version $Revision: 202069 $
- * @package Log
- */
-
-/**
- * The Log_sqlite class is a concrete implementation of the Log::
- * abstract class which sends messages to an Sqlite database.
- * Each entry occupies a separate row in the database.
- *
- * This implementation uses PHP native Sqlite functions.
- *
- * CREATE TABLE log_table (
- * id INTEGER PRIMARY KEY NOT NULL,
- * logtime NOT NULL,
- * ident CHAR(16) NOT NULL,
- * priority INT NOT NULL,
- * message
- * );
- *
- * @author Bertrand Mansion <bmansion@mamasam.com>
- * @author Jon Parise <jon@php.net>
- * @since Log 1.8.3
- * @package Log
- *
- * @example sqlite.php Using the Sqlite handler.
- */
-class Log_sqlite extends Log
-{
- /**
- * Array containing the connection defaults
- * @var array
- * @access private
- */
- var $_options = array('mode' => 0666,
- 'persistent' => false);
-
- /**
- * Object holding the database handle.
- * @var object
- * @access private
- */
- var $_db = null;
-
- /**
- * Flag indicating that we're using an existing database connection.
- * @var boolean
- * @access private
- */
- var $_existingConnection = false;
-
- /**
- * String holding the database table to use.
- * @var string
- * @access private
- */
- var $_table = 'log_table';
-
-
- /**
- * Constructs a new sql logging object.
- *
- * @param string $name The target SQL table.
- * @param string $ident The identification field.
- * @param mixed $conf Can be an array of configuration options used
- * to open a new database connection
- * or an already opened sqlite connection.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_sqlite($name, $ident = '', &$conf, $level = PEAR_LOG_DEBUG)
- {
- $this->_id = md5(microtime());
- $this->_table = $name;
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
-
- if (is_array($conf)) {
- foreach ($conf as $k => $opt) {
- $this->_options[$k] = $opt;
- }
- } else {
- // If an existing database connection was provided, use it.
- $this->_db =& $conf;
- $this->_existingConnection = true;
- }
- }
-
- /**
- * Opens a connection to the database, if it has not already
- * been opened. This is implicitly called by log(), if necessary.
- *
- * @return boolean True on success, false on failure.
- * @access public
- */
- function open()
- {
- if (is_resource($this->_db)) {
- $this->_opened = true;
- return $this->_createTable();
- } else {
- /* Set the connection function based on the 'persistent' option. */
- if (empty($this->_options['persistent'])) {
- $connectFunction = 'sqlite_open';
- } else {
- $connectFunction = 'sqlite_popen';
- }
-
- /* Attempt to connect to the database. */
- if ($this->_db = $connectFunction($this->_options['filename'],
- (int)$this->_options['mode'],
- $error)) {
- $this->_opened = true;
- return $this->_createTable();
- }
- }
-
- return $this->_opened;
- }
-
- /**
- * Closes the connection to the database if it is still open and we were
- * the ones that opened it. It is the caller's responsible to close an
- * existing connection that was passed to us via $conf['db'].
- *
- * @return boolean True on success, false on failure.
- * @access public
- */
- function close()
- {
- /* We never close existing connections. */
- if ($this->_existingConnection) {
- return false;
- }
-
- if ($this->_opened) {
- $this->_opened = false;
- sqlite_close($this->_db);
- }
-
- return ($this->_opened === false);
- }
-
- /**
- * Inserts $message to the currently open database. Calls open(),
- * if necessary. Also passes the message along to any Log_observer
- * instances that are observing this Log.
- *
- * @param mixed $message String or object containing the message to log.
- * @param string $priority The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* If the connection isn't open and can't be opened, return failure. */
- if (!$this->_opened && !$this->open()) {
- return false;
- }
-
- // Extract the string representation of the message.
- $message = $this->_extractMessage($message);
-
- // Build the SQL query for this log entry insertion.
- $q = sprintf('INSERT INTO [%s] (logtime, ident, priority, message) ' .
- "VALUES ('%s', '%s', %d, '%s')",
- $this->_table,
- strftime('%Y-%m-%d %H:%M:%S', time()),
- sqlite_escape_string($this->_ident),
- $priority,
- sqlite_escape_string($message));
- if (!($res = @sqlite_unbuffered_query($this->_db, $q))) {
- return false;
- }
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return true;
- }
-
- /**
- * Checks whether the log table exists and creates it if necessary.
- *
- * @return boolean True on success or false on failure.
- * @access private
- */
- function _createTable()
- {
- $q = "SELECT name FROM sqlite_master WHERE name='" . $this->_table .
- "' AND type='table'";
-
- $res = sqlite_query($this->_db, $q);
-
- if (sqlite_num_rows($res) == 0) {
- $q = 'CREATE TABLE [' . $this->_table . '] (' .
- 'id INTEGER PRIMARY KEY NOT NULL, ' .
- 'logtime NOT NULL, ' .
- 'ident CHAR(16) NOT NULL, ' .
- 'priority INT NOT NULL, ' .
- 'message)';
-
- if (!($res = sqlite_unbuffered_query($this->_db, $q))) {
- return false;
- }
- }
-
- return true;
- }
-
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- * $Horde: horde/lib/Log/syslog.php,v 1.6 2000/06/28 21:36:13 jon Exp $
- *
- * @version $Revision: 308379 $
- * @package Log
- */
-
-/**
- * The Log_syslog class is a concrete implementation of the Log::
- * abstract class which sends messages to syslog on UNIX-like machines
- * (PHP emulates this with the Event Log on Windows machines).
- *
- * @author Chuck Hagenbuch <chuck@horde.org>
- * @author Jon Parise <jon@php.net>
- * @since Horde 1.3
- * @since Log 1.0
- * @package Log
- *
- * @example syslog.php Using the syslog handler.
- */
-class Log_syslog extends Log
-{
- /**
- * Integer holding the log facility to use.
- * @var integer
- * @access private
- */
- var $_name = LOG_SYSLOG;
-
- /**
- * Should we inherit the current syslog connection for this process, or
- * should we call openlog() to start a new syslog connection?
- * @var boolean
- * @access private
- */
- var $_inherit = false;
-
- /**
- * Should we re-open the syslog connection for each log event?
- * @var boolean
- * @access private
- */
- var $_reopen = false;
-
- /**
- * Maximum message length that will be sent to syslog(). If the handler
- * receives a message longer than this length limit, it will be split into
- * multiple syslog() calls.
- * @var integer
- * @access private
- */
- var $_maxLength = 500;
-
- /**
- * String containing the format of a message.
- * @var string
- * @access private
- */
- var $_lineFormat = '%4$s';
-
- /**
- * String containing the timestamp format. It will be passed directly to
- * strftime(). Note that the timestamp string will generated using the
- * current locale.
- * @var string
- * @access private
- */
- var $_timeFormat = '%b %d %H:%M:%S';
-
- /**
- * Constructs a new syslog object.
- *
- * @param string $name The syslog facility.
- * @param string $ident The identity string.
- * @param array $conf The configuration array.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_syslog($name, $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- /* Ensure we have a valid integer value for $name. */
- if (empty($name) || !is_int($name)) {
- $name = LOG_SYSLOG;
- }
-
- if (isset($conf['inherit'])) {
- $this->_inherit = $conf['inherit'];
- $this->_opened = $this->_inherit;
- }
- if (isset($conf['reopen'])) {
- $this->_reopen = $conf['reopen'];
- }
- if (isset($conf['maxLength'])) {
- $this->_maxLength = $conf['maxLength'];
- }
- if (!empty($conf['lineFormat'])) {
- $this->_lineFormat = str_replace(array_keys($this->_formatMap),
- array_values($this->_formatMap),
- $conf['lineFormat']);
- }
- if (!empty($conf['timeFormat'])) {
- $this->_timeFormat = $conf['timeFormat'];
- }
-
- $this->_id = md5(microtime());
- $this->_name = $name;
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
- }
-
- /**
- * Opens a connection to the system logger, if it has not already
- * been opened. This is implicitly called by log(), if necessary.
- * @access public
- */
- function open()
- {
- if (!$this->_opened || $this->_reopen) {
- $this->_opened = openlog($this->_ident, LOG_PID, $this->_name);
- }
-
- return $this->_opened;
- }
-
- /**
- * Closes the connection to the system logger, if it is open.
- * @access public
- */
- function close()
- {
- if ($this->_opened && !$this->_inherit) {
- closelog();
- $this->_opened = false;
- }
-
- return true;
- }
-
- /**
- * Sends $message to the currently open syslog connection. Calls
- * open() if necessary. Also passes the message along to any Log_observer
- * instances that are observing this Log.
- *
- * @param mixed $message String or object containing the message to log.
- * @param int $priority (optional) The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* If we need to (re)open the connection and open() fails, abort. */
- if ((!$this->_opened || $this->_reopen) && !$this->open()) {
- return false;
- }
-
- /* Extract the string representation of the message. */
- $message = $this->_extractMessage($message);
-
- /* Build a syslog priority value based on our current configuration. */
- $priority = $this->_toSyslog($priority);
- if ($this->_inherit) {
- $priority |= $this->_name;
- }
-
- /* Apply the configured line format to the message string. */
- $message = $this->_format($this->_lineFormat,
- strftime($this->_timeFormat),
- $priority, $message);
-
- /* Split the string into parts based on our maximum length setting. */
- $parts = str_split($message, $this->_maxLength);
- if ($parts === false) {
- return false;
- }
-
- foreach ($parts as $part) {
- if (!syslog($priority, $part)) {
- return false;
- }
- }
-
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return true;
- }
-
- /**
- * Converts a PEAR_LOG_* constant into a syslog LOG_* constant.
- *
- * This function exists because, under Windows, not all of the LOG_*
- * constants have unique values. Instead, the PEAR_LOG_* were introduced
- * for global use, with the conversion to the LOG_* constants kept local to
- * to the syslog driver.
- *
- * @param int $priority PEAR_LOG_* value to convert to LOG_* value.
- *
- * @return The LOG_* representation of $priority.
- *
- * @access private
- */
- function _toSyslog($priority)
- {
- static $priorities = array(
- PEAR_LOG_EMERG => LOG_EMERG,
- PEAR_LOG_ALERT => LOG_ALERT,
- PEAR_LOG_CRIT => LOG_CRIT,
- PEAR_LOG_ERR => LOG_ERR,
- PEAR_LOG_WARNING => LOG_WARNING,
- PEAR_LOG_NOTICE => LOG_NOTICE,
- PEAR_LOG_INFO => LOG_INFO,
- PEAR_LOG_DEBUG => LOG_DEBUG
- );
-
- /* If we're passed an unknown priority, default to LOG_INFO. */
- if (!is_int($priority) || !in_array($priority, $priorities)) {
- return LOG_INFO;
- }
-
- return $priorities[$priority];
- }
-
-}
+++ /dev/null
-<?php
-/**
- * $Header$
- *
- * @version $Revision: 278003 $
- * @package Log
- */
-
-/**
- * The Log_win class is a concrete implementation of the Log abstract
- * class that logs messages to a separate browser window.
- *
- * The concept for this log handler is based on part by Craig Davis' article
- * entitled "JavaScript Power PHP Debugging:
- *
- * http://www.zend.com/zend/tut/tutorial-DebugLib.php
- *
- * @author Jon Parise <jon@php.net>
- * @since Log 1.7.0
- * @package Log
- *
- * @example win.php Using the window handler.
- */
-class Log_win extends Log
-{
- /**
- * The name of the output window.
- * @var string
- * @access private
- */
- var $_name = 'LogWindow';
-
- /**
- * The title of the output window.
- * @var string
- * @access private
- */
- var $_title = 'Log Output Window';
-
- /**
- * Mapping of log priorities to styles.
- * @var array
- * @access private
- */
- var $_styles = array(
- PEAR_LOG_EMERG => 'color: red;',
- PEAR_LOG_ALERT => 'color: orange;',
- PEAR_LOG_CRIT => 'color: yellow;',
- PEAR_LOG_ERR => 'color: green;',
- PEAR_LOG_WARNING => 'color: blue;',
- PEAR_LOG_NOTICE => 'color: indigo;',
- PEAR_LOG_INFO => 'color: violet;',
- PEAR_LOG_DEBUG => 'color: black;'
- );
-
- /**
- * String buffer that holds line that are pending output.
- * @var array
- * @access private
- */
- var $_buffer = array();
-
- /**
- * Constructs a new Log_win object.
- *
- * @param string $name Ignored.
- * @param string $ident The identity string.
- * @param array $conf The configuration array.
- * @param int $level Log messages up to and including this level.
- * @access public
- */
- function Log_win($name, $ident = '', $conf = array(),
- $level = PEAR_LOG_DEBUG)
- {
- $this->_id = md5(microtime());
- $this->_name = str_replace(' ', '_', $name);
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
-
- if (isset($conf['title'])) {
- $this->_title = $conf['title'];
- }
- if (isset($conf['styles']) && is_array($conf['styles'])) {
- $this->_styles = $conf['styles'];
- }
- if (isset($conf['colors']) && is_array($conf['colors'])) {
- foreach ($conf['colors'] as $level => $color) {
- $this->_styles[$level] .= "color: $color;";
- }
- }
-
- register_shutdown_function(array(&$this, '_Log_win'));
- }
-
- /**
- * Destructor
- */
- function _Log_win()
- {
- if ($this->_opened || (count($this->_buffer) > 0)) {
- $this->close();
- }
- }
-
- /**
- * The first time open() is called, it will open a new browser window and
- * prepare it for output.
- *
- * This is implicitly called by log(), if necessary.
- *
- * @access public
- */
- function open()
- {
- if (!$this->_opened) {
- $win = $this->_name;
- $styles = $this->_styles;
-
- if (!empty($this->_ident)) {
- $identHeader = "$win.document.writeln('<th>Ident</th>')";
- } else {
- $identHeader = '';
- }
-
- echo <<< EOT
-<script language="JavaScript">
-$win = window.open('', '{$this->_name}', 'toolbar=no,scrollbars,width=600,height=400');
-$win.document.writeln('<html>');
-$win.document.writeln('<head>');
-$win.document.writeln('<title>{$this->_title}</title>');
-$win.document.writeln('<style type="text/css">');
-$win.document.writeln('body { font-family: monospace; font-size: 8pt; }');
-$win.document.writeln('td,th { font-size: 8pt; }');
-$win.document.writeln('td,th { border-bottom: #999999 solid 1px; }');
-$win.document.writeln('td,th { border-right: #999999 solid 1px; }');
-$win.document.writeln('tr { text-align: left; vertical-align: top; }');
-$win.document.writeln('td.l0 { $styles[0] }');
-$win.document.writeln('td.l1 { $styles[1] }');
-$win.document.writeln('td.l2 { $styles[2] }');
-$win.document.writeln('td.l3 { $styles[3] }');
-$win.document.writeln('td.l4 { $styles[4] }');
-$win.document.writeln('td.l5 { $styles[5] }');
-$win.document.writeln('td.l6 { $styles[6] }');
-$win.document.writeln('td.l7 { $styles[7] }');
-$win.document.writeln('</style>');
-$win.document.writeln('<script type="text/javascript">');
-$win.document.writeln('function scroll() {');
-$win.document.writeln(' body = document.getElementById("{$this->_name}");');
-$win.document.writeln(' body.scrollTop = body.scrollHeight;');
-$win.document.writeln('}');
-$win.document.writeln('<\/script>');
-$win.document.writeln('</head>');
-$win.document.writeln('<body id="{$this->_name}" onclick="scroll()">');
-$win.document.writeln('<table border="0" cellpadding="2" cellspacing="0">');
-$win.document.writeln('<tr><th>Time</th>');
-$identHeader
-$win.document.writeln('<th>Priority</th><th width="100%">Message</th></tr>');
-</script>
-EOT;
- $this->_opened = true;
- }
-
- return $this->_opened;
- }
-
- /**
- * Closes the output stream if it is open. If there are still pending
- * lines in the output buffer, the output window will be opened so that
- * the buffer can be drained.
- *
- * @access public
- */
- function close()
- {
- /*
- * If there are still lines waiting to be written, open the output
- * window so that we can drain the buffer.
- */
- if (!$this->_opened && (count($this->_buffer) > 0)) {
- $this->open();
- }
-
- if ($this->_opened) {
- $this->_writeln('</table>');
- $this->_writeln('</body></html>');
- $this->_drainBuffer();
- $this->_opened = false;
- }
-
- return ($this->_opened === false);
- }
-
- /**
- * Writes the contents of the output buffer to the output window.
- *
- * @access private
- */
- function _drainBuffer()
- {
- $win = $this->_name;
- foreach ($this->_buffer as $line) {
- echo "<script language='JavaScript'>\n";
- echo "$win.document.writeln('" . addslashes($line) . "');\n";
- echo "self.focus();\n";
- echo "</script>\n";
- }
-
- /* Now that the buffer has been drained, clear it. */
- $this->_buffer = array();
- }
-
- /**
- * Writes a single line of text to the output buffer.
- *
- * @param string $line The line of text to write.
- *
- * @access private
- */
- function _writeln($line)
- {
- /* Add this line to our output buffer. */
- $this->_buffer[] = $line;
-
- /* Buffer the output until this page's headers have been sent. */
- if (!headers_sent()) {
- return;
- }
-
- /* If we haven't already opened the output window, do so now. */
- if (!$this->_opened && !$this->open()) {
- return;
- }
-
- /* Drain the buffer to the output window. */
- $this->_drainBuffer();
- }
-
- /**
- * Logs $message to the output window. The message is also passed along
- * to any Log_observer instances that are observing this Log.
- *
- * @param mixed $message String or object containing the message to log.
- * @param string $priority The priority of the message. Valid
- * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
- * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
- * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
- * @return boolean True on success or false on failure.
- * @access public
- */
- function log($message, $priority = null)
- {
- /* If a priority hasn't been specified, use the default value. */
- if ($priority === null) {
- $priority = $this->_priority;
- }
-
- /* Abort early if the priority is above the maximum logging level. */
- if (!$this->_isMasked($priority)) {
- return false;
- }
-
- /* Extract the string representation of the message. */
- $message = $this->_extractMessage($message);
- $message = preg_replace('/\r\n|\n|\r/', '<br />', $message);
-
- list($usec, $sec) = explode(' ', microtime());
-
- /* Build the output line that contains the log entry row. */
- $line = '<tr>';
- $line .= sprintf('<td>%s.%s</td>',
- strftime('%H:%M:%S', $sec), substr($usec, 2, 2));
- if (!empty($this->_ident)) {
- $line .= '<td>' . $this->_ident . '</td>';
- }
- $line .= '<td>' . ucfirst($this->priorityToString($priority)) . '</td>';
- $line .= sprintf('<td class="l%d">%s</td>', $priority, $message);
- $line .= '</tr>';
-
- $this->_writeln($line);
-
- $this->_announce(array('priority' => $priority, 'message' => $message));
-
- return true;
- }
-
-}
+++ /dev/null
-=================
- The Log Package
-=================
-
---------------------
- User Documentation
---------------------
-
-:Author: Jon Parise
-:Contact: jon@php.net
-:Date: $Date: 2011-02-15 21:13:19 -0800 (Tue, 15 Feb 2011) $
-:Revision: $Revision: 308379 $
-
-.. contents:: Contents
-.. section-numbering::
-
-Using Log Handlers
-==================
-
-The Log package is implemented as a framework that supports the notion of
-backend-specific log handlers. The base logging object (defined by the `Log
-class`_) is primarily an abstract interface to the currently configured
-handler.
-
-A wide variety of handlers are distributed with the Log package, and, should
-none of them fit your application's needs, it's easy to `write your own`__.
-
-.. _Log class: http://cvs.php.net/viewvc.cgi/pear/Log/Log.php
-__ `Custom Handlers`_
-
-Creating a Log Object
----------------------
-There are three ways to create Log objects:
-
- - Using the ``Log::factory()`` method
- - Using the ``Log::singleton()`` method
- - Direct instantiation
-
-The Factory Method
-~~~~~~~~~~~~~~~~~~
-The ``Log::factory()`` method implements the `Factory Pattern`_. It allows
-for the parameterized construction of concrete Log instances at runtime. The
-first parameter to the ``Log::factory()`` method indicates the name of the
-concrete handler to create. The rest of the parameters will be passed on to
-the handler's constructor (see `Configuring a Handler`_ below).
-
-The new ``Log`` instance is returned by reference.
-
-::
-
- require_once 'Log.php';
-
- $console = Log::factory('console', '', 'TEST');
- $console->log('Logging to the console.');
-
- $file = Log::factory('file', 'out.log', 'TEST');
- $file->log('Logging to out.log.');
-
-.. _Factory Pattern: http://wikipedia.org/wiki/Factory_method_pattern
-
-The Singleton Method
-~~~~~~~~~~~~~~~~~~~~
-The ``Log::singleton()`` method implements the `Singleton Pattern`_. The
-singleton pattern ensures that only a single instance of a given log type and
-configuration is ever created. This has two benefits: first, it prevents
-duplicate ``Log`` instances from being constructed, and, second, it gives all
-of your code access to the same ``Log`` instance. The latter is especially
-important when logging to files because only a single file handler will need
-to be managed.
-
-The ``Log::singleton()`` method's parameters match the ``Log::factory()``
-method. The new ``Log`` instance is returned by reference.
-
-::
-
- require_once 'Log.php';
-
- /* Same construction parameters */
- $a = Log::singleton('console', '', 'TEST');
- $b = Log::singleton('console', '', 'TEST');
-
- if ($a === $b) {
- echo '$a and $b point to the same Log instance.' . "\n";
- }
-
- /* Different construction parameters */
- $c = Log::singleton('console', '', 'TEST1');
- $d = Log::singleton('console', '', 'TEST2');
-
- if ($c !== $d) {
- echo '$c and $d point to different Log instances.' . "\n";
- }
-
-.. _Singleton Pattern: http://wikipedia.org/wiki/Singleton_pattern
-
-Direct Instantiation
-~~~~~~~~~~~~~~~~~~~~
-It is also possible to directly instantiate concrete ``Log`` handler
-instances. However, this method is **not recommended** because it creates a
-tighter coupling between your application code and the Log package than is
-necessary. Use of `the factory method`_ or `the singleton method`_ is
-preferred.
-
-
-Configuring a Handler
----------------------
-A log handler's configuration is determined by the arguments used in its
-construction. Here's an overview of those parameters::
-
- /* Using the factory method ... */
- Log::factory($handler, $name, $ident, $conf, $maxLevel);
-
- /* Using the singleton method ... */
- Log::singleton($handler, $name, $ident, $conf, $maxLevel);
-
- /* Using direct instantiation ... */
- new Log_handler($name, $ident, $conf, $maxLevel);
-
-+---------------+-----------+-----------------------------------------------+
-| Parameter | Type | Description |
-+===============+===========+===============================================+
-| ``$handler`` | String | The type of Log handler to construct. This |
-| | | parameter is only available when `the factory |
-| | | method`_ or `the singleton method`_ are used. |
-+---------------+-----------+-----------------------------------------------+
-| ``$name`` | String | The name of the log resource to which the |
-| | | events will be logged. The use of this value |
-| | | is determined by the handler's implementation.|
-| | | It defaults to an empty string. |
-+---------------+-----------+-----------------------------------------------+
-| ``$ident`` | String | An identification string that will be included|
-| | | in all log events logged by this handler. |
-| | | This value defaults to an empty string and can|
-| | | be changed at runtime using the ``setIdent()``|
-| | | method. |
-+---------------+-----------+-----------------------------------------------+
-| ``$conf`` | Array | Associative array of key-value pairs that are |
-| | | used to specify any handler-specific settings.|
-+---------------+-----------+-----------------------------------------------+
-| ``$level`` | Integer | Log messages up to and including this level. |
-| | | This value defaults to ``PEAR_LOG_DEBUG``. |
-| | | See `Log Levels`_ and `Log Level Masks`_. |
-+---------------+-----------+-----------------------------------------------+
-
-
-Logging an Event
-----------------
-Events are logged using the ``log()`` method::
-
- $logger->log('Message', PEAR_LOG_NOTICE);
-
-The first argument contains the log event's message. Even though the event is
-always logged as a string, it is possible to pass an object to the ``log()``
-method. If the object implements a ``getString()`` method, a ``toString()``
-method or Zend Engine 2's special ``__toString()`` casting method, it will be
-used to determine the object's string representation. Otherwise, the
-`serialized`_ form of the object will be logged.
-
-The second, optional argument specifies the log event's priority. See the
-`Log Levels`_ table for the complete list of priorities. The default priority
-is PEAR_LOG_INFO.
-
-The ``log()`` method will return ``true`` if the event was successfully
-logged.
-
-"Shortcut" methods are also available for logging an event at a specific log
-level. See the `Log Levels`_ table for the complete list.
-
-.. _serialized: http://www.php.net/serialize
-
-
-Log Levels
-----------
-This table is ordered by highest priority (``PEAR_LOG_EMERG``) to lowest
-priority (``PEAR_LOG_DEBUG``).
-
-+-----------------------+---------------+-----------------------------------+
-| Level | Shortcut | Description |
-+=======================+===============+===================================+
-| ``PEAR_LOG_EMERG`` | ``emerg()`` | System is unusable |
-+-----------------------+---------------+-----------------------------------+
-| ``PEAR_LOG_ALERT`` | ``alert()`` | Immediate action required |
-+-----------------------+---------------+-----------------------------------+
-| ``PEAR_LOG_CRIT`` | ``crit()`` | Critical conditions |
-+-----------------------+---------------+-----------------------------------+
-| ``PEAR_LOG_ERR`` | ``err()`` | Error conditions |
-+-----------------------+---------------+-----------------------------------+
-| ``PEAR_LOG_WARNING`` | ``warning()`` | Warning conditions |
-+-----------------------+---------------+-----------------------------------+
-| ``PEAR_LOG_NOTICE`` | ``notice()`` | Normal but significant |
-+-----------------------+---------------+-----------------------------------+
-| ``PEAR_LOG_INFO`` | ``info()`` | Informational |
-+-----------------------+---------------+-----------------------------------+
-| ``PEAR_LOG_DEBUG`` | ``debug()`` | Debug-level messages |
-+-----------------------+---------------+-----------------------------------+
-
-
-Log Level Masks
----------------
-Defining a log level mask allows you to include and/or exclude specific levels
-of events from being logged. The ``$level`` construction parameter (see
-`Configuring a Handler`_) uses this mechanism to exclude log events below a
-certain priority, and it's possible to define more complex masks once the Log
-object has been constructed.
-
-Each priority has a specific mask associated with it. To compute a priority's
-mask, use the static ``Log::MASK()`` method::
-
- $mask = Log::MASK(PEAR_LOG_INFO);
-
-To compute the mask for all priorities up to, and including, a certain level,
-use the ``Log::MAX()`` static method::
-
- $mask = Log::MAX(PEAR_LOG_INFO);
-
-To compute the mask for all priorities greater than or equal to a certain
-level, use the ``Log::MIN()`` static method::
-
- $mask = Log::MIN(PEAR_LOG_INFO);
-
-The apply the mask, use the ``setMask()`` method::
-
- $logger->setMask($mask);
-
-Masks can be be combined using bitwise operations. To restrict logging to
-only those events marked as ``PEAR_LOG_NOTICE`` or ``PEAR_LOG_DEBUG``::
-
- $mask = Log::MASK(PEAR_LOG_NOTICE) | Log::MASK(PEAR_LOG_DEBUG);
- $logger->setMask($mask);
-
-For convenience, two special masks are predefined: ``PEAR_LOG_NONE`` and
-``PEAR_LOG_ALL``. ``PEAR_LOG_ALL`` is especially useful for excluding only
-specific priorities::
-
- $mask = PEAR_LOG_ALL ^ Log::MASK(PEAR_LOG_NOTICE);
- $logger->setMask($mask);
-
-It is also possible to retrieve and modify a Log object's existing mask::
-
- $mask = $logger->getMask() | Log::MASK(PEAR_LOG_INFO);
- $logger->setMask($mask);
-
-
-Log Line Format
----------------
-Most log handlers support configurable line formats. The following is a list
-of special tokens that will be expanded at runtime with contextual information
-related to the log event. Each token has an alternate shorthand notation, as
-well.
-
-+------------------+-----------+--------------------------------------------+
-| Token | Alternate | Description |
-+==================+===========+============================================+
-| ``%{timestamp}`` | ``%1$s`` | Timestamp. This is often configurable. |
-+------------------+-----------+--------------------------------------------+
-| ``%{ident}`` | ``%2$s`` | The log handler's identification string. |
-+------------------+-----------+--------------------------------------------+
-| ``%{priority}`` | ``%3$s`` | The log event's priority. |
-+------------------+-----------+--------------------------------------------+
-| ``%{message}`` | ``%4$s`` | The log event's message text. |
-+------------------+-----------+--------------------------------------------+
-| ``%{file}`` | ``%5$s`` | The full filename of the logging file. |
-+------------------+-----------+--------------------------------------------+
-| ``%{line}`` | ``%6$s`` | The line number on which the event occured.|
-+------------------+-----------+--------------------------------------------+
-| ``%{function}`` | ``%7$s`` | The function from which the event occurred.|
-+------------------+-----------+--------------------------------------------+
-| ``%{class}`` | ``%8$s`` | The class in which the event occurred. |
-+------------------+-----------+--------------------------------------------+
-
-
-Flushing Log Events
--------------------
-Some log handlers (such as `the console handler`_) support explicit
-"buffering". When buffering is enabled, log events won't actually be written
-to the output stream until the handler is closed. Other handlers (such as
-`the file handler`_) support implicit buffering because they use the operating
-system's IO routines, which may buffer the output.
-
-It's possible to force these handlers to flush their output, however, by
-calling their ``flush()`` method::
-
- $conf = array('buffering' => true);
- $logger = Log::singleton('console', '', 'test', $conf);
-
- for ($i = 0; $i < 10; $i++) {
- $logger->log('This event will be buffered.');
- }
-
- /* Flush all of the buffered log events. */
- $logger->flush();
-
- for ($i = 0; $i < 10; $i++) {
- $logger->log('This event will be buffered.');
- }
-
- /* Implicitly flush the buffered events on close. */
- $logger->close();
-
-At this time, the ``flush()`` method is only implemented by `the console
-handler`_, `the file handler`_, `the Firebug handler`_, and `the mail
-handler`_.
-
-
-Standard Log Handlers
-=====================
-
-The Console Handler
--------------------
-The Console handler outputs log events directly to the console. It supports
-output buffering and configurable string formats.
-
-Configuration
-~~~~~~~~~~~~~
-+-------------------+-----------+---------------+---------------------------+
-| Parameter | Type | Default | Description |
-+===================+===========+===============+===========================+
-| ``stream`` | File | STDOUT_ | The output stream to use. |
-+-------------------+-----------+---------------+---------------------------+
-| ``buffering`` | Boolean | False | Should the output be |
-| | | | buffered until shutdown? |
-+-------------------+-----------+---------------+---------------------------+
-| ``lineFormat`` | String | ``%1$s %2$s | `Log line format`_ |
-| | | [%3$s] %4$s`` | specification. |
-+-------------------+-----------+---------------+---------------------------+
-| ``timeFormat`` | String | ``%b %d | Time stamp format |
-| | | %H:%M:%S`` | (for strftime_). |
-+-------------------+-----------+---------------+---------------------------+
-
-.. _STDOUT: http://www.php.net/wrappers.php
-.. _strftime: http://www.php.net/strftime
-
-Example
-~~~~~~~
-::
-
- $logger = Log::singleton('console', '', 'ident');
- for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
- }
-
-
-The Display Handler
--------------------
-The Display handler simply prints the log events back to the browser. It
-respects the ``error_prepend_string`` and ``error_append_string`` `error
-handling values`_ and is useful when `logging from standard error handlers`_.
-
-Configuration
-~~~~~~~~~~~~~
-+-------------------+-----------+---------------+---------------------------+
-| Parameter | Type | Default | Description |
-+===================+===========+===============+===========================+
-| ``lineFormat`` | String | ``<b>%3$s</b>:| `Log line format`_ |
-| | | %4$s`` | specification. |
-+-------------------+-----------+---------------+---------------------------+
-| ``timeFormat`` | String | ``%b %d | Time stamp format |
-| | | %H:%M:%S`` | (for strftime_). |
-+-------------------+-----------+---------------+---------------------------+
-| ``error_prepend`` | String | PHP INI value | This string will be |
-| | | | prepended to the line |
-| | | | format. |
-+-------------------+-----------+---------------+---------------------------+
-| ``error_append`` | String | PHP INI value | This string will be |
-| | | | appended to the line |
-| | | | format. |
-+-------------------+-----------+---------------+---------------------------+
-| ``linebreak`` | String | ``<br />\n`` | This string is used to |
-| | | | represent a line break. |
-+-------------------+-----------+---------------+---------------------------+
-| ``rawText`` | Boolean | False | Should message text be |
-| | | | passed directly to the log|
-| | | | system? Otherwise, it |
-| | | | will be converted to an |
-| | | | HTML-safe representation. |
-+-------------------+-----------+---------------+---------------------------+
-
-.. _error handling values: http://www.php.net/errorfunc
-
-Example
-~~~~~~~
-::
-
- $conf = array('error_prepend' => '<font color="#ff0000"><tt>',
- 'error_append' => '</tt></font>');
- $logger = Log::singleton('display', '', '', $conf, PEAR_LOG_DEBUG);
- for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
- }
-
-
-The Error_Log Handler
----------------------
-The Error_Log handler sends log events to PHP's `error_log()`_ function.
-
-Configuration
-~~~~~~~~~~~~~
-+-------------------+-----------+---------------+---------------------------+
-| Parameter | Type | Default | Description |
-+===================+===========+===============+===========================+
-| ``destination`` | String | '' `(empty)` | Optional destination value|
-| | | | for `error_log()`_. See |
-| | | | `Error_Log Types`_ for |
-| | | | more details. |
-+-------------------+-----------+---------------+---------------------------+
-| ``extra_headers`` | String | '' `(empty)` | Additional headers to pass|
-| | | | to the `mail()`_ function |
-| | | | when the |
-| | | | ``PEAR_LOG_TYPE_MAIL`` |
-| | | | type is specified. |
-+-------------------+-----------+---------------+---------------------------+
-| ``lineFormat`` | String | ``%2$s: %4$s``| `Log line format`_ |
-| | | | specification. |
-+-------------------+-----------+---------------+---------------------------+
-| ``timeFormat`` | String | ``%b %d | Time stamp format |
-| | | %H:%M:%S`` | (for strftime_). |
-+-------------------+-----------+---------------+---------------------------+
-
-Error_Log Types
-~~~~~~~~~~~~~~~
-All of the available log types are detailed in the `error_log()`_ section of
-the PHP manual. For your convenience, the Log package also defines the
-following constants that can be used for the ``$name`` handler construction
-parameter.
-
-+---------------------------+-----------------------------------------------+
-| Constant | Description |
-+===========================+===============================================+
-| ``PEAR_LOG_TYPE_SYSTEM`` | Log events are sent to PHP's system logger, |
-| | which uses the operating system's logging |
-| | mechanism or a file (depending on the value |
-| | of the `error_log configuration directive`_). |
-+---------------------------+-----------------------------------------------+
-| ``PEAR_LOG_TYPE_MAIL`` | Log events are sent via email to the address |
-| | specified in the ``destination`` value. |
-+---------------------------+-----------------------------------------------+
-| ``PEAR_LOG_TYPE_DEBUG`` | Log events are sent through PHP's debugging |
-| | connection. This will only work if |
-| | `remote debugging`_ has been enabled. The |
-| | ``destination`` value is used to specify the |
-| | host name or IP address of the target socket. |
-+---------------------------+-----------------------------------------------+
-| ``PEAR_LOG_TYPE_FILE`` | Log events will be appended to the file named |
-| | by the ``destination`` value. |
-+---------------------------+-----------------------------------------------+
-| ``PEAR_LOG_TYPE_SAPI`` | Log events will be sent directly to the SAPI |
-| | logging handler. |
-+---------------------------+-----------------------------------------------+
-
-.. _error_log(): http://www.php.net/error_log
-.. _mail(): http://www.php.net/mail
-.. _error_log configuration directive: http://www.php.net/errorfunc#ini.error-log
-.. _remote debugging: http://www.php.net/install.configure#install.configure.enable-debugger
-
-Example
-~~~~~~~
-::
-
- $logger = Log::singleton('error_log', PEAR_LOG_TYPE_SYSTEM, 'ident');
- for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
- }
-
-
-The File Handler
-----------------
-The File handler writes log events to a text file using configurable string
-formats.
-
-Configuration
-~~~~~~~~~~~~~
-+-------------------+-----------+---------------+---------------------------+
-| Parameter | Type | Default | Description |
-+===================+===========+===============+===========================+
-| ``append`` | Boolean | True | Should new log entries be |
-| | | | append to an existing log |
-| | | | file, or should the a new |
-| | | | log file overwrite an |
-| | | | existing one? |
-+-------------------+-----------+---------------+---------------------------+
-| ``locking`` | Boolean | False | Should advisory file |
-| | | | locking (using flock_) be |
-| | | | used? |
-+-------------------+-----------+---------------+---------------------------+
-| ``mode`` | Integer | 0644 | Octal representation of |
-| | | | the log file's permissions|
-| | | | mode. |
-+-------------------+-----------+---------------+---------------------------+
-| ``dirmode`` | Integer | 0755 | Octal representation of |
-| | | | the file permission mode |
-| | | | that will be used when |
-| | | | creating directories that |
-| | | | do not already exist. |
-+-------------------+-----------+---------------+---------------------------+
-| ``eol`` | String | OS default | The end-of-line character |
-| | | | sequence. |
-+-------------------+-----------+---------------+---------------------------+
-| ``lineFormat`` | String | ``%1$s %2$s | `Log line format`_ |
-| | | [%3$s] %4$s`` | specification. |
-+-------------------+-----------+---------------+---------------------------+
-| ``timeFormat`` | String | ``%b %d | Time stamp format |
-| | | %H:%M:%S`` | (for strftime_). |
-+-------------------+-----------+---------------+---------------------------+
-
-.. _flock: http://www.php.net/flock
-.. _strftime: http://www.php.net/strftime
-
-The file handler will only attempt to set the ``mode`` value if it was
-responsible for creating the file.
-
-Example
-~~~~~~~
-::
-
- $conf = array('mode' => 0600, 'timeFormat' => '%X %x');
- $logger = Log::singleton('file', 'out.log', 'ident', $conf);
- for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
- }
-
-
-The Firebug Handler
--------------------
-The Firebug handler outputs log events to the Firebug_ console. It supports
-output buffering and configurable string formats.
-
-Configuration
-~~~~~~~~~~~~~
-+-------------------+-----------+---------------+---------------------------+
-| Parameter | Type | Default | Description |
-+===================+===========+===============+===========================+
-| ``buffering`` | Boolean | False | Should the output be |
-| | | | buffered until shutdown? |
-+-------------------+-----------+---------------+---------------------------+
-| ``lineFormat`` | String | ``%2$s [%3$s] | `Log line format`_ |
-| | | %4$s`` | specification. |
-+-------------------+-----------+---------------+---------------------------+
-| ``timeFormat`` | String | ``%b %d | Time stamp format |
-| | | %H:%M:%S`` | (for strftime_). |
-+-------------------+-----------+---------------+---------------------------+
-
-.. _Firebug: http://www.getfirebug.com/
-.. _strftime: http://www.php.net/strftime
-
-Example
-~~~~~~~
-::
-
- $logger = Log::singleton('firebug', '', 'ident');
- for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
- }
-
-
-The Mail Handler
-----------------
-
-The Mail handler aggregates a session's log events and sends them in the body
-of an email message using either the `PEAR Mail`_ package or PHP's native
-`mail()`_ function.
-
-If an empty ``mailBackend`` value is specified, the `mail()`_ function will be
-used instead of the `PEAR Mail`_ package.
-
-Multiple recipients can be specified by separating their email addresses with
-commas in the ``$name`` construction parameter.
-
-Configuration
-~~~~~~~~~~~~~
-+-------------------+-----------+---------------+---------------------------+
-| Parameter | Type | Default | Description |
-+===================+===========+===============+===========================+
-| ``from`` | String | sendmail_from | Value for the message's |
-| | | INI value | ``From:`` header. |
-+-------------------+-----------+---------------+---------------------------+
-| ``subject`` | String | ``[Log_mail] | Value for the message's |
-| | | Log message`` | ``Subject:`` header. |
-+-------------------+-----------+---------------+---------------------------+
-| ``preamble`` | String | `` `(empty)` | Preamble for the message. |
-+-------------------+-----------+---------------+---------------------------+
-| ``lineFormat`` | String | ``%1$s %2$s | `Log line format`_ |
-| | | [%3$s] %4$s`` | specification. |
-+-------------------+-----------+---------------+---------------------------+
-| ``timeFormat`` | String | ``%b %d | Time stamp format |
-| | | %H:%M:%S`` | (for strftime_). |
-+-------------------+-----------+---------------+---------------------------+
-| ``mailBackend`` | String | `` `(empty)` | Name of the Mail package |
-| | | | backend to use. |
-+-------------------+-----------+---------------+---------------------------+
-| ``mailParams`` | Array | `(empty)` | Array of parameters that |
-| | | | will be passed to the |
-| | | | Mail package backend. |
-+-------------------+-----------+---------------+---------------------------+
-
-.. _PEAR Mail: http://pear.php.net/package/Mail
-.. _mail(): http://www.php.net/mail
-
-Example
-~~~~~~~
-::
-
- $conf = array('subject' => 'Important Log Events');
- $logger = Log::singleton('mail', 'webmaster@example.com', 'ident', $conf);
- for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
- }
-
-
-The MDB2 Handler
-----------------
-The MDB2 handler is similar to `the SQL (DB) handler`_, but instead of using
-the PEAR DB package, it uses the `MDB2 database abstraction package`_.
-
-Configuration
-~~~~~~~~~~~~~
-+-------------------+-----------+---------------+---------------------------+
-| Parameter | Type | Default | Description |
-+===================+===========+===============+===========================+
-| ``dsn`` | Mixed | '' `(empty)` | A `Data Source Name`_. |
-| | | | |required| |
-+-------------------+-----------+---------------+---------------------------+
-| ``options`` | Array | ``persistent``| An array of `MDB2`_ |
-| | | | options. |
-+-------------------+-----------+---------------+---------------------------+
-| ``db`` | Object | NULL | An existing `MDB2`_ |
-| | | | object. If specified, |
-| | | | this object will be used, |
-| | | | and ``dsn`` will be |
-| | | | ignored. |
-+-------------------+-----------+---------------+---------------------------+
-| ``sequence`` | String | ``log_id`` | The name of the sequence |
-| | | | to use when generating |
-| | | | unique event IDs. Under |
-| | | | many databases, this will |
-| | | | be used as the name of |
-| | | | the sequence table. |
-+-------------------+-----------+---------------+---------------------------+
-| ``identLimit`` | Integer | 16 | The maximum length of the |
-| | | | ``ident`` string. |
-| | | | **Changing this value may |
-| | | | require updates to the SQL|
-| | | | schema, as well.** |
-+-------------------+-----------+---------------+---------------------------+
-| ``singleton`` | Boolean | false | Is true, use a singleton |
-| | | | database object using |
-| | | | `MDB2::singleton()`_. |
-+-------------------+-----------+---------------+---------------------------+
-
-.. _MDB2: http://pear.php.net/package/MDB2
-.. _MDB2 database abstraction package: MDB2_
-.. _MDB2::singleton(): http://pear.php.net/package/MDB2/docs/latest/MDB2/MDB2.html#methodsingleton
-
-The Null Handler
-----------------
-The Null handler simply consumes log events (akin to sending them to
-``/dev/null``). `Log level masks`_ are respected, and the event will still be
-sent to any registered `log observers`_.
-
-Example
-~~~~~~~
-::
-
- $logger = Log::singleton('null');
- for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
- }
-
-
-The SQL (DB) Handler
---------------------
-
-The SQL handler sends log events to a database using `PEAR's DB abstraction
-layer`_.
-
-**Note:** Due to the constraints of the default database schema, the SQL
-handler limits the length of the ``$ident`` string to sixteen (16) characters.
-This limit can be adjusted using the ``identLimit`` configuration parameter.
-
-The Log Table
-~~~~~~~~~~~~~
-The default SQL table used by this handler looks like this::
-
- CREATE TABLE log_table (
- id INT NOT NULL,
- logtime TIMESTAMP NOT NULL,
- ident CHAR(16) NOT NULL,
- priority INT NOT NULL,
- message VARCHAR(200),
- PRIMARY KEY (id)
- );
-
-This is the "lowest common denominator" that should work across all SQL
-compliant database. You may want to make database- or site-specific changes
-to this schema to support your specific needs, however. For example,
-`PostgreSQL`_ users may prefer to use a ``TEXT`` type for the ``message``
-field.
-
-.. _PostgreSQL: http://www.postgresql.org/
-
-Configuration
-~~~~~~~~~~~~~
-+-------------------+-----------+---------------+---------------------------+
-| Parameter | Type | Default | Description |
-+===================+===========+===============+===========================+
-| ``dsn`` | Mixed | '' `(empty)` | A `Data Source Name`_. |
-| | | | |required| |
-+-------------------+-----------+---------------+---------------------------+
-| ``sql`` | String | |sql-default| | SQL insertion statement. |
-+-------------------+-----------+---------------+---------------------------+
-| ``options`` | Array | ``persistent``| An array of `DB`_ options.|
-+-------------------+-----------+---------------+---------------------------+
-| ``db`` | Object | NULL | An existing `DB`_ object. |
-| | | | If specified, this object |
-| | | | will be used, and ``dsn`` |
-| | | | will be ignored. |
-+-------------------+-----------+---------------+---------------------------+
-| ``sequence`` | String | ``log_id`` | The name of the sequence |
-| | | | to use when generating |
-| | | | unique event IDs. Under |
-| | | | many databases, this will |
-| | | | be used as the name of |
-| | | | the sequence table. |
-+-------------------+-----------+---------------+---------------------------+
-| ``identLimit`` | Integer | 16 | The maximum length of the |
-| | | | ``ident`` string. |
-| | | | **Changing this value may |
-| | | | require updates to the SQL|
-| | | | schema, as well.** |
-+-------------------+-----------+---------------+---------------------------+
-
-The name of the database table to which the log entries will be written is
-specified using the ``$name`` construction parameter (see `Configuring a
-Handler`_).
-
-.. |sql-default| replace:: ``INSERT INTO $table (id, logtime, ident, priority, message) VALUES(?, CURRENT_TIMESTAMP, ?, ?, ?)``
-
-.. _DB: http://pear.php.net/package/DB
-.. _PEAR's DB abstraction layer: DB_
-.. _Data Source Name: http://pear.php.net/manual/en/package.database.db.intro-dsn.php
-
-Examples
-~~~~~~~~
-Using a `Data Source Name`_ to create a new database connection::
-
- $conf = array('dsn' => 'pgsql://jon@localhost+unix/logs');
- $logger = Log::singleton('sql', 'log_table', 'ident', $conf);
- for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
- }
-
-Using an existing `DB`_ object::
-
- require_once 'DB.php';
- $db = &DB::connect('pgsql://jon@localhost+unix/logs');
-
- $conf['db'] = $db;
- $logger = Log::singleton('sql', 'log_table', 'ident', $conf);
- for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
- }
-
-
-The Sqlite Handler
-------------------
-:Author: Bertrand Mansion
-
-The Sqlite handler sends log events to an Sqlite database using the `native
-PHP sqlite functions`_.
-
-It is faster than `the SQL (DB) handler`_ because requests are made directly
-to the database without using an abstraction layer. It is also interesting to
-note that Sqlite database files can be moved, copied, and deleted on your
-system just like any other files, which makes log management easier. Last but
-not least, using a database to log your events allows you to use SQL queries
-to create reports and statistics.
-
-When using a database and logging a lot of events, it is recommended to split
-the database into smaller databases. This is allowed by Sqlite, and you can
-later use the Sqlite `ATTACH`_ statement to query your log database files
-globally.
-
-If the database does not exist when the log is opened, sqlite will try to
-create it automatically. If the log table does not exist, it will also be
-automatically created. The table creation uses the following SQL request::
-
- CREATE TABLE log_table (
- id INTEGER PRIMARY KEY NOT NULL,
- logtime NOT NULL,
- ident CHAR(16) NOT NULL,
- priority INT NOT NULL,
- message
- );
-
-Configuration
-~~~~~~~~~~~~~
-+-------------------+-----------+---------------+---------------------------+
-| Parameter | Type | Default | Description |
-+===================+===========+===============+===========================+
-| ``filename`` | String | '' `(empty)` | Path to an Sqlite |
-| | | | database. |required| |
-+-------------------+-----------+---------------+---------------------------+
-| ``mode`` | Integer | 0666 | Octal mode used to open |
-| | | | the database. |
-+-------------------+-----------+---------------+---------------------------+
-| ``persistent`` | Boolean | false | Use a persistent |
-| | | | connection. |
-+-------------------+-----------+---------------+---------------------------+
-
-An already opened database connection can also be passed as parameter instead
-of the above configuration. In this case, closing the database connection is
-up to the user.
-
-.. _native PHP sqlite functions: http://www.php.net/sqlite
-.. _ATTACH: http://www.sqlite.org/lang.html#attach
-
-Examples
-~~~~~~~~
-Using a configuration to create a new database connection::
-
- $conf = array('filename' => 'log.db', 'mode' => 0666, 'persistent' => true);
- $logger = Log::factory('sqlite', 'log_table', 'ident', $conf);
- $logger->log('logging an event', PEAR_LOG_WARNING);
-
-Using an existing connection::
-
- $db = sqlite_open('log.db', 0666, $error);
- $logger = Log::factory('sqlite', 'log_table', 'ident', $db);
- $logger->log('logging an event', PEAR_LOG_WARNING);
- sqlite_close($db);
-
-
-The Syslog Handler
-------------------
-The Syslog handler sends log events to the system logging service (syslog on
-Unix-like environments or the Event Log on Windows systems). The events are
-sent using PHP's `syslog()`_ function.
-
-Configuration
-~~~~~~~~~~~~~
-+-------------------+-----------+---------------+---------------------------+
-| Parameter | Type | Default | Description |
-+===================+===========+===============+===========================+
-| ``inherit`` | Boolean | false | Inherit the current syslog|
-| | | | connection for this |
-| | | | process, or start a new |
-| | | | one via `openlog()`_? |
-+-------------------+-----------+---------------+---------------------------+
-| ``reopen`` | Boolean | false | Reopen the syslog |
-| | | | connection for each log |
-| | | | event? |
-+-------------------+-----------+---------------+---------------------------+
-| ``maxLength`` | Integer | 500 | Maximum message length |
-| | | | that will be sent to the |
-| | | | `syslog()`_ function. |
-| | | | Longer messages will be |
-| | | | split across multiple |
-| | | | `syslog()`_ calls. |
-+-------------------+-----------+---------------+---------------------------+
-| ``lineFormat`` | String | ``%4$s`` | `Log line format`_ |
-| | | | specification. |
-+-------------------+-----------+---------------+---------------------------+
-| ``timeFormat`` | String | ``%b %d | Time stamp format |
-| | | %H:%M:%S`` | (for strftime_). |
-+-------------------+-----------+---------------+---------------------------+
-
-Facilities
-~~~~~~~~~~
-+-------------------+-------------------------------------------------------+
-| Constant | Category Description |
-+===================+=======================================================+
-| ``LOG_AUTH`` | Security / authorization messages; ``LOG_AUTHPRIV`` is|
-| | preferred on systems where it is defined. |
-+-------------------+-------------------------------------------------------+
-| ``LOG_AUTHPRIV`` | Private security / authorization messages |
-+-------------------+-------------------------------------------------------+
-| ``LOG_CRON`` | Clock daemon (``cron`` and ``at``) |
-+-------------------+-------------------------------------------------------+
-| ``LOG_DAEMON`` | System daemon processes |
-+-------------------+-------------------------------------------------------+
-| ``LOG_KERN`` | Kernel messages |
-+-------------------+-------------------------------------------------------+
-| ``LOG_LOCAL0`` .. | Reserved for local use; **not** available under |
-| ``LOG_LOCAL7`` | Windows. |
-+-------------------+-------------------------------------------------------+
-| ``LOG_LPR`` | Printer subsystem |
-+-------------------+-------------------------------------------------------+
-| ``LOG_MAIL`` | Mail subsystem |
-+-------------------+-------------------------------------------------------+
-| ``LOG_NEWS`` | USENET news subsystem |
-+-------------------+-------------------------------------------------------+
-| ``LOG_SYSLOG`` | Internal syslog messages |
-+-------------------+-------------------------------------------------------+
-| ``LOG_USER`` | Generic user-level messages |
-+-------------------+-------------------------------------------------------+
-| ``LOG_UUCP`` | UUCP subsystem |
-+-------------------+-------------------------------------------------------+
-
-.. _syslog(): http://www.php.net/syslog
-.. _openlog(): http://www.php.net/openlog
-
-Example
-~~~~~~~
-::
-
- $logger = Log::singleton('syslog', LOG_LOCAL0, 'ident');
- for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
- }
-
-
-The Window Handler
-------------------
-The Window handler sends log events to a separate browser window. The
-original idea for this handler was inspired by Craig Davis' Zend.com article
-entitled `"JavaScript Power PHP Debugging"`_.
-
-Configuration
-~~~~~~~~~~~~~
-+-------------------+-----------+---------------+---------------------------+
-| Parameter | Type | Default | Description |
-+===================+===========+===============+===========================+
-| ``title`` | String | ``Log Output | The title of the output |
-| | | Window`` | window. |
-+-------------------+-----------+---------------+---------------------------+
-| ``styles`` | Array | `ROY G BIV`_ | Mapping of log priorities |
-| | | (high to low) | to CSS styles. |
-+-------------------+-----------+---------------+---------------------------+
-
-**Note:** The Window handler may not work reliably when PHP's `output
-buffering`_ system is enabled.
-
-.. _"JavaScript Power PHP Debugging": http://www.zend.com/zend/tut/tutorial-DebugLib.php
-.. _ROY G BIV: http://www.cis.rit.edu/
-.. _output buffering: http://www.php.net/outcontrol
-
-Example
-~~~~~~~
-::
-
- $conf = array('title' => 'Sample Log Output');
- $logger = Log::singleton('win', 'LogWindow', 'ident', $conf);
- for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
- }
-
-
-Composite Handlers
-==================
-It is often useful to log events to multiple handlers. The Log package
-provides a compositing system that marks this task trivial.
-
-Start by creating the individual log handlers::
-
- $console = Log::singleton('console', '', 'TEST');
- $file = Log::singleton('file', 'out.log', 'TEST');
-
-Then, construct a composite handler and add the individual handlers as
-children of the composite::
-
- $composite = Log::singleton('composite');
- $composite->addChild($console);
- $composite->addChild($file);
-
-The composite handler implements the standard ``Log`` interface so you can use
-it just like any of the other handlers::
-
- $composite->log('This event will be logged to both handlers.');
-
-Children can be removed from the composite when they're not longer needed::
-
- $composite->removeChild($file);
-
-
-Log Observers
-=============
-Log observers provide an implementation of the `observer pattern`_. In the
-content of the Log package, they provide a mechanism by which you can examine
-(i.e. observe) each event as it is logged. This allows the implementation of
-special behavior based on the contents of a log event. For example, the
-observer code could send an alert email if a log event contained the string
-``PANIC``.
-
-Creating a log observer involves implementing a subclass of the
-``Log_observer`` class. The subclass must override the base class's
-``notify()`` method. This method is passed a hash containing the event's
-priority and event. The subclass's implementation is free to act upon this
-information in any way it likes.
-
-Log observers are attached to ``Log`` instances via the ``attach()`` method::
-
- $observer = Log_observer::factory('yourType');
- $logger->attach($observer);
-
-Observers can be detached using the ``detach()`` method::
-
- $logger->detach($observer);
-
-At this time, no concrete ``Log_observer`` implementations are distributed
-with the Log package.
-
-.. _observer pattern: http://wikipedia.org/wiki/Observer_pattern
-
-
-Logging From Standard Error Handlers
-====================================
-
-Logging PHP Errors
-------------------
-PHP's default error handler can be overridden using the `set_error_handler()`_
-function. The custom error handling function can use a global Log instance to
-log the PHP errors.
-
-**Note:** Fatal PHP errors cannot be handled by a custom error handler at this
-time.
-
-::
-
- function errorHandler($code, $message, $file, $line)
- {
- global $logger;
-
- /* Map the PHP error to a Log priority. */
- switch ($code) {
- case E_WARNING:
- case E_USER_WARNING:
- $priority = PEAR_LOG_WARNING;
- break;
- case E_NOTICE:
- case E_USER_NOTICE:
- $priority = PEAR_LOG_NOTICE;
- break;
- case E_ERROR:
- case E_USER_ERROR:
- $priority = PEAR_LOG_ERR;
- break;
- default:
- $priority = PEAR_LOG_INFO;
- }
-
- $logger->log($message . ' in ' . $file . ' at line ' . $line,
- $priority);
- }
-
- set_error_handler('errorHandler');
- trigger_error('This is an information log message.', E_USER_NOTICE);
-
-.. _set_error_handler(): http://www.php.net/set_error_handler
-
-Logging PHP Assertions
-----------------------
-PHP allows user-defined `assert()`_ callback handlers. The assertion callback
-is configured using the `assert_options()`_ function.
-
-::
-
- function assertCallback($file, $line, $message)
- {
- global $logger;
-
- $logger->log($message . ' in ' . $file . ' at line ' . $line,
- PEAR_LOG_ALERT);
- }
-
- assert_options(ASSERT_CALLBACK, 'assertCallback');
- assert(false);
-
-.. _assert(): http://www.php.net/assert
-.. _assert_options(): http://www.php.net/assert_options
-
-Logging PHP Exceptions
-----------------------
-PHP 5 and later support the concept of `exceptions`_. A custom exception
-handler can be assigned using the `set_exception_handler()`_ function.
-
-::
-
- function exceptionHandler($exception)
- {
- global $logger;
-
- $logger->log($exception->getMessage(), PEAR_LOG_ALERT);
- }
-
- set_exception_handler('exceptionHandler');
- throw new Exception('Uncaught Exception');
-
-.. _exceptions: http://www.php.net/exceptions
-.. _set_exception_handler(): http://www.php.net/set_exception_handler
-
-Logging PEAR Errors
--------------------
-The Log package can be used with `PEAR::setErrorHandling()`_'s
-``PEAR_ERROR_CALLBACK`` mechanism by writing an error handling function that
-uses a global Log instance. Here's an example::
-
- function errorHandler($error)
- {
- global $logger;
-
- $message = $error->getMessage();
-
- if (!empty($error->backtrace[1]['file'])) {
- $message .= ' (' . $error->backtrace[1]['file'];
- if (!empty($error->backtrace[1]['line'])) {
- $message .= ' at line ' . $error->backtrace[1]['line'];
- }
- $message .= ')';
- }
-
- $logger->log($message, $error->code);
- }
-
- PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'errorHandler');
- PEAR::raiseError('This is an information log message.', PEAR_LOG_INFO);
-
-.. _PEAR::setErrorHandling(): http://pear.php.net/manual/en/core.pear.pear.seterrorhandling.php
-
-
-Custom Handlers
-===============
-There are times when the standard handlers aren't a perfect match for your
-needs. In those situations, the solution might be to write a custom handler.
-
-Using a Custom Handler
-----------------------
-Using a custom Log handler is very simple. Once written (see `Writing New
-Handlers`_ and `Extending Existing Handlers`_ below), you have the choice of
-placing the file in your PEAR installation's main ``Log/`` directory (usually
-something like ``/usr/local/lib/php/Log`` or ``C:\php\pear\Log``), where it
-can be found and use by any PHP application on the system, or placing the file
-somewhere in your application's local hierarchy and including it before the
-the custom Log object is constructed.
-
-Method 1: Handler in the Standard Location
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-After copying the handler file to your PEAR installation's ``Log/`` directory,
-simply treat the handler as if it were part of the standard distributed. If
-your handler is named ``custom`` (and therefore implemented by a class named
-``Log_custom``)::
-
- require_once 'Log.php';
-
- $logger = Log::factory('custom', '', 'CUSTOM');
-
-
-Method 2: Handler in a Custom Location
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If you prefer storing your handler in your application's local hierarchy,
-you'll need to include that file before you can create a Log instance based on
-it.
-
-::
-
- require_once 'Log.php';
- require_once 'LocalHandlers/custom.php';
-
- $logger = Log::factory('custom', '', 'CUSTOM');
-
-
-Writing New Handlers
---------------------
-Writing a new Log handler is as simple as authoring a new class that extends
-the ``Log`` class and that implements a relatively small set of standard
-methods.
-
-Every handler's class name must start with ``Log_`` in order for it to be
-recognized by the Log package.
-
-::
-
- class Log_custom extends Log
-
-The handler's constructor will be called with four parameters. These values
-are discussed in detail in the `Configuring a Handler`_ section.
-
-::
-
- Log_custom($name, $ident = '', $conf = array(), $level = PEAR_LOG_DEBUG)
-
-The constructor is responsible for configuring the handler based on these
-values. Handler-specific parameters are passed as part of the ``$conf``
-array. At a minimum, the handler's constructor must set the following values
-defined by the ``Log`` base class::
-
- $this->_id = md5(microtime());
- $this->_name = $name;
- $this->_ident = $ident;
- $this->_mask = Log::UPTO($level);
-
-The `Handler Methods`_ section below details the various standard methods that
-can be implemented by a log handler. The `Utility Methods`_ section describes
-some useful utility methods provided by the ``Log`` base class which may be
-useful when implementing a log handler.
-
-
-Extending Existing Handlers
----------------------------
-Extending existing handlers is very similar to `writing new handlers`_ with
-the exception that, instead of inheriting from the ``Log`` base class
-directly, the handler extends an existing handler's class. This is a useful
-way of adding some custom behavior to an existing handler without writing an
-entirely new class (in the spirit of object-oriented programming).
-
-For example, `the mail handler`_ could be extended to support sending messages
-with MIME-encoded attachments simply by authoring a new ``Log_mail_mime``
-class with a compliant constructor and a custom ``log()`` method. The rest of
-the standard methods would fall back on the ``Log_mail`` base class's
-implementations.
-
-Obviously, the specific details involved in extending an existing handler
-require a good working understanding of that handler's implementation.
-
-
-Handler Methods
----------------
-
-bool open()
-~~~~~~~~~~~
-The ``open()`` method is called to open the log resource for output. Handlers
-can call ``open()`` immediately upon construction or lazily at runtime
-(perhaps when the first log event is received).
-
-The ``Log`` base class provides a protected ``$_opened`` member variable which
-should be set to ``true`` when the log handler is opened and ``false`` when it
-is closed. Handler methods can inspect this value to determine whether or not
-the handler is currently open and ready for output.
-
-If the ``open()`` method fails to ready the handler for output, it should
-return ``false`` and set ``$this->_opened`` to ``false``.
-
-bool close()
-~~~~~~~~~~~~
-The ``close()`` method is called to close the log resource. This method is
-the analog of the ``open()`` method. It should be safe to call ``close()``
-even when the handler is not open for output.
-
-If the ``close()`` method fails to close the handler, it should return
-``false``. Otherwise, it should return ``true``. The ``$this->_opened``
-flag should also be updated appropriately.
-
-bool flush()
-~~~~~~~~~~~~
-The ``flush()`` method flushes any buffered log events, as described in
-`Flushing Log Events`_. The implementation of this method will be largely
-handler-specific. If the handler does not support buffered output,
-implementing this method is not necessary; the ``Log`` class's ``flush()``
-method will be called instead.
-
-bool log($message, $priority = null)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ``log()`` method is the core of every log handler. It is called whenever
-the user wishes to log an event. The implementation of this method is very
-handler-specific. It should return ``true`` or ``false``, depending on
-whether or not the message was successfully logged by the handler.
-
-The ``log()`` implementation should be sure to call `_announce()`__ whenever
-an event is successfully logged.
-
-.. __: `void _announce($event)`_
-
-Utility Methods
----------------
-These utility methods are provided by the ``Log`` base class and provide
-common, useful functionality to handler implementations.
-
-string _extractMessage($message)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-This method returns the string representation of the provided message data.
-
-If ``$message`` is an object, ``_extractMessage()`` will attempt to extract
-the message text using a known method (such as a `PEAR_Error`_ object's
-`getMessage()`_ method). If a known method, cannot be found, the serialized
-representation of the object will be returned.
-
-If the message data is already a string, it will be returned unchanged.
-
-.. _PEAR_Error: http://pear.php.net/manual/en/core.pear.pear-error.php
-.. _getMessage(): http://pear.php.net/manual/en/core.pear.pear-error.getmessage.php
-
-string _format($format, $timestamp, $priority, $message)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-This method produces a formatted log line based on a format string and a set
-of `tokens`_ representing the current log record and state.
-
-.. _tokens: `Log Line Format`_
-
-bool _isMasked($priority)
-~~~~~~~~~~~~~~~~~~~~~~~~~
-This method checks if the given priority is included in the handler's current
-level mask. This is useful for determining whether or not a log event should
-be written to the handler's log.
-
-void _announce($event)
-~~~~~~~~~~~~~~~~~~~~~~
-This method informs any registered `log observers`_ that a new event has been
-logged. ``$event`` is an array containing two named elements::
-
- array('priority' => $priority, 'message' => $message)
-
-``_announce()`` should be called from a handler's `log()`_ method whenever an
-event is successfully logged. Otherwise, registered observers will never
-become aware of the event.
-
-.. _log(): `bool log($message, $priority = null)`_
-
-.. |required| replace:: **[required]**
-
-.. vim: tabstop=4 shiftwidth=4 softtabstop=4 expandtab textwidth=78 ft=rst:
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-$console = &Log::singleton('console', '', 'TEST');
-$file = &Log::singleton('file', 'out.log', 'TEST');
-
-$composite = &Log::singleton('composite');
-$composite->addChild($console);
-$composite->addChild($file);
-
-$composite->log('This event will be logged to both handlers.');
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-$logger = &Log::singleton('console', '', 'ident');
-for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
-}
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-$conf = array('error_prepend' => '<font color="#ff0000"><tt>',
- 'error_append' => '</tt></font>');
-$logger = &Log::singleton('display', '', '', $conf, PEAR_LOG_DEBUG);
-for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
-}
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-$logger = &Log::singleton('error_log', PEAR_LOG_TYPE_SYSTEM, 'ident');
-for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
-}
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-$conf = array('mode' => 0600, 'timeFormat' => '%X %x');
-$logger = &Log::singleton('file', 'out.log', 'ident', $conf);
-for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
-}
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-$logger = &Log::singleton('firebug', '',
- 'PHP',
- array('buffering' => true),
- PEAR_LOG_DEBUG);
-
-for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
-}
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-$conf = array('subject' => 'Important Log Events');
-$logger = &Log::singleton('mail', 'webmaster@example.com', 'ident', $conf);
-for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
-}
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-$logger = &Log::singleton('null');
-for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
-}
+++ /dev/null
-<?php
-
-require_once 'Log/observer.php';
-
-class Log_observer_mail extends Log_observer
-{
- var $_to = '';
- var $_subject = '';
- var $_pattern = '';
-
- function Log_observer_mail($priority, $conf)
- {
- /* Call the base class constructor. */
- $this->Log_observer($priority);
-
- /* Configure the observer. */
- $this->_to = $conf['to'];
- $this->_subject = $conf['subject'];
- $this->_pattern = $conf['pattern'];
- }
-
- function notify($event)
- {
- if (preg_match($this->_pattern, $event['message']) != 0) {
- mail($this->_to, $this->_subject, $event['message']);
- }
- }
-}
-
-?>
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-function errorHandler($error)
-{
- global $logger;
-
- $message = $error->getMessage();
-
- if (!empty($error->backtrace[1]['file'])) {
- $message .= ' (' . $error->backtrace[1]['file'];
- if (!empty($error->backtrace[1]['line'])) {
- $message .= ' at line ' . $error->backtrace[1]['line'];
- }
- $message .= ')';
- }
-
- $logger->log($message, $error->code);
-}
-
-$logger = &Log::singleton('console', '', 'ident');
-
-PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'errorHandler');
-PEAR::raiseError('This is an information log message.', PEAR_LOG_INFO);
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-function errorHandler($code, $message, $file, $line)
-{
- global $logger;
-
- /* Map the PHP error to a Log priority. */
- switch ($code) {
- case E_WARNING:
- case E_USER_WARNING:
- $priority = PEAR_LOG_WARNING;
- break;
- case E_NOTICE:
- case E_USER_NOTICE:
- $priority = PEAR_LOG_NOTICE;
- break;
- case E_ERROR:
- case E_USER_ERROR:
- $priority = PEAR_LOG_ERR;
- break;
- default:
- $priotity = PEAR_LOG_INFO;
- }
-
- $logger->log($message . ' in ' . $file . ' at line ' . $line,
- $priority);
-}
-
-$logger = &Log::singleton('console', '', 'ident');
-
-set_error_handler('errorHandler');
-trigger_error('This is an information log message.', E_USER_NOTICE);
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-$conf = array('dsn' => 'pgsql://jon@localhost+unix/logs');
-$logger = &Log::singleton('sql', 'log_table', 'ident', $conf);
-for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
-}
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-/* Creating a new database connection. */
-$conf = array('filename' => 'log.db', 'mode' => 0666, 'persistent' => true);
-$logger =& Log::factory('sqlite', 'log_table', 'ident', $conf);
-$logger->log('logging an event', PEAR_LOG_WARNING);
-
-/* Using an existing database connection. */
-$db = sqlite_open('log.db', 0666, $error);
-$logger =& Log::factory('sqlite', 'log_table', 'ident', $db);
-$logger->log('logging an event', PEAR_LOG_WARNING);
-sqlite_close($db);
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-$logger = &Log::singleton('syslog', LOG_LOCAL0, 'ident');
-for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
-}
+++ /dev/null
-<?php
-
-require_once 'Log.php';
-
-$conf = array('title' => 'Sample Log Output');
-$logger = &Log::singleton('win', 'LogWindow', 'ident', $conf);
-for ($i = 0; $i < 10; $i++) {
- $logger->log("Log entry $i");
-}
+++ /dev/null
--- $Id: log.sql 215378 2006-06-26 15:25:35Z jon $
-
-CREATE TABLE log_table (
- id INT NOT NULL,
- logtime TIMESTAMP NOT NULL,
- ident CHAR(16) NOT NULL,
- priority INT NOT NULL,
- message VARCHAR(200),
- PRIMARY KEY (id)
-);
+++ /dev/null
---TEST--
-Log: Backtrace Vars
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$conf = array('lineFormat' => '%6$s [%8$s::%7$s] %4$s');
-$logger = Log::singleton('console', '', 'ident', $conf);
-
-# Top-level Logger
-#
-$logger->log("Top-level Logger - log()");
-$logger->info("Top-level Logger - info()");
-
-# Function Logger
-#
-function functionLog($logger)
-{
- $logger->log("Function Logger - log()");
- $logger->info("Function Logger - info()");
-}
-
-functionLog($logger);
-
-# Class Logger
-#
-class ClassLogger
-{
- function log($logger)
- {
- $logger->log("Class Logger - log()");
- $logger->info("Class Logger - info()");
- }
-}
-
-$classLogger = new ClassLogger();
-$classLogger->log($logger);
-
-# Composite Logger
-#
-$composite = Log::singleton('composite');
-$composite->addChild($logger);
-
-$composite->log("Composite Logger - log()");
-$composite->info("Composite Logger - info()");
-
-# Composite Logger via Class
-#
-$classLogger->log($composite);
-
-# Deeper Backtrace
-function deeperLog($logger)
-{
- $logger->log("Deeper Logger - log()");
- $logger->info("Deeper Logger - info()");
-}
-
-$logger->setBacktraceDepth(1);
-deeperLog($logger);
-
---EXPECT--
-10 [::(none)] Top-level Logger - log()
-11 [::(none)] Top-level Logger - info()
-17 [::functionLog] Function Logger - log()
-18 [::functionLog] Function Logger - info()
-29 [ClassLogger::log] Class Logger - log()
-30 [ClassLogger::log] Class Logger - info()
-42 [::(none)] Composite Logger - log()
-43 [::(none)] Composite Logger - info()
-29 [ClassLogger::log] Class Logger - log()
-30 [ClassLogger::log] Class Logger - info()
-57 [::(none)] Deeper Logger - log()
-53 [::deeperLog] Deeper Logger - info()
+++ /dev/null
---TEST--
-Log: Composite Handler
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-function printOpenStates($children) {
- foreach ($children as $child) {
- $state = ($child->_opened) ? 'OPEN' : 'CLOSED';
- echo "$child->_ident : $state\n";
- }
-}
-
-function printIdents($children) {
- foreach ($children as $child) {
- echo "$child->_ident\n";
- }
-}
-
-function testPriority($composite, $priority) {
- $name = Log::priorityToString($priority);
- $success = $composite->log($name, $priority);
- echo "$name : " . (($success) ? 'GOOD' : 'BAD') . "\n";
-}
-
-/* Create three handlers with different priority masks. */
-$conf = array('lineFormat' => '%2$s [%3$s] %4$s');
-$children = array(
- Log::singleton('console', '', 'CONSOLE1', $conf),
- Log::singleton('console', '', 'CONSOLE2', $conf),
- Log::singleton('console', '', 'CONSOLE3', $conf)
-);
-
-$children[0]->setMask(Log::MASK(PEAR_LOG_DEBUG));
-$children[1]->setMask(Log::MASK(PEAR_LOG_INFO));
-$children[2]->setMask(Log::MASK(PEAR_LOG_ERR));
-
-$composite = Log::singleton('composite');
-$composite->addChild($children[0]);
-$composite->addChild($children[1]);
-$composite->addChild($children[2]);
-
-/* Verify that all of the children are initially closed. */
-printOpenStates($children);
-
-/* Verify that the composite handler's open() opens all of the children. */
-$composite->open();
-printOpenStates($children);
-
-/* Verify that the composite handler's close() closes all of the children. */
-$composite->close();
-printOpenStates($children);
-
-/* Verify the log results at different priorities. */
-testPriority($composite, PEAR_LOG_DEBUG);
-printOpenStates($children);
-testPriority($composite, PEAR_LOG_INFO);
-printOpenStates($children);
-testPriority($composite, PEAR_LOG_ERR);
-printOpenStates($children);
-
-/* Verify that changing the ident affects all children. */
-$composite->setIdent('IDENT');
-printIdents($children);
-
---EXPECT--
-CONSOLE1 : CLOSED
-CONSOLE2 : CLOSED
-CONSOLE3 : CLOSED
-CONSOLE1 : OPEN
-CONSOLE2 : OPEN
-CONSOLE3 : OPEN
-CONSOLE1 : CLOSED
-CONSOLE2 : CLOSED
-CONSOLE3 : CLOSED
-CONSOLE1 [debug] debug
-debug : GOOD
-CONSOLE1 : OPEN
-CONSOLE2 : CLOSED
-CONSOLE3 : CLOSED
-CONSOLE2 [info] info
-info : GOOD
-CONSOLE1 : OPEN
-CONSOLE2 : OPEN
-CONSOLE3 : CLOSED
-CONSOLE3 [error] error
-error : GOOD
-CONSOLE1 : OPEN
-CONSOLE2 : OPEN
-CONSOLE3 : OPEN
-IDENT
-IDENT
-IDENT
+++ /dev/null
---TEST--
-Log: Console Handler
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$conf = array('lineFormat' => '%2$s [%3$s] %4$s');
-$logger = Log::singleton('console', '', 'ident', $conf);
-for ($i = 0; $i < 3; $i++) {
- $logger->log("Log entry $i");
-}
-
-echo "\n[Buffering / Flush Test]\n";
-$conf = array('lineFormat' => '%2$s [%3$s] %4$s', 'buffering' => true);
-$buffered_logger = Log::singleton('console', '', 'buffered', $conf);
-for ($i = 0; $i < 3; $i++) {
- $buffered_logger->log("Pre-flush buffered log entry $i");
-}
-echo "Pre-flush\n";
-$buffered_logger->flush();
-echo "Post-flush\n";
-for ($i = 0; $i < 3; $i++) {
- $buffered_logger->log("Post-flush buffered log entry $i");
-}
-echo "Shutdown\n";
-$buffered_logger->close();
-
---EXPECT--
-ident [info] Log entry 0
-ident [info] Log entry 1
-ident [info] Log entry 2
-
-[Buffering / Flush Test]
-Pre-flush
-buffered [info] Pre-flush buffered log entry 0
-buffered [info] Pre-flush buffered log entry 1
-buffered [info] Pre-flush buffered log entry 2
-Post-flush
-Shutdown
-buffered [info] Post-flush buffered log entry 0
-buffered [info] Post-flush buffered log entry 1
-buffered [info] Post-flush buffered log entry 2
+++ /dev/null
---TEST--
-Log: Display Handler
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-function test($name, $conf)
-{
- echo "\nTesting $name Configuration\n";
- echo "------------------------------------------------------\n";
-
- $logger = Log::factory('display', '', $name, $conf);
-
- $logger->log("Info", PEAR_LOG_INFO);
- $logger->log("Error", PEAR_LOG_ERR);
- $logger->log("Debug", PEAR_LOG_DEBUG);
- $logger->log("Multi\nLine\nEntry", PEAR_LOG_INFO);
-
- echo "\n";
-}
-
-test('Default', array());
-test('Line Break', array('linebreak' => "\n"));
-test('Format', array('lineFormat' => '<!-- %4$s -->'));
-test('Prepend / Append', array('error_prepend' => '<tt>',
- 'error_append' => '</tt>'));
-
---EXPECT--
-Testing Default Configuration
-------------------------------------------------------
-<b>info</b>: Info<br />
-<b>error</b>: Error<br />
-<b>debug</b>: Debug<br />
-<b>info</b>: Multi<br />
-Line<br />
-Entry<br />
-
-
-Testing Line Break Configuration
-------------------------------------------------------
-<b>info</b>: Info
-<b>error</b>: Error
-<b>debug</b>: Debug
-<b>info</b>: Multi<br />
-Line<br />
-Entry
-
-
-Testing Format Configuration
-------------------------------------------------------
-<!-- Info --><br />
-<!-- Error --><br />
-<!-- Debug --><br />
-<!-- Multi<br />
-Line<br />
-Entry --><br />
-
-
-Testing Prepend / Append Configuration
-------------------------------------------------------
-<tt><b>info</b>: Info</tt><br />
-<tt><b>error</b>: Error</tt><br />
-<tt><b>debug</b>: Debug</tt><br />
-<tt><b>info</b>: Multi<br />
-Line<br />
-Entry</tt><br />
+++ /dev/null
---TEST--
-Log: Error_Log Handler
---SKIPIF--
-<?php if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') die("skip\n"); ?>
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-/* Default Configuration */
-$logger1 = Log::singleton('error_log', PEAR_LOG_TYPE_SYSTEM, 'ident');
-for ($i = 0; $i < 3; $i++) {
- $logger1->log("Log entry $i");
-}
-
-/* Custom line format */
-$conf = array('lineFormat' => '%2$s: [%3$s] %4$s');
-$logger2 = Log::singleton('error_log', PEAR_LOG_TYPE_SYSTEM, 'ident', $conf);
-for ($i = 0; $i < 3; $i++) {
- $logger2->log("Log entry $i");
-}
-
---EXPECT--
-ident: Log entry 0
-ident: Log entry 1
-ident: Log entry 2
-ident: [info] Log entry 0
-ident: [info] Log entry 1
-ident: [info] Log entry 2
+++ /dev/null
---TEST--
-Log: _extractMessage() [Zend Engine 2.0]
---SKIPIF--
-<?php
-if (version_compare(zend_version(), "2.0.0", "<") ||
- version_compare(zend_version(), "2.2.0", ">=")) die('skip');
-?>
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$conf = array('lineFormat' => '%2$s [%3$s] %4$s');
-$logger = Log::singleton('console', '', 'ident', $conf);
-
-/* Logging a regular string. */
-$logger->log('String');
-
-/* Logging a bare object. */
-class BareObject {}
-$logger->log(new BareObject());
-
-/* Logging an object with a getMessage() method. */
-class GetMessageObject { function getMessage() { return "getMessage"; } }
-$logger->log(new GetMessageObject());
-
-/* Logging an object with a toString() method. */
-class ToStringObject { function toString() { return "toString"; } }
-$logger->log(new ToStringObject());
-
-/* Logging an object with a __toString() method using casting. */
-class CastableObject { function __toString() { return "__toString"; } }
-$logger->log(new CastableObject());
-
-/* Logging a PEAR_Error object. */
-require_once 'PEAR.php';
-$logger->log(new PEAR_Error('PEAR_Error object', 100));
-
-/* Logging an array. */
-$logger->log(array(1, 2, 'three' => 3));
-
-/* Logging an array with scalar 'message' keys. */
-$logger->log(array('message' => 'Message Key'));
-$logger->log(array('message' => 50));
-
-/* Logging an array with a non-scalar 'message' key. */
-$logger->log(array('message' => array(1, 2, 3)));
-
---EXPECT--
-ident [info] String
-ident [info] BareObject::__set_state(array(
-))
-ident [info] getMessage
-ident [info] toString
-ident [info] Object id #2
-ident [info] PEAR_Error object
-ident [info] array (
- 0 => 1,
- 1 => 2,
- 'three' => 3,
-
-ident [info] Message Key
-ident [info] 50
-ident [info] array (
- 0 => 1,
- 1 => 2,
- 2 => 3,
-)
+++ /dev/null
---TEST--
-Log: _extractMessage() [Zend Engine 2.2]
---SKIPIF--
-<?php if (version_compare(zend_version(), "2.2.0", "<")) die('skip'); ?>
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$conf = array('lineFormat' => '%2$s [%3$s] %4$s');
-$logger = Log::singleton('console', '', 'ident', $conf);
-
-/* Logging a regular string. */
-$logger->log('String');
-
-/* Logging a bare object. */
-class BareObject {}
-$logger->log(new BareObject());
-
-/* Logging an object with a getMessage() method. */
-class GetMessageObject { function getMessage() { return "getMessage"; } }
-$logger->log(new GetMessageObject());
-
-/* Logging an object with a toString() method. */
-class ToStringObject { function toString() { return "toString"; } }
-$logger->log(new ToStringObject());
-
-/* Logging an object with a __toString() method using casting. */
-class CastableObject { function __toString() { return "__toString"; } }
-$logger->log(new CastableObject());
-
-/* Logging a PEAR_Error object. */
-require_once 'PEAR.php';
-$logger->log(new PEAR_Error('PEAR_Error object', 100));
-
-/* Logging an array. */
-$logger->log(array(1, 2, 'three' => 3));
-
-/* Logging an array with scalar 'message' keys. */
-$logger->log(array('message' => 'Message Key'));
-$logger->log(array('message' => 50));
-
-/* Logging an array with a non-scalar 'message' key. */
-$logger->log(array('message' => array(1, 2, 3)));
-
---EXPECT--
-ident [info] String
-ident [info] BareObject::__set_state(array(
-))
-ident [info] getMessage
-ident [info] toString
-ident [info] __toString
-ident [info] PEAR_Error object
-ident [info] array (
- 0 => 1,
- 1 => 2,
- 'three' => 3,
-)
-ident [info] Message Key
-ident [info] 50
-ident [info] array (
- 0 => 1,
- 1 => 2,
- 2 => 3,
-)
+++ /dev/null
---TEST--
-Log: Factory
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$console1 = Log::factory('console');
-$console2 = Log::factory('console');
-
-if (is_a($console1, 'Log_console') && is_a($console2, 'Log_console'))
-{
- echo "Two Log_console objects.\n";
-}
-
-if ($console1->_id != $console2->_id) {
- echo "The objects have different IDs.\n";
-}
-
---EXPECT--
-Two Log_console objects.
-The objects have different IDs.
+++ /dev/null
---TEST--
-Log: File Handler
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$filename = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test.log';
-if (file_exists($filename)) unlink($filename);
-
-/* Write some entries to the log file. */
-$conf = array('lineFormat' => '%2$s [%3$s] %4$s');
-$logger = Log::singleton('file', $filename, '', $conf);
-
-for ($i = 0; $i < 3; $i++) {
- $logger->log("Log entry $i");
-}
-$logger->close();
-
-/* Dump the contents of the log file. */
-echo file_get_contents($filename);
-
-/* Clean up. */
-if (file_exists($filename)) unlink($filename);
-
---EXPECT--
- [info] Log entry 0
- [info] Log entry 1
- [info] Log entry 2
+++ /dev/null
---TEST--
-Log: Firebug Handler
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$conf = array();
-print "** UNBUFFERED **\n";
-$logger = Log::singleton('firebug', '', 'PHP', $conf);
-$logger->log('Debug', PEAR_LOG_DEBUG);
-$logger->log('Info', PEAR_LOG_INFO);
-$logger->log('Notice', PEAR_LOG_NOTICE);
-$logger->log('Warning', PEAR_LOG_WARNING);
-$logger->log('Error', PEAR_LOG_ERR);
-$logger->log('Critical', PEAR_LOG_CRIT);
-$logger->log('Alert', PEAR_LOG_ALERT);
-$logger->log('Emergency', PEAR_LOG_EMERG);
-unset($logger);
-
-print "\n** START BUFFERING **\n";
-$conf = array('buffering' => true);
-$logger = Log::singleton('firebug', '', 'PHP', $conf);
-$logger->log('Debug', PEAR_LOG_DEBUG);
-$logger->log('Info', PEAR_LOG_INFO);
-$logger->log('Notice', PEAR_LOG_NOTICE);
-$logger->log('Warning', PEAR_LOG_WARNING);
-$logger->flush();
-print "** FLUSHED **\n";
-print "** REST OF BUFFERED **\n";
-$logger->log('Error', PEAR_LOG_ERR);
-$logger->log('Critical', PEAR_LOG_CRIT);
-$logger->log('Alert', PEAR_LOG_ALERT);
-$logger->log('Emergency', PEAR_LOG_EMERG);
---EXPECT--
-** UNBUFFERED **
-<script type="text/javascript">
-if (('console' in window) && ('firebug' in console)) {
- console.debug("PHP [debug] Debug");
-}
-</script>
-<script type="text/javascript">
-if (('console' in window) && ('firebug' in console)) {
- console.info("PHP [info] Info");
-}
-</script>
-<script type="text/javascript">
-if (('console' in window) && ('firebug' in console)) {
- console.info("PHP [notice] Notice");
-}
-</script>
-<script type="text/javascript">
-if (('console' in window) && ('firebug' in console)) {
- console.warn("PHP [warning] Warning");
-}
-</script>
-<script type="text/javascript">
-if (('console' in window) && ('firebug' in console)) {
- console.error("PHP [error] Error");
-}
-</script>
-<script type="text/javascript">
-if (('console' in window) && ('firebug' in console)) {
- console.error("PHP [critical] Critical");
-}
-</script>
-<script type="text/javascript">
-if (('console' in window) && ('firebug' in console)) {
- console.error("PHP [alert] Alert");
-}
-</script>
-<script type="text/javascript">
-if (('console' in window) && ('firebug' in console)) {
- console.error("PHP [emergency] Emergency");
-}
-</script>
-
-** START BUFFERING **
-<script type="text/javascript">
-if (('console' in window) && ('firebug' in console)) {
- console.debug("PHP [debug] Debug");
- console.info("PHP [info] Info");
- console.info("PHP [notice] Notice");
- console.warn("PHP [warning] Warning");
-}
-</script>
-** FLUSHED **
-** REST OF BUFFERED **
-<script type="text/javascript">
-if (('console' in window) && ('firebug' in console)) {
- console.error("PHP [error] Error");
- console.error("PHP [critical] Critical");
- console.error("PHP [alert] Alert");
- console.error("PHP [emergency] Emergency");
-}
-</script>
+++ /dev/null
---TEST--
-Log: Line Format
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$conf = array('lineFormat' => '%{timestamp} %{ident} %{priority} %{message} %{file} %{line} %{function} %{class}');
-$logger = Log::singleton('console', '', 'ident', $conf);
-$logger->log('Message');
-
---EXPECTREGEX--
-^\w{3} \d+ \d{2}:\d{2}:\d{2} ident info Message .*format\.php \d+ [\(\)\w]+$
+++ /dev/null
---TEST--
-Log: Levels
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-function verify($exp, $msg)
-{
- echo $msg . ': ';
- echo ($exp) ? 'pass' : 'fail';
- echo "\n";
-}
-
-function testLevels($mask)
-{
- echo "Mask: " . ($mask & 0xffff) . "\n";
-
- for ($priority = PEAR_LOG_EMERG; $priority <= PEAR_LOG_DEBUG; $priority++) {
- $masked = (Log::MASK($priority) & $mask);
- echo "Priority $priority: ";
- echo($masked) ? "masked\n" : "unmasked\n";
- }
-
- echo "\n";
-}
-
-testLevels(PEAR_LOG_NONE);
-testLevels(PEAR_LOG_ALL);
-testLevels(Log::MIN(PEAR_LOG_WARNING));
-testLevels(Log::MAX(PEAR_LOG_WARNING));
-
---EXPECT--
-Mask: 0
-Priority 0: unmasked
-Priority 1: unmasked
-Priority 2: unmasked
-Priority 3: unmasked
-Priority 4: unmasked
-Priority 5: unmasked
-Priority 6: unmasked
-Priority 7: unmasked
-
-Mask: 65535
-Priority 0: masked
-Priority 1: masked
-Priority 2: masked
-Priority 3: masked
-Priority 4: masked
-Priority 5: masked
-Priority 6: masked
-Priority 7: masked
-
-Mask: 65520
-Priority 0: unmasked
-Priority 1: unmasked
-Priority 2: unmasked
-Priority 3: unmasked
-Priority 4: masked
-Priority 5: masked
-Priority 6: masked
-Priority 7: masked
-
-Mask: 31
-Priority 0: masked
-Priority 1: masked
-Priority 2: masked
-Priority 3: masked
-Priority 4: masked
-Priority 5: unmasked
-Priority 6: unmasked
-Priority 7: unmasked
+++ /dev/null
---TEST--
-Log: Masks
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-/* Levels */
-for ($level = PEAR_LOG_EMERG; $level <= PEAR_LOG_DEBUG; $level++) {
-
- printf("Level %d: 0x%08x, 0x%08x, 0x%08x\n",
- $level,
- Log::MASK($level),
- Log::MIN($level),
- Log::MAX($level));
-}
-echo "\n";
-
-/* Mask */
-$conf = array('lineFormat' => '%2$s [%3$s] %4$s');
-$logger = Log::singleton('console', '', 'ident', $conf);
-
-$logger->setMask(Log::MAX(PEAR_LOG_INFO));
-$logger->info('Info 1');
-$logger->setMask(Log::MAX(PEAR_LOG_ERR));
-$logger->info('Info 2');
-
---EXPECT--
-Level 0: 0x00000001, 0xffffffff, 0x00000001
-Level 1: 0x00000002, 0xfffffffe, 0x00000003
-Level 2: 0x00000004, 0xfffffffc, 0x00000007
-Level 3: 0x00000008, 0xfffffff8, 0x0000000f
-Level 4: 0x00000010, 0xfffffff0, 0x0000001f
-Level 5: 0x00000020, 0xffffffe0, 0x0000003f
-Level 6: 0x00000040, 0xffffffc0, 0x0000007f
-Level 7: 0x00000080, 0xffffff80, 0x000000ff
-
-ident [info] Info 1
+++ /dev/null
---TEST--
-Log: Null Handler
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$logger = Log::singleton('null');
-for ($i = 0; $i < 3; $i++) {
- $logger->log("Log entry $i");
-}
-
---EXPECT--
+++ /dev/null
---TEST--
-Log: Priorities
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$conf = array('lineFormat' => '[%3$s] %4$s');
-$logger = Log::singleton('console', '', 'ident', $conf);
-
-/* Log at the default PEAR_LOG_INFO level. */
-$logger->log('Log message');
-
-/* Set the default priority to PEAR_LOG_DEBUG. */
-$logger->setPriority(PEAR_LOG_DEBUG);
-$logger->log('Log message');
-
-/* Verify that the getPriority() method also things we're at PEAR_LOG_DEBUG. */
-$priority = $logger->priorityToString($logger->getPriority());
-echo "$priority\n";
-
-/* Verify that stringToPriority() can convert back to a constant. */
-$priority = $logger->stringToPriority($priority);
-echo "$priority\n";
-
---EXPECT--
-[info] Log message
-[debug] Log message
-debug
-7
+++ /dev/null
---TEST--
-Log: Singleton
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$console1 = Log::singleton('console');
-$console2 = Log::singleton('console');
-
-if (is_a($console1, 'Log_console') && is_a($console2, 'Log_console'))
-{
- echo "Two Log_console objects.\n";
-}
-
-if ($console1->_id == $console2->_id) {
- echo "The objects have the same ID.\n";
-}
-
---EXPECT--
-Two Log_console objects.
-The objects have the same ID.
+++ /dev/null
---TEST--
-Log: SQL setIdent()
---SKIPIF--
-<?php
-
-require_once 'PEAR/Registry.php';
-$registry = &new PEAR_Registry();
-
-if (!$registry->packageExists('DB')) die("skip\n");
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$ident = '12345678901234567890';
-
-$logger = Log::singleton('sql', 'log_table', $ident, array('dsn' => ''));
-echo $logger->getIdent() . "\n";
-
-$logger->setIdent($ident);
-echo $logger->getIdent() . "\n";
-
---EXPECT--
-1234567890123456
-1234567890123456
+++ /dev/null
---TEST--
-Log: Sqlite Handler
---SKIPIF--
-<?php if (!function_exists('sqlite_open')) die("skip\n"); ?>
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$filename = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'sqlite-log.db';
-if (file_exists($filename)) unlink($filename);
-
-$db = sqlite_open($filename, 0666, $error);
-$ident = time();
-$message = 'logging an event';
-$logger = Log::factory('sqlite', 'log_table', $ident, $db);
-$logger->log($message, PEAR_LOG_WARNING);
-
-$q = "SELECT message FROM log_table WHERE ident='$ident'";
-$res = sqlite_query($db, $q);
-if (sqlite_fetch_string($res) == $message) {
- echo 'ok';
-}
-
-sqlite_close($db);
-if (file_exists($filename)) unlink($filename);
-
---EXPECT--
-ok
+++ /dev/null
---TEST--
-Log: Syslog Handler
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$logger = Log::singleton('syslog', '', 'Test');
-for ($i = 0; $i < 3; $i++) {
- $logger->notice("Log entry $i");
-}
-
---EXPECT--
+++ /dev/null
---TEST--
-Log: Window Handler (Output Buffering)
---INI--
-date.timezone=UTC
-output_buffering=on
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$conf = array('title' => 'Test Output');
-$logger = Log::singleton('win', 'test', 'ident', $conf);
-
-for ($i = 0; $i < 3; $i++) {
- $logger->log("Log entry $i");
-}
-
---EXPECTF--
-<script language="JavaScript">
-test = window.open('', 'test', 'toolbar=no,scrollbars,width=600,height=400');
-test.document.writeln('<html>');
-test.document.writeln('<head>');
-test.document.writeln('<title>Test Output</title>');
-test.document.writeln('<style type="text/css">');
-test.document.writeln('body { font-family: monospace; font-size: 8pt; }');
-test.document.writeln('td,th { font-size: 8pt; }');
-test.document.writeln('td,th { border-bottom: #999999 solid 1px; }');
-test.document.writeln('td,th { border-right: #999999 solid 1px; }');
-test.document.writeln('tr { text-align: left; vertical-align: top; }');
-test.document.writeln('td.l0 { color: red; }');
-test.document.writeln('td.l1 { color: orange; }');
-test.document.writeln('td.l2 { color: yellow; }');
-test.document.writeln('td.l3 { color: green; }');
-test.document.writeln('td.l4 { color: blue; }');
-test.document.writeln('td.l5 { color: indigo; }');
-test.document.writeln('td.l6 { color: violet; }');
-test.document.writeln('td.l7 { color: black; }');
-test.document.writeln('</style>');
-test.document.writeln('<script type="text/javascript">');
-test.document.writeln('function scroll() {');
-test.document.writeln(' body = document.getElementById("test");');
-test.document.writeln(' body.scrollTop = body.scrollHeight;');
-test.document.writeln('}');
-test.document.writeln('<\/script>');
-test.document.writeln('</head>');
-test.document.writeln('<body id="test" onclick="scroll()">');
-test.document.writeln('<table border="0" cellpadding="2" cellspacing="0">');
-test.document.writeln('<tr><th>Time</th>');
-test.document.writeln('<th>Ident</th>')
-test.document.writeln('<th>Priority</th><th width="100%">Message</th></tr>');
-</script><script language='JavaScript'>
-test.document.writeln('<tr><td>%i:%i:%i.%i</td><td>ident</td><td>Info</td><td class=\"l6\">Log entry 0</td></tr>');
-self.focus();
-</script>
-<script language='JavaScript'>
-test.document.writeln('<tr><td>%i:%i:%i.%i</td><td>ident</td><td>Info</td><td class=\"l6\">Log entry 1</td></tr>');
-self.focus();
-</script>
-<script language='JavaScript'>
-test.document.writeln('<tr><td>%i:%i:%i.%i</td><td>ident</td><td>Info</td><td class=\"l6\">Log entry 2</td></tr>');
-self.focus();
-</script>
-<script language='JavaScript'>
-test.document.writeln('</table>');
-self.focus();
-</script>
-<script language='JavaScript'>
-test.document.writeln('</body></html>');
-self.focus();
-</script>
+++ /dev/null
---TEST--
-Log: Window Handler
---INI--
-date.timezone=UTC
---FILE--
-<?php
-
-require_once 'Log.php';
-
-$conf = array('title' => 'Test Output');
-$logger = Log::singleton('win', 'test', 'ident', $conf);
-
-for ($i = 0; $i < 3; $i++) {
- $logger->log("Log entry $i");
-}
-
---EXPECTF--
-<script language="JavaScript">
-test = window.open('', 'test', 'toolbar=no,scrollbars,width=600,height=400');
-test.document.writeln('<html>');
-test.document.writeln('<head>');
-test.document.writeln('<title>Test Output</title>');
-test.document.writeln('<style type="text/css">');
-test.document.writeln('body { font-family: monospace; font-size: 8pt; }');
-test.document.writeln('td,th { font-size: 8pt; }');
-test.document.writeln('td,th { border-bottom: #999999 solid 1px; }');
-test.document.writeln('td,th { border-right: #999999 solid 1px; }');
-test.document.writeln('tr { text-align: left; vertical-align: top; }');
-test.document.writeln('td.l0 { color: red; }');
-test.document.writeln('td.l1 { color: orange; }');
-test.document.writeln('td.l2 { color: yellow; }');
-test.document.writeln('td.l3 { color: green; }');
-test.document.writeln('td.l4 { color: blue; }');
-test.document.writeln('td.l5 { color: indigo; }');
-test.document.writeln('td.l6 { color: violet; }');
-test.document.writeln('td.l7 { color: black; }');
-test.document.writeln('</style>');
-test.document.writeln('<script type="text/javascript">');
-test.document.writeln('function scroll() {');
-test.document.writeln(' body = document.getElementById("test");');
-test.document.writeln(' body.scrollTop = body.scrollHeight;');
-test.document.writeln('}');
-test.document.writeln('<\/script>');
-test.document.writeln('</head>');
-test.document.writeln('<body id="test" onclick="scroll()">');
-test.document.writeln('<table border="0" cellpadding="2" cellspacing="0">');
-test.document.writeln('<tr><th>Time</th>');
-test.document.writeln('<th>Ident</th>')
-test.document.writeln('<th>Priority</th><th width="100%">Message</th></tr>');
-</script><script language='JavaScript'>
-test.document.writeln('<tr><td>%i:%i:%i.%i</td><td>ident</td><td>Info</td><td class=\"l6\">Log entry 0</td></tr>');
-self.focus();
-</script>
-<script language='JavaScript'>
-test.document.writeln('<tr><td>%i:%i:%i.%i</td><td>ident</td><td>Info</td><td class=\"l6\">Log entry 1</td></tr>');
-self.focus();
-</script>
-<script language='JavaScript'>
-test.document.writeln('<tr><td>%i:%i:%i.%i</td><td>ident</td><td>Info</td><td class=\"l6\">Log entry 2</td></tr>');
-self.focus();
-</script>
-<script language='JavaScript'>
-test.document.writeln('</table>');
-self.focus();
-</script>
-<script language='JavaScript'>
-test.document.writeln('</body></html>');
-self.focus();
-</script>
--- /dev/null
+<?php
+/**
+ * $Header$
+ * $Horde: horde/lib/Log.php,v 1.15 2000/06/29 23:39:45 jon Exp $
+ *
+ * @version $Revision: 310238 $
+ * @package Log
+ */
+
+define('PEAR_LOG_EMERG', 0); /* System is unusable */
+define('PEAR_LOG_ALERT', 1); /* Immediate action required */
+define('PEAR_LOG_CRIT', 2); /* Critical conditions */
+define('PEAR_LOG_ERR', 3); /* Error conditions */
+define('PEAR_LOG_WARNING', 4); /* Warning conditions */
+define('PEAR_LOG_NOTICE', 5); /* Normal but significant */
+define('PEAR_LOG_INFO', 6); /* Informational */
+define('PEAR_LOG_DEBUG', 7); /* Debug-level messages */
+
+define('PEAR_LOG_ALL', 0xffffffff); /* All messages */
+define('PEAR_LOG_NONE', 0x00000000); /* No message */
+
+/* Log types for PHP's native error_log() function. */
+define('PEAR_LOG_TYPE_SYSTEM', 0); /* Use PHP's system logger */
+define('PEAR_LOG_TYPE_MAIL', 1); /* Use PHP's mail() function */
+define('PEAR_LOG_TYPE_DEBUG', 2); /* Use PHP's debugging connection */
+define('PEAR_LOG_TYPE_FILE', 3); /* Append to a file */
+define('PEAR_LOG_TYPE_SAPI', 4); /* Use the SAPI logging handler */
+
+/**
+ * The Log:: class implements both an abstraction for various logging
+ * mechanisms and the Subject end of a Subject-Observer pattern.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Jon Parise <jon@php.net>
+ * @since Horde 1.3
+ * @package Log
+ */
+class Log
+{
+ /**
+ * Indicates whether or not the log can been opened / connected.
+ *
+ * @var boolean
+ * @access protected
+ */
+ var $_opened = false;
+
+ /**
+ * Instance-specific unique identification number.
+ *
+ * @var integer
+ * @access protected
+ */
+ var $_id = 0;
+
+ /**
+ * The label that uniquely identifies this set of log messages.
+ *
+ * @var string
+ * @access protected
+ */
+ var $_ident = '';
+
+ /**
+ * The default priority to use when logging an event.
+ *
+ * @var integer
+ * @access protected
+ */
+ var $_priority = PEAR_LOG_INFO;
+
+ /**
+ * The bitmask of allowed log levels.
+ *
+ * @var integer
+ * @access protected
+ */
+ var $_mask = PEAR_LOG_ALL;
+
+ /**
+ * Holds all Log_observer objects that wish to be notified of new messages.
+ *
+ * @var array
+ * @access protected
+ */
+ var $_listeners = array();
+
+ /**
+ * Starting depth to use when walking a backtrace in search of the
+ * function that invoked the log system.
+ *
+ * @var integer
+ * @access protected
+ */
+ var $_backtrace_depth = 0;
+
+ /**
+ * Maps canonical format keys to position arguments for use in building
+ * "line format" strings.
+ *
+ * @var array
+ * @access protected
+ */
+ var $_formatMap = array('%{timestamp}' => '%1$s',
+ '%{ident}' => '%2$s',
+ '%{priority}' => '%3$s',
+ '%{message}' => '%4$s',
+ '%{file}' => '%5$s',
+ '%{line}' => '%6$s',
+ '%{function}' => '%7$s',
+ '%{class}' => '%8$s',
+ '%\{' => '%%{');
+
+ /**
+ * Attempts to return a concrete Log instance of type $handler.
+ *
+ * @param string $handler The type of concrete Log subclass to return.
+ * Attempt to dynamically include the code for
+ * this subclass. Currently, valid values are
+ * 'console', 'syslog', 'sql', 'file', and 'mcal'.
+ *
+ * @param string $name The name of the actually log file, table, or
+ * other specific store to use. Defaults to an
+ * empty string, with which the subclass will
+ * attempt to do something intelligent.
+ *
+ * @param string $ident The identity reported to the log system.
+ *
+ * @param array $conf A hash containing any additional configuration
+ * information that a subclass might need.
+ *
+ * @param int $level Log messages up to and including this level.
+ *
+ * @return object Log The newly created concrete Log instance, or
+ * null on an error.
+ * @access public
+ * @since Log 1.0
+ */
+ public static function factory($handler, $name = '', $ident = '',
+ $conf = array(), $level = PEAR_LOG_DEBUG)
+ {
+ $handler = strtolower($handler);
+ $class = 'Log_' . $handler;
+ $classfile = 'Log/' . $handler . '.php';
+
+ /*
+ * Attempt to include our version of the named class, but don't treat
+ * a failure as fatal. The caller may have already included their own
+ * version of the named class.
+ */
+ if (!class_exists($class, false)) {
+ include_once $classfile;
+ }
+
+ /* If the class exists, return a new instance of it. */
+ if (class_exists($class, false)) {
+ $obj = new $class($name, $ident, $conf, $level);
+ return $obj;
+ }
+
+ $null = null;
+ return $null;
+ }
+
+ /**
+ * Attempts to return a reference to a concrete Log instance of type
+ * $handler, only creating a new instance if no log instance with the same
+ * parameters currently exists.
+ *
+ * You should use this if there are multiple places you might create a
+ * logger, you don't want to create multiple loggers, and you don't want to
+ * check for the existance of one each time. The singleton pattern does all
+ * the checking work for you.
+ *
+ * <b>You MUST call this method with the $var = &Log::singleton() syntax.
+ * Without the ampersand (&) in front of the method name, you will not get
+ * a reference, you will get a copy.</b>
+ *
+ * @param string $handler The type of concrete Log subclass to return.
+ * Attempt to dynamically include the code for
+ * this subclass. Currently, valid values are
+ * 'console', 'syslog', 'sql', 'file', and 'mcal'.
+ *
+ * @param string $name The name of the actually log file, table, or
+ * other specific store to use. Defaults to an
+ * empty string, with which the subclass will
+ * attempt to do something intelligent.
+ *
+ * @param string $ident The identity reported to the log system.
+ *
+ * @param array $conf A hash containing any additional configuration
+ * information that a subclass might need.
+ *
+ * @param int $level Log messages up to and including this level.
+ *
+ * @return object Log The newly created concrete Log instance, or
+ * null on an error.
+ * @access public
+ * @since Log 1.0
+ */
+ public static function singleton($handler, $name = '', $ident = '',
+ $conf = array(), $level = PEAR_LOG_DEBUG)
+ {
+ static $instances;
+ if (!isset($instances)) $instances = array();
+
+ $signature = serialize(array($handler, $name, $ident, $conf, $level));
+ if (!isset($instances[$signature])) {
+ $instances[$signature] = Log::factory($handler, $name, $ident,
+ $conf, $level);
+ }
+
+ return $instances[$signature];
+ }
+
+ /**
+ * Abstract implementation of the open() method.
+ * @since Log 1.0
+ */
+ function open()
+ {
+ return false;
+ }
+
+ /**
+ * Abstract implementation of the close() method.
+ * @since Log 1.0
+ */
+ function close()
+ {
+ return false;
+ }
+
+ /**
+ * Abstract implementation of the flush() method.
+ * @since Log 1.8.2
+ */
+ function flush()
+ {
+ return false;
+ }
+
+ /**
+ * Abstract implementation of the log() method.
+ * @since Log 1.0
+ */
+ function log($message, $priority = null)
+ {
+ return false;
+ }
+
+ /**
+ * A convenience function for logging a emergency event. It will log a
+ * message at the PEAR_LOG_EMERG log level.
+ *
+ * @param mixed $message String or object containing the message
+ * to log.
+ *
+ * @return boolean True if the message was successfully logged.
+ *
+ * @access public
+ * @since Log 1.7.0
+ */
+ function emerg($message)
+ {
+ return $this->log($message, PEAR_LOG_EMERG);
+ }
+
+ /**
+ * A convenience function for logging an alert event. It will log a
+ * message at the PEAR_LOG_ALERT log level.
+ *
+ * @param mixed $message String or object containing the message
+ * to log.
+ *
+ * @return boolean True if the message was successfully logged.
+ *
+ * @access public
+ * @since Log 1.7.0
+ */
+ function alert($message)
+ {
+ return $this->log($message, PEAR_LOG_ALERT);
+ }
+
+ /**
+ * A convenience function for logging a critical event. It will log a
+ * message at the PEAR_LOG_CRIT log level.
+ *
+ * @param mixed $message String or object containing the message
+ * to log.
+ *
+ * @return boolean True if the message was successfully logged.
+ *
+ * @access public
+ * @since Log 1.7.0
+ */
+ function crit($message)
+ {
+ return $this->log($message, PEAR_LOG_CRIT);
+ }
+
+ /**
+ * A convenience function for logging a error event. It will log a
+ * message at the PEAR_LOG_ERR log level.
+ *
+ * @param mixed $message String or object containing the message
+ * to log.
+ *
+ * @return boolean True if the message was successfully logged.
+ *
+ * @access public
+ * @since Log 1.7.0
+ */
+ function err($message)
+ {
+ return $this->log($message, PEAR_LOG_ERR);
+ }
+
+ /**
+ * A convenience function for logging a warning event. It will log a
+ * message at the PEAR_LOG_WARNING log level.
+ *
+ * @param mixed $message String or object containing the message
+ * to log.
+ *
+ * @return boolean True if the message was successfully logged.
+ *
+ * @access public
+ * @since Log 1.7.0
+ */
+ function warning($message)
+ {
+ return $this->log($message, PEAR_LOG_WARNING);
+ }
+
+ /**
+ * A convenience function for logging a notice event. It will log a
+ * message at the PEAR_LOG_NOTICE log level.
+ *
+ * @param mixed $message String or object containing the message
+ * to log.
+ *
+ * @return boolean True if the message was successfully logged.
+ *
+ * @access public
+ * @since Log 1.7.0
+ */
+ function notice($message)
+ {
+ return $this->log($message, PEAR_LOG_NOTICE);
+ }
+
+ /**
+ * A convenience function for logging a information event. It will log a
+ * message at the PEAR_LOG_INFO log level.
+ *
+ * @param mixed $message String or object containing the message
+ * to log.
+ *
+ * @return boolean True if the message was successfully logged.
+ *
+ * @access public
+ * @since Log 1.7.0
+ */
+ function info($message)
+ {
+ return $this->log($message, PEAR_LOG_INFO);
+ }
+
+ /**
+ * A convenience function for logging a debug event. It will log a
+ * message at the PEAR_LOG_DEBUG log level.
+ *
+ * @param mixed $message String or object containing the message
+ * to log.
+ *
+ * @return boolean True if the message was successfully logged.
+ *
+ * @access public
+ * @since Log 1.7.0
+ */
+ function debug($message)
+ {
+ return $this->log($message, PEAR_LOG_DEBUG);
+ }
+
+ /**
+ * Returns the string representation of the message data.
+ *
+ * If $message is an object, _extractMessage() will attempt to extract
+ * the message text using a known method (such as a PEAR_Error object's
+ * getMessage() method). If a known method, cannot be found, the
+ * serialized representation of the object will be returned.
+ *
+ * If the message data is already a string, it will be returned unchanged.
+ *
+ * @param mixed $message The original message data. This may be a
+ * string or any object.
+ *
+ * @return string The string representation of the message.
+ *
+ * @access protected
+ */
+ function _extractMessage($message)
+ {
+ /*
+ * If we've been given an object, attempt to extract the message using
+ * a known method. If we can't find such a method, default to the
+ * "human-readable" version of the object.
+ *
+ * We also use the human-readable format for arrays.
+ */
+ if (is_object($message)) {
+ if (method_exists($message, 'getmessage')) {
+ $message = $message->getMessage();
+ } else if (method_exists($message, 'tostring')) {
+ $message = $message->toString();
+ } else if (method_exists($message, '__tostring')) {
+ $message = (string)$message;
+ } else {
+ $message = var_export($message, true);
+ }
+ } else if (is_array($message)) {
+ if (isset($message['message'])) {
+ if (is_scalar($message['message'])) {
+ $message = $message['message'];
+ } else {
+ $message = var_export($message['message'], true);
+ }
+ } else {
+ $message = var_export($message, true);
+ }
+ } else if (is_bool($message) || $message === NULL) {
+ $message = var_export($message, true);
+ }
+
+ /* Otherwise, we assume the message is a string. */
+ return $message;
+ }
+
+ /**
+ * Using debug_backtrace(), returns the file, line, and enclosing function
+ * name of the source code context from which log() was invoked.
+ *
+ * @param int $depth The initial number of frames we should step
+ * back into the trace.
+ *
+ * @return array Array containing four strings: the filename, the line,
+ * the function name, and the class name from which log()
+ * was called.
+ *
+ * @access private
+ * @since Log 1.9.4
+ */
+ function _getBacktraceVars($depth)
+ {
+ /* Start by generating a backtrace from the current call (here). */
+ $bt = debug_backtrace();
+
+ /* Store some handy shortcuts to our previous frames. */
+ $bt0 = isset($bt[$depth]) ? $bt[$depth] : null;
+ $bt1 = isset($bt[$depth + 1]) ? $bt[$depth + 1] : null;
+
+ /*
+ * If we were ultimately invoked by the composite handler, we need to
+ * increase our depth one additional level to compensate.
+ */
+ $class = isset($bt1['class']) ? $bt1['class'] : null;
+ if ($class !== null && strcasecmp($class, 'Log_composite') == 0) {
+ $depth++;
+ $bt0 = isset($bt[$depth]) ? $bt[$depth] : null;
+ $bt1 = isset($bt[$depth + 1]) ? $bt[$depth + 1] : null;
+ $class = isset($bt1['class']) ? $bt1['class'] : null;
+ }
+
+ /*
+ * We're interested in the frame which invoked the log() function, so
+ * we need to walk back some number of frames into the backtrace. The
+ * $depth parameter tells us where to start looking. We go one step
+ * further back to find the name of the encapsulating function from
+ * which log() was called.
+ */
+ $file = isset($bt0) ? $bt0['file'] : null;
+ $line = isset($bt0) ? $bt0['line'] : 0;
+ $func = isset($bt1) ? $bt1['function'] : null;
+
+ /*
+ * However, if log() was called from one of our "shortcut" functions,
+ * we're going to need to go back an additional step.
+ */
+ if (in_array($func, array('emerg', 'alert', 'crit', 'err', 'warning',
+ 'notice', 'info', 'debug'))) {
+ $bt2 = isset($bt[$depth + 2]) ? $bt[$depth + 2] : null;
+
+ $file = is_array($bt1) ? $bt1['file'] : null;
+ $line = is_array($bt1) ? $bt1['line'] : 0;
+ $func = is_array($bt2) ? $bt2['function'] : null;
+ $class = isset($bt2['class']) ? $bt2['class'] : null;
+ }
+
+ /*
+ * If we couldn't extract a function name (perhaps because we were
+ * executed from the "main" context), provide a default value.
+ */
+ if ($func === null) {
+ $func = '(none)';
+ }
+
+ /* Return a 4-tuple containing (file, line, function, class). */
+ return array($file, $line, $func, $class);
+ }
+
+ /**
+ * Sets the starting depth to use when walking a backtrace in search of
+ * the function that invoked the log system. This is used on conjunction
+ * with the 'file', 'line', 'function', and 'class' formatters.
+ *
+ * @param int $depth The new backtrace depth.
+ *
+ * @access public
+ * @since Log 1.12.7
+ */
+ public function setBacktraceDepth($depth)
+ {
+ $this->_backtrace_depth = $depth;
+ }
+
+ /**
+ * Produces a formatted log line based on a format string and a set of
+ * variables representing the current log record and state.
+ *
+ * @return string Formatted log string.
+ *
+ * @access protected
+ * @since Log 1.9.4
+ */
+ function _format($format, $timestamp, $priority, $message)
+ {
+ /*
+ * If the format string references any of the backtrace-driven
+ * variables (%5 %6,%7,%8), generate the backtrace and fetch them.
+ */
+ if (preg_match('/%[5678]/', $format)) {
+ /* Plus 2 to account for our internal function calls. */
+ $d = $this->_backtrace_depth + 2;
+ list($file, $line, $func, $class) = $this->_getBacktraceVars($d);
+ }
+
+ /*
+ * Build the formatted string. We use the sprintf() function's
+ * "argument swapping" capability to dynamically select and position
+ * the variables which will ultimately appear in the log string.
+ */
+ return sprintf($format,
+ $timestamp,
+ $this->_ident,
+ $this->priorityToString($priority),
+ $message,
+ isset($file) ? $file : '',
+ isset($line) ? $line : '',
+ isset($func) ? $func : '',
+ isset($class) ? $class : '');
+ }
+
+ /**
+ * Returns the string representation of a PEAR_LOG_* integer constant.
+ *
+ * @param int $priority A PEAR_LOG_* integer constant.
+ *
+ * @return string The string representation of $level.
+ *
+ * @access public
+ * @since Log 1.0
+ */
+ function priorityToString($priority)
+ {
+ $levels = array(
+ PEAR_LOG_EMERG => 'emergency',
+ PEAR_LOG_ALERT => 'alert',
+ PEAR_LOG_CRIT => 'critical',
+ PEAR_LOG_ERR => 'error',
+ PEAR_LOG_WARNING => 'warning',
+ PEAR_LOG_NOTICE => 'notice',
+ PEAR_LOG_INFO => 'info',
+ PEAR_LOG_DEBUG => 'debug'
+ );
+
+ return $levels[$priority];
+ }
+
+ /**
+ * Returns the the PEAR_LOG_* integer constant for the given string
+ * representation of a priority name. This function performs a
+ * case-insensitive search.
+ *
+ * @param string $name String containing a priority name.
+ *
+ * @return string The PEAR_LOG_* integer contstant corresponding
+ * the the specified priority name.
+ *
+ * @access public
+ * @since Log 1.9.0
+ */
+ function stringToPriority($name)
+ {
+ $levels = array(
+ 'emergency' => PEAR_LOG_EMERG,
+ 'alert' => PEAR_LOG_ALERT,
+ 'critical' => PEAR_LOG_CRIT,
+ 'error' => PEAR_LOG_ERR,
+ 'warning' => PEAR_LOG_WARNING,
+ 'notice' => PEAR_LOG_NOTICE,
+ 'info' => PEAR_LOG_INFO,
+ 'debug' => PEAR_LOG_DEBUG
+ );
+
+ return $levels[strtolower($name)];
+ }
+
+ /**
+ * Calculate the log mask for the given priority.
+ *
+ * This method may be called statically.
+ *
+ * @param integer $priority The priority whose mask will be calculated.
+ *
+ * @return integer The calculated log mask.
+ *
+ * @access public
+ * @since Log 1.7.0
+ */
+ public static function MASK($priority)
+ {
+ return (1 << $priority);
+ }
+
+ /**
+ * Calculate the log mask for all priorities up to the given priority.
+ *
+ * This method may be called statically.
+ *
+ * @param integer $priority The maximum priority covered by this mask.
+ *
+ * @return integer The resulting log mask.
+ *
+ * @access public
+ * @since Log 1.7.0
+ *
+ * @deprecated deprecated since Log 1.9.4; use Log::MAX() instead
+ */
+ public static function UPTO($priority)
+ {
+ return Log::MAX($priority);
+ }
+
+ /**
+ * Calculate the log mask for all priorities greater than or equal to the
+ * given priority. In other words, $priority will be the lowest priority
+ * matched by the resulting mask.
+ *
+ * This method may be called statically.
+ *
+ * @param integer $priority The minimum priority covered by this mask.
+ *
+ * @return integer The resulting log mask.
+ *
+ * @access public
+ * @since Log 1.9.4
+ */
+ public static function MIN($priority)
+ {
+ return PEAR_LOG_ALL ^ ((1 << $priority) - 1);
+ }
+
+ /**
+ * Calculate the log mask for all priorities less than or equal to the
+ * given priority. In other words, $priority will be the highests priority
+ * matched by the resulting mask.
+ *
+ * This method may be called statically.
+ *
+ * @param integer $priority The maximum priority covered by this mask.
+ *
+ * @return integer The resulting log mask.
+ *
+ * @access public
+ * @since Log 1.9.4
+ */
+ public static function MAX($priority)
+ {
+ return ((1 << ($priority + 1)) - 1);
+ }
+
+ /**
+ * Set and return the level mask for the current Log instance.
+ *
+ * @param integer $mask A bitwise mask of log levels.
+ *
+ * @return integer The current level mask.
+ *
+ * @access public
+ * @since Log 1.7.0
+ */
+ function setMask($mask)
+ {
+ $this->_mask = $mask;
+
+ return $this->_mask;
+ }
+
+ /**
+ * Returns the current level mask.
+ *
+ * @return interger The current level mask.
+ *
+ * @access public
+ * @since Log 1.7.0
+ */
+ function getMask()
+ {
+ return $this->_mask;
+ }
+
+ /**
+ * Check if the given priority is included in the current level mask.
+ *
+ * @param integer $priority The priority to check.
+ *
+ * @return boolean True if the given priority is included in the current
+ * log mask.
+ *
+ * @access protected
+ * @since Log 1.7.0
+ */
+ function _isMasked($priority)
+ {
+ return (Log::MASK($priority) & $this->_mask);
+ }
+
+ /**
+ * Returns the current default priority.
+ *
+ * @return integer The current default priority.
+ *
+ * @access public
+ * @since Log 1.8.4
+ */
+ function getPriority()
+ {
+ return $this->_priority;
+ }
+
+ /**
+ * Sets the default priority to the specified value.
+ *
+ * @param integer $priority The new default priority.
+ *
+ * @access public
+ * @since Log 1.8.4
+ */
+ function setPriority($priority)
+ {
+ $this->_priority = $priority;
+ }
+
+ /**
+ * Adds a Log_observer instance to the list of observers that are listening
+ * for messages emitted by this Log instance.
+ *
+ * @param object $observer The Log_observer instance to attach as a
+ * listener.
+ *
+ * @param boolean True if the observer is successfully attached.
+ *
+ * @access public
+ * @since Log 1.0
+ */
+ function attach(&$observer)
+ {
+ if (!is_a($observer, 'Log_observer')) {
+ return false;
+ }
+
+ $this->_listeners[$observer->_id] = &$observer;
+
+ return true;
+ }
+
+ /**
+ * Removes a Log_observer instance from the list of observers.
+ *
+ * @param object $observer The Log_observer instance to detach from
+ * the list of listeners.
+ *
+ * @param boolean True if the observer is successfully detached.
+ *
+ * @access public
+ * @since Log 1.0
+ */
+ function detach($observer)
+ {
+ if (!is_a($observer, 'Log_observer') ||
+ !isset($this->_listeners[$observer->_id])) {
+ return false;
+ }
+
+ unset($this->_listeners[$observer->_id]);
+
+ return true;
+ }
+
+ /**
+ * Informs each registered observer instance that a new message has been
+ * logged.
+ *
+ * @param array $event A hash describing the log event.
+ *
+ * @access protected
+ */
+ function _announce($event)
+ {
+ foreach ($this->_listeners as $id => $listener) {
+ if ($event['priority'] <= $this->_listeners[$id]->_priority) {
+ $this->_listeners[$id]->notify($event);
+ }
+ }
+ }
+
+ /**
+ * Indicates whether this is a composite class.
+ *
+ * @return boolean True if this is a composite class.
+ *
+ * @access public
+ * @since Log 1.0
+ */
+ function isComposite()
+ {
+ return false;
+ }
+
+ /**
+ * Sets this Log instance's identification string.
+ *
+ * @param string $ident The new identification string.
+ *
+ * @access public
+ * @since Log 1.6.3
+ */
+ function setIdent($ident)
+ {
+ $this->_ident = $ident;
+ }
+
+ /**
+ * Returns the current identification string.
+ *
+ * @return string The current Log instance's identification string.
+ *
+ * @access public
+ * @since Log 1.6.3
+ */
+ function getIdent()
+ {
+ return $this->_ident;
+ }
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ * $Horde: horde/lib/Log/composite.php,v 1.2 2000/06/28 21:36:13 jon Exp $
+ *
+ * @version $Revision: 305990 $
+ * @package Log
+ */
+
+/**
+ * The Log_composite:: class implements a Composite pattern which
+ * allows multiple Log implementations to receive the same events.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Jon Parise <jon@php.net>
+ *
+ * @since Horde 1.3
+ * @since Log 1.0
+ * @package Log
+ *
+ * @example composite.php Using the composite handler.
+ */
+class Log_composite extends Log
+{
+ /**
+ * Array holding all of the Log instances to which log events should be
+ * sent.
+ *
+ * @var array
+ * @access private
+ */
+ var $_children = array();
+
+
+ /**
+ * Constructs a new composite Log object.
+ *
+ * @param boolean $name This parameter is ignored.
+ * @param boolean $ident This parameter is ignored.
+ * @param boolean $conf This parameter is ignored.
+ * @param boolean $level This parameter is ignored.
+ *
+ * @access public
+ */
+ function Log_composite($name, $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ $this->_ident = $ident;
+ }
+
+ /**
+ * Opens all of the child instances.
+ *
+ * @return True if all of the child instances were successfully opened.
+ *
+ * @access public
+ */
+ function open()
+ {
+ /* Attempt to open each of our children. */
+ $this->_opened = true;
+ foreach ($this->_children as $child) {
+ $this->_opened &= $child->open();
+ }
+
+ /* If all children were opened, return success. */
+ return $this->_opened;
+ }
+
+ /**
+ * Closes all open child instances.
+ *
+ * @return True if all of the opened child instances were successfully
+ * closed.
+ *
+ * @access public
+ */
+ function close()
+ {
+ /* If we haven't been opened, there's nothing more to do. */
+ if (!$this->_opened) {
+ return true;
+ }
+
+ /* Attempt to close each of our children. */
+ $closed = true;
+ foreach ($this->_children as $child) {
+ if ($child->_opened) {
+ $closed &= $child->close();
+ }
+ }
+
+ /* Clear the opened state for consistency. */
+ $this->_opened = false;
+
+ /* If all children were closed, return success. */
+ return $closed;
+ }
+
+ /**
+ * Flushes all child instances. It is assumed that all of the children
+ * have been successfully opened.
+ *
+ * @return True if all of the child instances were successfully flushed.
+ *
+ * @access public
+ * @since Log 1.8.2
+ */
+ function flush()
+ {
+ /* Attempt to flush each of our children. */
+ $flushed = true;
+ foreach ($this->_children as $child) {
+ $flushed &= $child->flush();
+ }
+
+ /* If all children were flushed, return success. */
+ return $flushed;
+ }
+
+ /**
+ * Sends $message and $priority to each child of this composite. If the
+ * appropriate children aren't already open, they will be opened here.
+ *
+ * @param mixed $message String or object containing the message
+ * to log.
+ * @param string $priority (optional) The priority of the message.
+ * Valid values are: PEAR_LOG_EMERG,
+ * PEAR_LOG_ALERT, PEAR_LOG_CRIT,
+ * PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and
+ * PEAR_LOG_DEBUG.
+ *
+ * @return boolean True if the entry is successfully logged.
+ *
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /*
+ * Abort early if the priority is above the composite handler's
+ * maximum logging level.
+ *
+ * XXX: Consider whether or not introducing this change would break
+ * backwards compatibility. Some users may be expecting composite
+ * handlers to pass on all events to their children regardless of
+ * their own priority.
+ */
+ #if (!$this->_isMasked($priority)) {
+ # return false;
+ #}
+
+ /*
+ * Iterate over all of our children. If a unopened child will respond
+ * to this log event, we attempt to open it immediately. The composite
+ * handler's opened state will be enabled as soon as the first child
+ * handler is successfully opened.
+ *
+ * We track an overall success state that indicates whether or not all
+ * of the relevant child handlers were opened and successfully logged
+ * the event. If one handler fails, we still attempt any remaining
+ * children, but we consider the overall result a failure.
+ */
+ $success = true;
+ foreach ($this->_children as $child) {
+ /* If this child won't respond to this event, skip it. */
+ if (!$child->_isMasked($priority)) {
+ continue;
+ }
+
+ /* If this child has yet to be opened, attempt to do so now. */
+ if (!$child->_opened) {
+ $success &= $child->open();
+
+ /*
+ * If we've successfully opened our first handler, the
+ * composite handler itself is considered to be opened.
+ */
+ if (!$this->_opened && $success) {
+ $this->_opened = true;
+ }
+ }
+
+ /* Finally, attempt to log the message to the child handler. */
+ if ($child->_opened) {
+ $success &= $child->log($message, $priority);
+ }
+ }
+
+ /* Notify the observers. */
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ /* Return success if all of the open children logged the event. */
+ return $success;
+ }
+
+ /**
+ * Returns true if this is a composite.
+ *
+ * @return boolean True if this is a composite class.
+ *
+ * @access public
+ */
+ function isComposite()
+ {
+ return true;
+ }
+
+ /**
+ * Sets this identification string for all of this composite's children.
+ *
+ * @param string $ident The new identification string.
+ *
+ * @access public
+ * @since Log 1.6.7
+ */
+ function setIdent($ident)
+ {
+ /* Call our base class's setIdent() method. */
+ parent::setIdent($ident);
+
+ /* ... and then call setIdent() on all of our children. */
+ foreach ($this->_children as $child) {
+ $child->setIdent($ident);
+ }
+ }
+
+ /**
+ * Adds a Log instance to the list of children.
+ *
+ * @param object $child The Log instance to add.
+ *
+ * @return boolean True if the Log instance was successfully added.
+ *
+ * @access public
+ */
+ function addChild(&$child)
+ {
+ /* Make sure this is a Log instance. */
+ if (!is_a($child, 'Log')) {
+ return false;
+ }
+
+ $this->_children[$child->_id] = $child;
+
+ return true;
+ }
+
+ /**
+ * Removes a Log instance from the list of children.
+ *
+ * @param object $child The Log instance to remove.
+ *
+ * @return boolean True if the Log instance was successfully removed.
+ *
+ * @access public
+ */
+ function removeChild($child)
+ {
+ if (!is_a($child, 'Log') || !isset($this->_children[$child->_id])) {
+ return false;
+ }
+
+ unset($this->_children[$child->_id]);
+
+ return true;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ *
+ * @version $Revision: 306594 $
+ * @package Log
+ */
+
+/**
+ * The Log_console class is a concrete implementation of the Log::
+ * abstract class which writes message to the text console.
+ *
+ * @author Jon Parise <jon@php.net>
+ * @since Log 1.1
+ * @package Log
+ *
+ * @example console.php Using the console handler.
+ */
+class Log_console extends Log
+{
+ /**
+ * Handle to the current output stream.
+ * @var resource
+ * @access private
+ */
+ var $_stream = null;
+
+ /**
+ * Is this object responsible for closing the stream resource?
+ * @var bool
+ * @access private
+ */
+ var $_closeResource = false;
+
+ /**
+ * Should the output be buffered or displayed immediately?
+ * @var string
+ * @access private
+ */
+ var $_buffering = false;
+
+ /**
+ * String holding the buffered output.
+ * @var string
+ * @access private
+ */
+ var $_buffer = '';
+
+ /**
+ * String containing the format of a log line.
+ * @var string
+ * @access private
+ */
+ var $_lineFormat = '%1$s %2$s [%3$s] %4$s';
+
+ /**
+ * String containing the timestamp format. It will be passed directly to
+ * strftime(). Note that the timestamp string will generated using the
+ * current locale.
+ * @var string
+ * @access private
+ */
+ var $_timeFormat = '%b %d %H:%M:%S';
+
+ /**
+ * Constructs a new Log_console object.
+ *
+ * @param string $name Ignored.
+ * @param string $ident The identity string.
+ * @param array $conf The configuration array.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_console($name, $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ $this->_id = md5(microtime());
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+
+ if (!empty($conf['stream'])) {
+ $this->_stream = $conf['stream'];
+ } elseif (defined('STDOUT')) {
+ $this->_stream = STDOUT;
+ } else {
+ $this->_stream = fopen('php://output', 'a');
+ $this->_closeResource = true;
+ }
+
+ if (isset($conf['buffering'])) {
+ $this->_buffering = $conf['buffering'];
+ }
+
+ if (!empty($conf['lineFormat'])) {
+ $this->_lineFormat = str_replace(array_keys($this->_formatMap),
+ array_values($this->_formatMap),
+ $conf['lineFormat']);
+ }
+
+ if (!empty($conf['timeFormat'])) {
+ $this->_timeFormat = $conf['timeFormat'];
+ }
+
+ /*
+ * If output buffering has been requested, we need to register a
+ * shutdown function that will dump the buffer upon termination.
+ */
+ if ($this->_buffering) {
+ register_shutdown_function(array(&$this, '_Log_console'));
+ }
+ }
+
+ /**
+ * Destructor
+ */
+ function _Log_console()
+ {
+ $this->close();
+ }
+
+ /**
+ * Open the output stream.
+ *
+ * @access public
+ * @since Log 1.9.7
+ */
+ function open()
+ {
+ $this->_opened = true;
+ return true;
+ }
+
+ /**
+ * Closes the output stream.
+ *
+ * This results in a call to flush().
+ *
+ * @access public
+ * @since Log 1.9.0
+ */
+ function close()
+ {
+ $this->flush();
+ $this->_opened = false;
+ if ($this->_closeResource === true && is_resource($this->_stream)) {
+ fclose($this->_stream);
+ }
+ return true;
+ }
+
+ /**
+ * Flushes all pending ("buffered") data to the output stream.
+ *
+ * @access public
+ * @since Log 1.8.2
+ */
+ function flush()
+ {
+ /*
+ * If output buffering is enabled, dump the contents of the buffer to
+ * the output stream.
+ */
+ if ($this->_buffering && (strlen($this->_buffer) > 0)) {
+ fwrite($this->_stream, $this->_buffer);
+ $this->_buffer = '';
+ }
+
+ if (is_resource($this->_stream)) {
+ return fflush($this->_stream);
+ }
+
+ return false;
+ }
+
+ /**
+ * Writes $message to the text console. Also, passes the message
+ * along to any Log_observer instances that are observing this Log.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param string $priority The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+
+ /* Build the string containing the complete log line. */
+ $line = $this->_format($this->_lineFormat,
+ strftime($this->_timeFormat),
+ $priority, $message) . "\n";
+
+ /*
+ * If buffering is enabled, append this line to the output buffer.
+ * Otherwise, print the line to the output stream immediately.
+ */
+ if ($this->_buffering) {
+ $this->_buffer .= $line;
+ } else {
+ fwrite($this->_stream, $line);
+ }
+
+ /* Notify observers about this log message. */
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ *
+ * @version $Revision: 250926 $
+ * @package Log
+ */
+
+/**
+ * The Log_daemon class is a concrete implementation of the Log::
+ * abstract class which sends messages to syslog daemon on UNIX-like machines.
+ * This class uses the syslog protocol: http://www.ietf.org/rfc/rfc3164.txt
+ *
+ * @author Bart van der Schans <schans@dds.nl>
+ * @version $Revision: 250926 $
+ * @package Log
+ */
+class Log_daemon extends Log
+{
+ /**
+ * Integer holding the log facility to use.
+ * @var string
+ */
+ var $_name = LOG_DAEMON;
+
+ /**
+ * Var holding the resource pointer to the socket
+ * @var resource
+ */
+ var $_socket;
+
+ /**
+ * The ip address or servername
+ * @see http://www.php.net/manual/en/transports.php
+ * @var string
+ */
+ var $_ip = '127.0.0.1';
+
+ /**
+ * Protocol to use (tcp, udp, etc.)
+ * @see http://www.php.net/manual/en/transports.php
+ * @var string
+ */
+ var $_proto = 'udp';
+
+ /**
+ * Port to connect to
+ * @var int
+ */
+ var $_port = 514;
+
+ /**
+ * Maximum message length in bytes
+ * @var int
+ */
+ var $_maxsize = 4096;
+
+ /**
+ * Socket timeout in seconds
+ * @var int
+ */
+ var $_timeout = 1;
+
+
+ /**
+ * Constructs a new syslog object.
+ *
+ * @param string $name The syslog facility.
+ * @param string $ident The identity string.
+ * @param array $conf The configuration array.
+ * @param int $maxLevel Maximum level at which to log.
+ * @access public
+ */
+ function Log_daemon($name, $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ /* Ensure we have a valid integer value for $name. */
+ if (empty($name) || !is_int($name)) {
+ $name = LOG_SYSLOG;
+ }
+
+ $this->_id = md5(microtime());
+ $this->_name = $name;
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+
+ if (isset($conf['ip'])) {
+ $this->_ip = $conf['ip'];
+ }
+ if (isset($conf['proto'])) {
+ $this->_proto = $conf['proto'];
+ }
+ if (isset($conf['port'])) {
+ $this->_port = $conf['port'];
+ }
+ if (isset($conf['maxsize'])) {
+ $this->_maxsize = $conf['maxsize'];
+ }
+ if (isset($conf['timeout'])) {
+ $this->_timeout = $conf['timeout'];
+ }
+ $this->_proto = $this->_proto . '://';
+
+ register_shutdown_function(array(&$this, '_Log_daemon'));
+ }
+
+ /**
+ * Destructor.
+ *
+ * @access private
+ */
+ function _Log_daemon()
+ {
+ $this->close();
+ }
+
+ /**
+ * Opens a connection to the system logger, if it has not already
+ * been opened. This is implicitly called by log(), if necessary.
+ * @access public
+ */
+ function open()
+ {
+ if (!$this->_opened) {
+ $this->_opened = (bool)($this->_socket = @fsockopen(
+ $this->_proto . $this->_ip,
+ $this->_port,
+ $errno,
+ $errstr,
+ $this->_timeout));
+ }
+ return $this->_opened;
+ }
+
+ /**
+ * Closes the connection to the system logger, if it is open.
+ * @access public
+ */
+ function close()
+ {
+ if ($this->_opened) {
+ $this->_opened = false;
+ return fclose($this->_socket);
+ }
+ return true;
+ }
+
+ /**
+ * Sends $message to the currently open syslog connection. Calls
+ * open() if necessary. Also passes the message along to any Log_observer
+ * instances that are observing this Log.
+ *
+ * @param string $message The textual message to be logged.
+ * @param int $priority (optional) The priority of the message. Valid
+ * values are: LOG_EMERG, LOG_ALERT, LOG_CRIT,
+ * LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO,
+ * and LOG_DEBUG. The default is LOG_INFO.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* If the connection isn't open and can't be opened, return failure. */
+ if (!$this->_opened && !$this->open()) {
+ return false;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+
+ /* Set the facility level. */
+ $facility_level = intval($this->_name) +
+ intval($this->_toSyslog($priority));
+
+ /* Prepend ident info. */
+ if (!empty($this->_ident)) {
+ $message = $this->_ident . ' ' . $message;
+ }
+
+ /* Check for message length. */
+ if (strlen($message) > $this->_maxsize) {
+ $message = substr($message, 0, ($this->_maxsize) - 10) . ' [...]';
+ }
+
+ /* Write to socket. */
+ fwrite($this->_socket, '<' . $facility_level . '>' . $message . "\n");
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+ }
+
+ /**
+ * Converts a PEAR_LOG_* constant into a syslog LOG_* constant.
+ *
+ * This function exists because, under Windows, not all of the LOG_*
+ * constants have unique values. Instead, the PEAR_LOG_* were introduced
+ * for global use, with the conversion to the LOG_* constants kept local to
+ * to the syslog driver.
+ *
+ * @param int $priority PEAR_LOG_* value to convert to LOG_* value.
+ *
+ * @return The LOG_* representation of $priority.
+ *
+ * @access private
+ */
+ function _toSyslog($priority)
+ {
+ static $priorities = array(
+ PEAR_LOG_EMERG => LOG_EMERG,
+ PEAR_LOG_ALERT => LOG_ALERT,
+ PEAR_LOG_CRIT => LOG_CRIT,
+ PEAR_LOG_ERR => LOG_ERR,
+ PEAR_LOG_WARNING => LOG_WARNING,
+ PEAR_LOG_NOTICE => LOG_NOTICE,
+ PEAR_LOG_INFO => LOG_INFO,
+ PEAR_LOG_DEBUG => LOG_DEBUG
+ );
+
+ /* If we're passed an unknown priority, default to LOG_INFO. */
+ if (!is_int($priority) || !in_array($priority, $priorities)) {
+ return LOG_INFO;
+ }
+
+ return $priorities[$priority];
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ *
+ * @version $Revision: 305290 $
+ * @package Log
+ */
+
+/**
+ * The Log_display class is a concrete implementation of the Log::
+ * abstract class which writes message into browser in usual PHP maner.
+ * This may be useful because when you use PEAR::setErrorHandling in
+ * PEAR_ERROR_CALLBACK mode error messages are not displayed by
+ * PHP error handler.
+ *
+ * @author Paul Yanchenko <pusher@inaco.ru>
+ * @since Log 1.8.0
+ * @package Log
+ *
+ * @example display.php Using the display handler.
+ */
+class Log_display extends Log
+{
+ /**
+ * String containing the format of a log line.
+ * @var string
+ * @access private
+ */
+ var $_lineFormat = '<b>%3$s</b>: %4$s';
+
+ /**
+ * String containing the timestamp format. It will be passed directly to
+ * strftime(). Note that the timestamp string will generated using the
+ * current locale.
+ * @var string
+ * @access private
+ */
+ var $_timeFormat = '%b %d %H:%M:%S';
+
+ /**
+ * Flag indicating whether raw message text should be passed directly to
+ * the log system. Otherwise, the text will be converted to an HTML-safe
+ * representation.
+ * @var boolean
+ * @access private
+ */
+ var $_rawText = false;
+
+ /**
+ * Constructs a new Log_display object.
+ *
+ * @param string $name Ignored.
+ * @param string $ident The identity string.
+ * @param array $conf The configuration array.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_display($name = '', $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ $this->_id = md5(microtime());
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+
+ /* Start by configuring the line format. */
+ if (!empty($conf['lineFormat'])) {
+ $this->_lineFormat = str_replace(array_keys($this->_formatMap),
+ array_values($this->_formatMap),
+ $conf['lineFormat']);
+ }
+
+ /* We may need to prepend a string to our line format. */
+ $prepend = null;
+ if (isset($conf['error_prepend'])) {
+ $prepend = $conf['error_prepend'];
+ } else {
+ $prepend = ini_get('error_prepend_string');
+ }
+ if (!empty($prepend)) {
+ $this->_lineFormat = $prepend . $this->_lineFormat;
+ }
+
+ /* We may also need to append a string to our line format. */
+ $append = null;
+ if (isset($conf['error_append'])) {
+ $append = $conf['error_append'];
+ } else {
+ $append = ini_get('error_append_string');
+ }
+ if (!empty($append)) {
+ $this->_lineFormat .= $append;
+ }
+
+ /* Lastly, the line ending sequence is also configurable. */
+ if (isset($conf['linebreak'])) {
+ $this->_lineFormat .= $conf['linebreak'];
+ } else {
+ $this->_lineFormat .= "<br />\n";
+ }
+
+ /* The user can also change the time format. */
+ if (!empty($conf['timeFormat'])) {
+ $this->_timeFormat = $conf['timeFormat'];
+ }
+
+ /* Message text conversion can be disabled. */
+ if (isset($conf['rawText'])) {
+ $this->_rawText = $conf['rawText'];
+ }
+ }
+
+ /**
+ * Opens the display handler.
+ *
+ * @access public
+ * @since Log 1.9.6
+ */
+ function open()
+ {
+ $this->_opened = true;
+ return true;
+ }
+
+ /**
+ * Closes the display handler.
+ *
+ * @access public
+ * @since Log 1.9.6
+ */
+ function close()
+ {
+ $this->_opened = false;
+ return true;
+ }
+
+ /**
+ * Writes $message to the text browser. Also, passes the message
+ * along to any Log_observer instances that are observing this Log.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param string $priority The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+
+ /* Convert the message to an HTML-friendly represention unless raw
+ * text has been requested. */
+ if ($this->_rawText === false) {
+ $message = nl2br(htmlspecialchars($message));
+ }
+
+ /* Build and output the complete log line. */
+ echo $this->_format($this->_lineFormat,
+ strftime($this->_timeFormat),
+ $priority,
+ $message);
+
+ /* Notify observers about this log message. */
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ *
+ * @version $Revision: 293927 $
+ * @package Log
+ */
+
+/**
+ * The Log_error_log class is a concrete implementation of the Log abstract
+ * class that logs messages using PHP's error_log() function.
+ *
+ * @author Jon Parise <jon@php.net>
+ * @since Log 1.7.0
+ * @package Log
+ *
+ * @example error_log.php Using the error_log handler.
+ */
+class Log_error_log extends Log
+{
+ /**
+ * The error_log() log type.
+ * @var integer
+ * @access private
+ */
+ var $_type = PEAR_LOG_TYPE_SYSTEM;
+
+ /**
+ * The type-specific destination value.
+ * @var string
+ * @access private
+ */
+ var $_destination = '';
+
+ /**
+ * Additional headers to pass to the mail() function when the
+ * PEAR_LOG_TYPE_MAIL type is used.
+ * @var string
+ * @access private
+ */
+ var $_extra_headers = '';
+
+ /**
+ * String containing the format of a log line.
+ * @var string
+ * @access private
+ */
+ var $_lineFormat = '%2$s: %4$s';
+
+ /**
+ * String containing the timestamp format. It will be passed directly to
+ * strftime(). Note that the timestamp string will generated using the
+ * current locale.
+ * @var string
+ * @access private
+ */
+ var $_timeFormat = '%b %d %H:%M:%S';
+
+ /**
+ * Constructs a new Log_error_log object.
+ *
+ * @param string $name One of the PEAR_LOG_TYPE_* constants.
+ * @param string $ident The identity string.
+ * @param array $conf The configuration array.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_error_log($name, $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ $this->_id = md5(microtime());
+ $this->_type = $name;
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+
+ if (!empty($conf['destination'])) {
+ $this->_destination = $conf['destination'];
+ }
+
+ if (!empty($conf['extra_headers'])) {
+ $this->_extra_headers = $conf['extra_headers'];
+ }
+
+ if (!empty($conf['lineFormat'])) {
+ $this->_lineFormat = str_replace(array_keys($this->_formatMap),
+ array_values($this->_formatMap),
+ $conf['lineFormat']);
+ }
+
+ if (!empty($conf['timeFormat'])) {
+ $this->_timeFormat = $conf['timeFormat'];
+ }
+ }
+
+ /**
+ * Opens the handler.
+ *
+ * @access public
+ * @since Log 1.9.6
+ */
+ function open()
+ {
+ $this->_opened = true;
+ return true;
+ }
+
+ /**
+ * Closes the handler.
+ *
+ * @access public
+ * @since Log 1.9.6
+ */
+ function close()
+ {
+ $this->_opened = false;
+ return true;
+ }
+
+ /**
+ * Logs $message using PHP's error_log() function. The message is also
+ * passed along to any Log_observer instances that are observing this Log.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param string $priority The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+
+ /* Build the string containing the complete log line. */
+ $line = $this->_format($this->_lineFormat,
+ strftime($this->_timeFormat),
+ $priority, $message);
+
+ /* Pass the log line and parameters to the error_log() function. */
+ $success = error_log($line, $this->_type, $this->_destination,
+ $this->_extra_headers);
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return $success;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ *
+ * @version $Revision: 224513 $
+ * @package Log
+ */
+
+/**
+ * The Log_file class is a concrete implementation of the Log abstract
+ * class that logs messages to a text file.
+ *
+ * @author Jon Parise <jon@php.net>
+ * @author Roman Neuhauser <neuhauser@bellavista.cz>
+ * @since Log 1.0
+ * @package Log
+ *
+ * @example file.php Using the file handler.
+ */
+class Log_file extends Log
+{
+ /**
+ * String containing the name of the log file.
+ * @var string
+ * @access private
+ */
+ var $_filename = 'php.log';
+
+ /**
+ * Handle to the log file.
+ * @var resource
+ * @access private
+ */
+ var $_fp = false;
+
+ /**
+ * Should new log entries be append to an existing log file, or should the
+ * a new log file overwrite an existing one?
+ * @var boolean
+ * @access private
+ */
+ var $_append = true;
+
+ /**
+ * Should advisory file locking (i.e., flock()) be used?
+ * @var boolean
+ * @access private
+ */
+ var $_locking = false;
+
+ /**
+ * Integer (in octal) containing the log file's permissions mode.
+ * @var integer
+ * @access private
+ */
+ var $_mode = 0644;
+
+ /**
+ * Integer (in octal) specifying the file permission mode that will be
+ * used when creating directories that do not already exist.
+ * @var integer
+ * @access private
+ */
+ var $_dirmode = 0755;
+
+ /**
+ * String containing the format of a log line.
+ * @var string
+ * @access private
+ */
+ var $_lineFormat = '%1$s %2$s [%3$s] %4$s';
+
+ /**
+ * String containing the timestamp format. It will be passed directly to
+ * strftime(). Note that the timestamp string will generated using the
+ * current locale.
+ * @var string
+ * @access private
+ */
+ var $_timeFormat = '%b %d %H:%M:%S';
+
+ /**
+ * String containing the end-on-line character sequence.
+ * @var string
+ * @access private
+ */
+ var $_eol = "\n";
+
+ /**
+ * Constructs a new Log_file object.
+ *
+ * @param string $name Ignored.
+ * @param string $ident The identity string.
+ * @param array $conf The configuration array.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_file($name, $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ $this->_id = md5(microtime());
+ $this->_filename = $name;
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+
+ if (isset($conf['append'])) {
+ $this->_append = $conf['append'];
+ }
+
+ if (isset($conf['locking'])) {
+ $this->_locking = $conf['locking'];
+ }
+
+ if (!empty($conf['mode'])) {
+ if (is_string($conf['mode'])) {
+ $this->_mode = octdec($conf['mode']);
+ } else {
+ $this->_mode = $conf['mode'];
+ }
+ }
+
+ if (!empty($conf['dirmode'])) {
+ if (is_string($conf['dirmode'])) {
+ $this->_dirmode = octdec($conf['dirmode']);
+ } else {
+ $this->_dirmode = $conf['dirmode'];
+ }
+ }
+
+ if (!empty($conf['lineFormat'])) {
+ $this->_lineFormat = str_replace(array_keys($this->_formatMap),
+ array_values($this->_formatMap),
+ $conf['lineFormat']);
+ }
+
+ if (!empty($conf['timeFormat'])) {
+ $this->_timeFormat = $conf['timeFormat'];
+ }
+
+ if (!empty($conf['eol'])) {
+ $this->_eol = $conf['eol'];
+ } else {
+ $this->_eol = (strstr(PHP_OS, 'WIN')) ? "\r\n" : "\n";
+ }
+
+ register_shutdown_function(array(&$this, '_Log_file'));
+ }
+
+ /**
+ * Destructor
+ */
+ function _Log_file()
+ {
+ if ($this->_opened) {
+ $this->close();
+ }
+ }
+
+ /**
+ * Creates the given directory path. If the parent directories don't
+ * already exist, they will be created, too.
+ *
+ * This implementation is inspired by Python's os.makedirs function.
+ *
+ * @param string $path The full directory path to create.
+ * @param integer $mode The permissions mode with which the
+ * directories will be created.
+ *
+ * @return True if the full path is successfully created or already
+ * exists.
+ *
+ * @access private
+ */
+ function _mkpath($path, $mode = 0700)
+ {
+ /* Separate the last pathname component from the rest of the path. */
+ $head = dirname($path);
+ $tail = basename($path);
+
+ /* Make sure we've split the path into two complete components. */
+ if (empty($tail)) {
+ $head = dirname($path);
+ $tail = basename($path);
+ }
+
+ /* Recurse up the path if our current segment does not exist. */
+ if (!empty($head) && !empty($tail) && !is_dir($head)) {
+ $this->_mkpath($head, $mode);
+ }
+
+ /* Create this segment of the path. */
+ return @mkdir($head, $mode);
+ }
+
+ /**
+ * Opens the log file for output. If the specified log file does not
+ * already exist, it will be created. By default, new log entries are
+ * appended to the end of the log file.
+ *
+ * This is implicitly called by log(), if necessary.
+ *
+ * @access public
+ */
+ function open()
+ {
+ if (!$this->_opened) {
+ /* If the log file's directory doesn't exist, create it. */
+ if (!is_dir(dirname($this->_filename))) {
+ $this->_mkpath($this->_filename, $this->_dirmode);
+ }
+
+ /* Determine whether the log file needs to be created. */
+ $creating = !file_exists($this->_filename);
+
+ /* Obtain a handle to the log file. */
+ $this->_fp = fopen($this->_filename, ($this->_append) ? 'a' : 'w');
+
+ /* We consider the file "opened" if we have a valid file pointer. */
+ $this->_opened = ($this->_fp !== false);
+
+ /* Attempt to set the file's permissions if we just created it. */
+ if ($creating && $this->_opened) {
+ chmod($this->_filename, $this->_mode);
+ }
+ }
+
+ return $this->_opened;
+ }
+
+ /**
+ * Closes the log file if it is open.
+ *
+ * @access public
+ */
+ function close()
+ {
+ /* If the log file is open, close it. */
+ if ($this->_opened && fclose($this->_fp)) {
+ $this->_opened = false;
+ }
+
+ return ($this->_opened === false);
+ }
+
+ /**
+ * Flushes all pending data to the file handle.
+ *
+ * @access public
+ * @since Log 1.8.2
+ */
+ function flush()
+ {
+ if (is_resource($this->_fp)) {
+ return fflush($this->_fp);
+ }
+
+ return false;
+ }
+
+ /**
+ * Logs $message to the output window. The message is also passed along
+ * to any Log_observer instances that are observing this Log.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param string $priority The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* If the log file isn't already open, open it now. */
+ if (!$this->_opened && !$this->open()) {
+ return false;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+
+ /* Build the string containing the complete log line. */
+ $line = $this->_format($this->_lineFormat,
+ strftime($this->_timeFormat),
+ $priority, $message) . $this->_eol;
+
+ /* If locking is enabled, acquire an exclusive lock on the file. */
+ if ($this->_locking) {
+ flock($this->_fp, LOCK_EX);
+ }
+
+ /* Write the log line to the log file. */
+ $success = (fwrite($this->_fp, $line) !== false);
+
+ /* Unlock the file now that we're finished writing to it. */
+ if ($this->_locking) {
+ flock($this->_fp, LOCK_UN);
+ }
+
+ /* Notify observers about this log message. */
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return $success;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ *
+ * @version $Revision: 313304 $
+ * @package Log
+ */
+
+/**
+ * The Log_firebug class is a concrete implementation of the Log::
+ * abstract class which writes message into Firebug console.
+ *
+ * http://www.getfirebug.com/
+ *
+ * @author Mika Tuupola <tuupola@appelsiini.net>
+ * @since Log 1.9.11
+ * @package Log
+ *
+ * @example firebug.php Using the firebug handler.
+ */
+class Log_firebug extends Log
+{
+ /**
+ * Should the output be buffered or displayed immediately?
+ * @var string
+ * @access private
+ */
+ var $_buffering = false;
+
+ /**
+ * String holding the buffered output.
+ * @var string
+ * @access private
+ */
+ var $_buffer = array();
+
+ /**
+ * String containing the format of a log line.
+ * @var string
+ * @access private
+ */
+ var $_lineFormat = '%2$s [%3$s] %4$s';
+
+ /**
+ * String containing the timestamp format. It will be passed directly to
+ * strftime(). Note that the timestamp string will generated using the
+ * current locale.
+ *
+ * Note! Default lineFormat of this driver does not display time.
+ *
+ * @var string
+ * @access private
+ */
+ var $_timeFormat = '%b %d %H:%M:%S';
+
+ /**
+ * Mapping of log priorities to Firebug methods.
+ * @var array
+ * @access private
+ */
+ var $_methods = array(
+ PEAR_LOG_EMERG => 'error',
+ PEAR_LOG_ALERT => 'error',
+ PEAR_LOG_CRIT => 'error',
+ PEAR_LOG_ERR => 'error',
+ PEAR_LOG_WARNING => 'warn',
+ PEAR_LOG_NOTICE => 'info',
+ PEAR_LOG_INFO => 'info',
+ PEAR_LOG_DEBUG => 'debug'
+ );
+
+ /**
+ * Constructs a new Log_firebug object.
+ *
+ * @param string $name Ignored.
+ * @param string $ident The identity string.
+ * @param array $conf The configuration array.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_firebug($name = '', $ident = 'PHP', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ $this->_id = md5(microtime());
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+ if (isset($conf['buffering'])) {
+ $this->_buffering = $conf['buffering'];
+ }
+
+ if ($this->_buffering) {
+ register_shutdown_function(array(&$this, '_Log_firebug'));
+ }
+
+ if (!empty($conf['lineFormat'])) {
+ $this->_lineFormat = str_replace(array_keys($this->_formatMap),
+ array_values($this->_formatMap),
+ $conf['lineFormat']);
+ }
+
+ if (!empty($conf['timeFormat'])) {
+ $this->_timeFormat = $conf['timeFormat'];
+ }
+ }
+
+ /**
+ * Opens the firebug handler.
+ *
+ * @access public
+ */
+ function open()
+ {
+ $this->_opened = true;
+ return true;
+ }
+
+ /**
+ * Destructor
+ */
+ function _Log_firebug()
+ {
+ $this->close();
+ }
+
+ /**
+ * Closes the firebug handler.
+ *
+ * @access public
+ */
+ function close()
+ {
+ $this->flush();
+ $this->_opened = false;
+ return true;
+ }
+
+ /**
+ * Flushes all pending ("buffered") data.
+ *
+ * @access public
+ */
+ function flush() {
+ if (count($this->_buffer)) {
+ print '<script type="text/javascript">';
+ print "\nif ('console' in window) {\n";
+ foreach ($this->_buffer as $line) {
+ print " $line\n";
+ }
+ print "}\n";
+ print "</script>\n";
+ };
+ $this->_buffer = array();
+ }
+
+ /**
+ * Writes $message to Firebug console. Also, passes the message
+ * along to any Log_observer instances that are observing this Log.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param string $priority The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+ $method = $this->_methods[$priority];
+
+ /* normalize line breaks and escape quotes*/
+ $message = preg_replace("/\r?\n/", "\\n", addslashes($message));
+
+ /* Build the string containing the complete log line. */
+ $line = $this->_format($this->_lineFormat,
+ strftime($this->_timeFormat),
+ $priority,
+ $message);
+
+ if ($this->_buffering) {
+ $this->_buffer[] = sprintf('console.%s("%s");', $method, $line);
+ } else {
+ print '<script type="text/javascript">';
+ print "\nif ('console' in window) {\n";
+ /* Build and output the complete log line. */
+ printf(' console.%s("%s");', $method, $line);
+ print "\n}\n";
+ print "</script>\n";
+ }
+ /* Notify observers about this log message. */
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ *
+ * @version $Revision: 266658 $
+ * @package Log
+ */
+
+/**
+ * The Log_mail class is a concrete implementation of the Log:: abstract class
+ * which sends log messages to a mailbox.
+ * The mail is actually sent when you close() the logger, or when the destructor
+ * is called (when the script is terminated).
+ *
+ * PLEASE NOTE that you must create a Log_mail object using =&, like this :
+ * $logger =& Log::factory("mail", "recipient@example.com", ...)
+ *
+ * This is a PEAR requirement for destructors to work properly.
+ * See http://pear.php.net/manual/en/class.pear.php
+ *
+ * @author Ronnie Garcia <ronnie@mk2.net>
+ * @author Jon Parise <jon@php.net>
+ * @since Log 1.3
+ * @package Log
+ *
+ * @example mail.php Using the mail handler.
+ */
+class Log_mail extends Log
+{
+ /**
+ * String holding the recipients' email addresses. Multiple addresses
+ * should be separated with commas.
+ * @var string
+ * @access private
+ */
+ var $_recipients = '';
+
+ /**
+ * String holding the sender's email address.
+ * @var string
+ * @access private
+ */
+ var $_from = '';
+
+ /**
+ * String holding the email's subject.
+ * @var string
+ * @access private
+ */
+ var $_subject = '[Log_mail] Log message';
+
+ /**
+ * String holding an optional preamble for the log messages.
+ * @var string
+ * @access private
+ */
+ var $_preamble = '';
+
+ /**
+ * String containing the format of a log line.
+ * @var string
+ * @access private
+ */
+ var $_lineFormat = '%1$s %2$s [%3$s] %4$s';
+
+ /**
+ * String containing the timestamp format. It will be passed directly to
+ * strftime(). Note that the timestamp string will generated using the
+ * current locale.
+ * @var string
+ * @access private
+ */
+ var $_timeFormat = '%b %d %H:%M:%S';
+
+ /**
+ * String holding the mail message body.
+ * @var string
+ * @access private
+ */
+ var $_message = '';
+
+ /**
+ * Flag used to indicated that log lines have been written to the message
+ * body and the message should be sent on close().
+ * @var boolean
+ * @access private
+ */
+ var $_shouldSend = false;
+
+ /**
+ * String holding the backend name of PEAR::Mail
+ * @var string
+ * @access private
+ */
+ var $_mailBackend = '';
+
+ /**
+ * Array holding the params for PEAR::Mail
+ * @var array
+ * @access private
+ */
+ var $_mailParams = array();
+
+ /**
+ * Constructs a new Log_mail object.
+ *
+ * Here is how you can customize the mail driver with the conf[] hash :
+ * $conf['from']: the mail's "From" header line,
+ * $conf['subject']: the mail's "Subject" line.
+ * $conf['mailBackend']: backend name of PEAR::Mail
+ * $conf['mailParams']: parameters for the PEAR::Mail backend
+ *
+ * @param string $name The message's recipients.
+ * @param string $ident The identity string.
+ * @param array $conf The configuration array.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_mail($name, $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ $this->_id = md5(microtime());
+ $this->_recipients = $name;
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+
+ if (!empty($conf['from'])) {
+ $this->_from = $conf['from'];
+ } else {
+ $this->_from = ini_get('sendmail_from');
+ }
+
+ if (!empty($conf['subject'])) {
+ $this->_subject = $conf['subject'];
+ }
+
+ if (!empty($conf['preamble'])) {
+ $this->_preamble = $conf['preamble'];
+ }
+
+ if (!empty($conf['lineFormat'])) {
+ $this->_lineFormat = str_replace(array_keys($this->_formatMap),
+ array_values($this->_formatMap),
+ $conf['lineFormat']);
+ }
+
+ if (!empty($conf['timeFormat'])) {
+ $this->_timeFormat = $conf['timeFormat'];
+ }
+
+ if (!empty($conf['mailBackend'])) {
+ $this->_mailBackend = $conf['mailBackend'];
+ }
+
+ if (!empty($conf['mailParams'])) {
+ $this->_mailParams = $conf['mailParams'];
+ }
+
+ /* register the destructor */
+ register_shutdown_function(array(&$this, '_Log_mail'));
+ }
+
+ /**
+ * Destructor. Calls close().
+ *
+ * @access private
+ */
+ function _Log_mail()
+ {
+ $this->close();
+ }
+
+ /**
+ * Starts a new mail message.
+ * This is implicitly called by log(), if necessary.
+ *
+ * @access public
+ */
+ function open()
+ {
+ if (!$this->_opened) {
+ if (!empty($this->_preamble)) {
+ $this->_message = $this->_preamble . "\r\n\r\n";
+ }
+ $this->_opened = true;
+ $_shouldSend = false;
+ }
+
+ return $this->_opened;
+ }
+
+ /**
+ * Closes the message, if it is open, and sends the mail.
+ * This is implicitly called by the destructor, if necessary.
+ *
+ * @access public
+ */
+ function close()
+ {
+ if ($this->_opened) {
+ if ($this->_shouldSend && !empty($this->_message)) {
+ if ($this->_mailBackend === '') { // use mail()
+ $headers = "From: $this->_from\r\n";
+ $headers .= 'User-Agent: PEAR Log Package';
+ if (mail($this->_recipients, $this->_subject,
+ $this->_message, $headers) == false) {
+ return false;
+ }
+ } else { // use PEAR::Mail
+ include_once 'Mail.php';
+ $headers = array('From' => $this->_from,
+ 'To' => $this->_recipients,
+ 'User-Agent' => 'PEAR Log Package',
+ 'Subject' => $this->_subject);
+ $mailer = &Mail::factory($this->_mailBackend,
+ $this->_mailParams);
+ $res = $mailer->send($this->_recipients, $headers,
+ $this->_message);
+ if (PEAR::isError($res)) {
+ return false;
+ }
+ }
+
+ /* Clear the message string now that the email has been sent. */
+ $this->_message = '';
+ $this->_shouldSend = false;
+ }
+ $this->_opened = false;
+ }
+
+ return ($this->_opened === false);
+ }
+
+ /**
+ * Flushes the log output by forcing the email message to be sent now.
+ * Events that are logged after flush() is called will be appended to a
+ * new email message.
+ *
+ * @access public
+ * @since Log 1.8.2
+ */
+ function flush()
+ {
+ /*
+ * It's sufficient to simply call close() to flush the output.
+ * The next call to log() will cause the handler to be reopened.
+ */
+ return $this->close();
+ }
+
+ /**
+ * Writes $message to the currently open mail message.
+ * Calls open(), if necessary.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param string $priority The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* If the message isn't open and can't be opened, return failure. */
+ if (!$this->_opened && !$this->open()) {
+ return false;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+
+ /* Append the string containing the complete log line. */
+ $this->_message .= $this->_format($this->_lineFormat,
+ strftime($this->_timeFormat),
+ $priority, $message) . "\r\n";
+ $this->_shouldSend = true;
+
+ /* Notify observers about this log message. */
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ * $Horde: horde/lib/Log/mcal.php,v 1.2 2000/06/28 21:36:13 jon Exp $
+ *
+ * @version $Revision: 180836 $
+ * @package Log
+ */
+
+/**
+ * The Log_mcal class is a concrete implementation of the Log::
+ * abstract class which sends messages to a local or remote calendar
+ * store accessed through MCAL.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @since Horde 1.3
+ * @since Log 1.0
+ * @package Log
+ */
+class Log_mcal extends Log
+{
+ /**
+ * holding the calendar specification to connect to.
+ * @var string
+ * @access private
+ */
+ var $_calendar = '{localhost/mstore}';
+
+ /**
+ * holding the username to use.
+ * @var string
+ * @access private
+ */
+ var $_username = '';
+
+ /**
+ * holding the password to use.
+ * @var string
+ * @access private
+ */
+ var $_password = '';
+
+ /**
+ * holding the options to pass to the calendar stream.
+ * @var integer
+ * @access private
+ */
+ var $_options = 0;
+
+ /**
+ * ResourceID of the MCAL stream.
+ * @var string
+ * @access private
+ */
+ var $_stream = '';
+
+ /**
+ * Integer holding the log facility to use.
+ * @var string
+ * @access private
+ */
+ var $_name = LOG_SYSLOG;
+
+
+ /**
+ * Constructs a new Log_mcal object.
+ *
+ * @param string $name The category to use for our events.
+ * @param string $ident The identity string.
+ * @param array $conf The configuration array.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_mcal($name, $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ $this->_id = md5(microtime());
+ $this->_name = $name;
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+ $this->_calendar = $conf['calendar'];
+ $this->_username = $conf['username'];
+ $this->_password = $conf['password'];
+ $this->_options = $conf['options'];
+ }
+
+ /**
+ * Opens a calendar stream, if it has not already been
+ * opened. This is implicitly called by log(), if necessary.
+ * @access public
+ */
+ function open()
+ {
+ if (!$this->_opened) {
+ $this->_stream = mcal_open($this->_calendar, $this->_username,
+ $this->_password, $this->_options);
+ $this->_opened = true;
+ }
+
+ return $this->_opened;
+ }
+
+ /**
+ * Closes the calendar stream, if it is open.
+ * @access public
+ */
+ function close()
+ {
+ if ($this->_opened) {
+ mcal_close($this->_stream);
+ $this->_opened = false;
+ }
+
+ return ($this->_opened === false);
+ }
+
+ /**
+ * Logs $message and associated information to the currently open
+ * calendar stream. Calls open() if necessary. Also passes the
+ * message along to any Log_observer instances that are observing
+ * this Log.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param string $priority The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* If the connection isn't open and can't be opened, return failure. */
+ if (!$this->_opened && !$this->open()) {
+ return false;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+
+ $date_str = date('Y:n:j:G:i:s');
+ $dates = explode(':', $date_str);
+
+ mcal_event_init($this->_stream);
+ mcal_event_set_title($this->_stream, $this->_ident);
+ mcal_event_set_category($this->_stream, $this->_name);
+ mcal_event_set_description($this->_stream, $message);
+ mcal_event_add_attribute($this->_stream, 'priority', $priority);
+ mcal_event_set_start($this->_stream, $dates[0], $dates[1], $dates[2],
+ $dates[3], $dates[4], $dates[5]);
+ mcal_event_set_end($this->_stream, $dates[0], $dates[1], $dates[2],
+ $dates[3], $dates[4], $dates[5]);
+ mcal_append_event($this->_stream);
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ *
+ * @version $Revision: 204814 $
+ * @package Log
+ */
+
+/** PEAR's MDB2 package */
+require_once 'MDB2.php';
+MDB2::loadFile('Date');
+
+/**
+ * The Log_mdb2 class is a concrete implementation of the Log:: abstract class
+ * which sends messages to an SQL server. Each entry occupies a separate row
+ * in the database.
+ *
+ * This implementation uses PEAR's MDB2 database abstraction layer.
+ *
+ * CREATE TABLE log_table (
+ * id INT NOT NULL,
+ * logtime TIMESTAMP NOT NULL,
+ * ident CHAR(16) NOT NULL,
+ * priority INT NOT NULL,
+ * message VARCHAR(200),
+ * PRIMARY KEY (id)
+ * );
+ *
+ * @author Lukas Smith <smith@backendmedia.com>
+ * @author Jon Parise <jon@php.net>
+ * @since Log 1.9.0
+ * @package Log
+ */
+class Log_mdb2 extends Log
+{
+ /**
+ * Variable containing the DSN information.
+ * @var mixed
+ * @access private
+ */
+ var $_dsn = '';
+
+ /**
+ * Array containing our set of DB configuration options.
+ * @var array
+ * @access private
+ */
+ var $_options = array('persistent' => true);
+
+ /**
+ * Object holding the database handle.
+ * @var object
+ * @access private
+ */
+ var $_db = null;
+
+ /**
+ * Resource holding the prepared statement handle.
+ * @var resource
+ * @access private
+ */
+ var $_statement = null;
+
+ /**
+ * Flag indicating that we're using an existing database connection.
+ * @var boolean
+ * @access private
+ */
+ var $_existingConnection = false;
+
+ /**
+ * String holding the database table to use.
+ * @var string
+ * @access private
+ */
+ var $_table = 'log_table';
+
+ /**
+ * String holding the name of the ID sequence.
+ * @var string
+ * @access private
+ */
+ var $_sequence = 'log_id';
+
+ /**
+ * Maximum length of the $ident string. This corresponds to the size of
+ * the 'ident' column in the SQL table.
+ * @var integer
+ * @access private
+ */
+ var $_identLimit = 16;
+
+ /**
+ * Set of field types used in the database table.
+ * @var array
+ * @access private
+ */
+ var $_types = array(
+ 'id' => 'integer',
+ 'logtime' => 'timestamp',
+ 'ident' => 'text',
+ 'priority' => 'text',
+ 'message' => 'clob'
+ );
+
+ /**
+ * Constructs a new sql logging object.
+ *
+ * @param string $name The target SQL table.
+ * @param string $ident The identification field.
+ * @param array $conf The connection configuration array.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_mdb2($name, $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ $this->_id = md5(microtime());
+ $this->_table = $name;
+ $this->_mask = Log::UPTO($level);
+
+ /* If an options array was provided, use it. */
+ if (isset($conf['options']) && is_array($conf['options'])) {
+ $this->_options = $conf['options'];
+ }
+
+ /* If a specific sequence name was provided, use it. */
+ if (!empty($conf['sequence'])) {
+ $this->_sequence = $conf['sequence'];
+ }
+
+ /* If a specific sequence name was provided, use it. */
+ if (isset($conf['identLimit'])) {
+ $this->_identLimit = $conf['identLimit'];
+ }
+
+ /* Now that the ident limit is confirmed, set the ident string. */
+ $this->setIdent($ident);
+
+ /* If an existing database connection was provided, use it. */
+ if (isset($conf['db'])) {
+ $this->_db = &$conf['db'];
+ $this->_existingConnection = true;
+ $this->_opened = true;
+ } elseif (isset($conf['singleton'])) {
+ $this->_db = &MDB2::singleton($conf['singleton'], $this->_options);
+ $this->_existingConnection = true;
+ $this->_opened = true;
+ } else {
+ $this->_dsn = $conf['dsn'];
+ }
+ }
+
+ /**
+ * Opens a connection to the database, if it has not already
+ * been opened. This is implicitly called by log(), if necessary.
+ *
+ * @return boolean True on success, false on failure.
+ * @access public
+ */
+ function open()
+ {
+ if (!$this->_opened) {
+ /* Use the DSN and options to create a database connection. */
+ $this->_db = &MDB2::connect($this->_dsn, $this->_options);
+ if (PEAR::isError($this->_db)) {
+ return false;
+ }
+
+ /* Create a prepared statement for repeated use in log(). */
+ if (!$this->_prepareStatement()) {
+ return false;
+ }
+
+ /* We now consider out connection open. */
+ $this->_opened = true;
+ }
+
+ return $this->_opened;
+ }
+
+ /**
+ * Closes the connection to the database if it is still open and we were
+ * the ones that opened it. It is the caller's responsible to close an
+ * existing connection that was passed to us via $conf['db'].
+ *
+ * @return boolean True on success, false on failure.
+ * @access public
+ */
+ function close()
+ {
+ /* If we have a statement object, free it. */
+ if (is_object($this->_statement)) {
+ $this->_statement->free();
+ $this->_statement = null;
+ }
+
+ /* If we opened the database connection, disconnect it. */
+ if ($this->_opened && !$this->_existingConnection) {
+ $this->_opened = false;
+ return $this->_db->disconnect();
+ }
+
+ return ($this->_opened === false);
+ }
+
+ /**
+ * Sets this Log instance's identification string. Note that this
+ * SQL-specific implementation will limit the length of the $ident string
+ * to sixteen (16) characters.
+ *
+ * @param string $ident The new identification string.
+ *
+ * @access public
+ * @since Log 1.8.5
+ */
+ function setIdent($ident)
+ {
+ $this->_ident = substr($ident, 0, $this->_identLimit);
+ }
+
+ /**
+ * Inserts $message to the currently open database. Calls open(),
+ * if necessary. Also passes the message along to any Log_observer
+ * instances that are observing this Log.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param string $priority The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* If the connection isn't open and can't be opened, return failure. */
+ if (!$this->_opened && !$this->open()) {
+ return false;
+ }
+
+ /* If we don't already have a statement object, create one. */
+ if (!is_object($this->_statement) && !$this->_prepareStatement()) {
+ return false;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+
+ /* Build our set of values for this log entry. */
+ $values = array(
+ 'id' => $this->_db->nextId($this->_sequence),
+ 'logtime' => MDB2_Date::mdbNow(),
+ 'ident' => $this->_ident,
+ 'priority' => $priority,
+ 'message' => $message
+ );
+
+ /* Execute the SQL query for this log entry insertion. */
+ $this->_db->expectError(MDB2_ERROR_NOSUCHTABLE);
+ $result = &$this->_statement->execute($values);
+ $this->_db->popExpect();
+
+ /* Attempt to handle any errors. */
+ if (PEAR::isError($result)) {
+ /* We can only handle MDB2_ERROR_NOSUCHTABLE errors. */
+ if ($result->getCode() != MDB2_ERROR_NOSUCHTABLE) {
+ return false;
+ }
+
+ /* Attempt to create the target table. */
+ if (!$this->_createTable()) {
+ return false;
+ }
+
+ /* Recreate our prepared statement resource. */
+ $this->_statement->free();
+ if (!$this->_prepareStatement()) {
+ return false;
+ }
+
+ /* Attempt to re-execute the insertion query. */
+ $result = $this->_statement->execute($values);
+ if (PEAR::isError($result)) {
+ return false;
+ }
+ }
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+
+ /**
+ * Create the log table in the database.
+ *
+ * @return boolean True on success or false on failure.
+ * @access private
+ */
+ function _createTable()
+ {
+ $this->_db->loadModule('Manager', null, true);
+ $result = $this->_db->manager->createTable(
+ $this->_table,
+ array(
+ 'id' => array('type' => $this->_types['id']),
+ 'logtime' => array('type' => $this->_types['logtime']),
+ 'ident' => array('type' => $this->_types['ident']),
+ 'priority' => array('type' => $this->_types['priority']),
+ 'message' => array('type' => $this->_types['message'])
+ )
+ );
+ if (PEAR::isError($result)) {
+ return false;
+ }
+
+ $result = $this->_db->manager->createIndex(
+ $this->_table,
+ 'unique_id',
+ array('fields' => array('id' => true), 'unique' => true)
+ );
+ if (PEAR::isError($result)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Prepare the SQL insertion statement.
+ *
+ * @return boolean True if the statement was successfully created.
+ *
+ * @access private
+ * @since Log 1.9.0
+ */
+ function _prepareStatement()
+ {
+ $this->_statement = &$this->_db->prepare(
+ 'INSERT INTO ' . $this->_table .
+ ' (id, logtime, ident, priority, message)' .
+ ' VALUES(:id, :logtime, :ident, :priority, :message)',
+ $this->_types, MDB2_PREPARE_MANIP);
+
+ /* Return success if we didn't generate an error. */
+ return (PEAR::isError($this->_statement) === false);
+ }
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ *
+ * @version $Revision: 215527 $
+ * @package Log
+ */
+
+/**
+ * The Log_null class is a concrete implementation of the Log:: abstract
+ * class. It simply consumes log events.
+ *
+ * @author Jon Parise <jon@php.net>
+ * @since Log 1.8.2
+ * @package Log
+ *
+ * @example null.php Using the null handler.
+ */
+class Log_null extends Log
+{
+ /**
+ * Constructs a new Log_null object.
+ *
+ * @param string $name Ignored.
+ * @param string $ident The identity string.
+ * @param array $conf The configuration array.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_null($name, $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ $this->_id = md5(microtime());
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+ }
+
+ /**
+ * Opens the handler.
+ *
+ * @access public
+ * @since Log 1.9.6
+ */
+ function open()
+ {
+ $this->_opened = true;
+ return true;
+ }
+
+ /**
+ * Closes the handler.
+ *
+ * @access public
+ * @since Log 1.9.6
+ */
+ function close()
+ {
+ $this->_opened = false;
+ return true;
+ }
+
+ /**
+ * Simply consumes the log event. The message will still be passed
+ * along to any Log_observer instances that are observing this Log.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param string $priority The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ * $Horde: horde/lib/Log/observer.php,v 1.5 2000/06/28 21:36:13 jon Exp $
+ *
+ * @version $Revision: 316951 $
+ * @package Log
+ */
+
+/**
+ * The Log_observer:: class implements the Observer end of a Subject-Observer
+ * pattern for watching log activity and taking actions on exceptional events.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @since Horde 1.3
+ * @since Log 1.0
+ * @package Log
+ *
+ * @example observer_mail.php An example Log_observer implementation.
+ */
+class Log_observer
+{
+ /**
+ * Instance-specific unique identification number.
+ *
+ * @var integer
+ * @access private
+ */
+ var $_id = 0;
+
+ /**
+ * The minimum priority level of message that we want to hear about.
+ * PEAR_LOG_EMERG is the highest priority, so we will only hear messages
+ * with an integer priority value less than or equal to ours. It defaults
+ * to PEAR_LOG_INFO, which listens to everything except PEAR_LOG_DEBUG.
+ *
+ * @var string
+ * @access private
+ */
+ var $_priority = PEAR_LOG_INFO;
+
+ /**
+ * Creates a new basic Log_observer instance.
+ *
+ * @param integer $priority The highest priority at which to receive
+ * log event notifications.
+ *
+ * @access public
+ */
+ function Log_observer($priority = PEAR_LOG_INFO)
+ {
+ $this->_id = md5(microtime());
+ $this->_priority = $priority;
+ }
+
+ /**
+ * Attempts to return a new concrete Log_observer instance of the requested
+ * type.
+ *
+ * @param string $type The type of concreate Log_observer subclass
+ * to return.
+ * @param integer $priority The highest priority at which to receive
+ * log event notifications.
+ * @param array $conf Optional associative array of additional
+ * configuration values.
+ *
+ * @return object The newly created concrete Log_observer
+ * instance, or null on an error.
+ */
+ function &factory($type, $priority = PEAR_LOG_INFO, $conf = array())
+ {
+ $type = strtolower($type);
+ $class = 'Log_observer_' . $type;
+
+ /*
+ * If the desired class already exists (because the caller has supplied
+ * it from some custom location), simply instantiate and return a new
+ * instance.
+ */
+ if (class_exists($class)) {
+ $object = new $class($priority, $conf);
+ return $object;
+ }
+
+ /* Support both the new-style and old-style file naming conventions. */
+ $newstyle = true;
+ $classfile = dirname(__FILE__) . '/observer_' . $type . '.php';
+
+ if (!file_exists($classfile)) {
+ $classfile = 'Log/' . $type . '.php';
+ $newstyle = false;
+ }
+
+ /*
+ * Attempt to include our version of the named class, but don't treat
+ * a failure as fatal. The caller may have already included their own
+ * version of the named class.
+ */
+ @include_once $classfile;
+
+ /* If the class exists, return a new instance of it. */
+ if (class_exists($class)) {
+ /* Support both new-style and old-style construction. */
+ if ($newstyle) {
+ $object = new $class($priority, $conf);
+ } else {
+ $object = new $class($priority);
+ }
+ return $object;
+ }
+
+ $null = null;
+ return $null;
+ }
+
+ /**
+ * This is a stub method to make sure that Log_Observer classes do
+ * something when they are notified of a message. The default behavior
+ * is to just print the message, which is obviously not desireable in
+ * practically any situation - which is why you need to override this
+ * method. :)
+ *
+ * @param array $event A hash describing the log event.
+ */
+ function notify($event)
+ {
+ print_r($event);
+ }
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ * $Horde: horde/lib/Log/sql.php,v 1.12 2000/08/16 20:27:34 chuck Exp $
+ *
+ * @version $Revision: 250926 $
+ * @package Log
+ */
+
+/**
+ * We require the PEAR DB class. This is generally defined in the DB.php file,
+ * but it's possible that the caller may have provided the DB class, or a
+ * compatible wrapper (such as the one shipped with MDB2), so we first check
+ * for an existing 'DB' class before including 'DB.php'.
+ */
+if (!class_exists('DB')) {
+ require_once 'DB.php';
+}
+
+/**
+ * The Log_sql class is a concrete implementation of the Log::
+ * abstract class which sends messages to an SQL server. Each entry
+ * occupies a separate row in the database.
+ *
+ * This implementation uses PHP's PEAR database abstraction layer.
+ *
+ * CREATE TABLE log_table (
+ * id INT NOT NULL,
+ * logtime TIMESTAMP NOT NULL,
+ * ident CHAR(16) NOT NULL,
+ * priority INT NOT NULL,
+ * message VARCHAR(200),
+ * PRIMARY KEY (id)
+ * );
+ *
+ * @author Jon Parise <jon@php.net>
+ * @since Horde 1.3
+ * @since Log 1.0
+ * @package Log
+ *
+ * @example sql.php Using the SQL handler.
+ */
+class Log_sql extends Log
+{
+ /**
+ * Variable containing the DSN information.
+ * @var mixed
+ * @access private
+ */
+ var $_dsn = '';
+
+ /**
+ * String containing the SQL insertion statement.
+ *
+ * @var string
+ * @access private
+ */
+ var $_sql = '';
+
+ /**
+ * Array containing our set of DB configuration options.
+ * @var array
+ * @access private
+ */
+ var $_options = array('persistent' => true);
+
+ /**
+ * Object holding the database handle.
+ * @var object
+ * @access private
+ */
+ var $_db = null;
+
+ /**
+ * Resource holding the prepared statement handle.
+ * @var resource
+ * @access private
+ */
+ var $_statement = null;
+
+ /**
+ * Flag indicating that we're using an existing database connection.
+ * @var boolean
+ * @access private
+ */
+ var $_existingConnection = false;
+
+ /**
+ * String holding the database table to use.
+ * @var string
+ * @access private
+ */
+ var $_table = 'log_table';
+
+ /**
+ * String holding the name of the ID sequence.
+ * @var string
+ * @access private
+ */
+ var $_sequence = 'log_id';
+
+ /**
+ * Maximum length of the $ident string. This corresponds to the size of
+ * the 'ident' column in the SQL table.
+ * @var integer
+ * @access private
+ */
+ var $_identLimit = 16;
+
+
+ /**
+ * Constructs a new sql logging object.
+ *
+ * @param string $name The target SQL table.
+ * @param string $ident The identification field.
+ * @param array $conf The connection configuration array.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_sql($name, $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ $this->_id = md5(microtime());
+ $this->_table = $name;
+ $this->_mask = Log::UPTO($level);
+
+ /* Now that we have a table name, assign our SQL statement. */
+ if (!empty($conf['sql'])) {
+ $this->_sql = $conf['sql'];
+ } else {
+ $this->_sql = 'INSERT INTO ' . $this->_table .
+ ' (id, logtime, ident, priority, message)' .
+ ' VALUES(?, CURRENT_TIMESTAMP, ?, ?, ?)';
+ }
+
+ /* If an options array was provided, use it. */
+ if (isset($conf['options']) && is_array($conf['options'])) {
+ $this->_options = $conf['options'];
+ }
+
+ /* If a specific sequence name was provided, use it. */
+ if (!empty($conf['sequence'])) {
+ $this->_sequence = $conf['sequence'];
+ }
+
+ /* If a specific sequence name was provided, use it. */
+ if (isset($conf['identLimit'])) {
+ $this->_identLimit = $conf['identLimit'];
+ }
+
+ /* Now that the ident limit is confirmed, set the ident string. */
+ $this->setIdent($ident);
+
+ /* If an existing database connection was provided, use it. */
+ if (isset($conf['db'])) {
+ $this->_db = &$conf['db'];
+ $this->_existingConnection = true;
+ $this->_opened = true;
+ } else {
+ $this->_dsn = $conf['dsn'];
+ }
+ }
+
+ /**
+ * Opens a connection to the database, if it has not already
+ * been opened. This is implicitly called by log(), if necessary.
+ *
+ * @return boolean True on success, false on failure.
+ * @access public
+ */
+ function open()
+ {
+ if (!$this->_opened) {
+ /* Use the DSN and options to create a database connection. */
+ $this->_db = &DB::connect($this->_dsn, $this->_options);
+ if (DB::isError($this->_db)) {
+ return false;
+ }
+
+ /* Create a prepared statement for repeated use in log(). */
+ if (!$this->_prepareStatement()) {
+ return false;
+ }
+
+ /* We now consider out connection open. */
+ $this->_opened = true;
+ }
+
+ return $this->_opened;
+ }
+
+ /**
+ * Closes the connection to the database if it is still open and we were
+ * the ones that opened it. It is the caller's responsible to close an
+ * existing connection that was passed to us via $conf['db'].
+ *
+ * @return boolean True on success, false on failure.
+ * @access public
+ */
+ function close()
+ {
+ if ($this->_opened && !$this->_existingConnection) {
+ $this->_opened = false;
+ $this->_db->freePrepared($this->_statement);
+ return $this->_db->disconnect();
+ }
+
+ return ($this->_opened === false);
+ }
+
+ /**
+ * Sets this Log instance's identification string. Note that this
+ * SQL-specific implementation will limit the length of the $ident string
+ * to sixteen (16) characters.
+ *
+ * @param string $ident The new identification string.
+ *
+ * @access public
+ * @since Log 1.8.5
+ */
+ function setIdent($ident)
+ {
+ $this->_ident = substr($ident, 0, $this->_identLimit);
+ }
+
+ /**
+ * Inserts $message to the currently open database. Calls open(),
+ * if necessary. Also passes the message along to any Log_observer
+ * instances that are observing this Log.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param string $priority The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* If the connection isn't open and can't be opened, return failure. */
+ if (!$this->_opened && !$this->open()) {
+ return false;
+ }
+
+ /* If we don't already have our statement object yet, create it. */
+ if (!is_object($this->_statement) && !$this->_prepareStatement()) {
+ return false;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+
+ /* Build our set of values for this log entry. */
+ $id = $this->_db->nextId($this->_sequence);
+ $values = array($id, $this->_ident, $priority, $message);
+
+ /* Execute the SQL query for this log entry insertion. */
+ $result =& $this->_db->execute($this->_statement, $values);
+ if (DB::isError($result)) {
+ return false;
+ }
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+
+ /**
+ * Prepare the SQL insertion statement.
+ *
+ * @return boolean True if the statement was successfully created.
+ *
+ * @access private
+ * @since Log 1.9.1
+ */
+ function _prepareStatement()
+ {
+ $this->_statement = $this->_db->prepare($this->_sql);
+
+ /* Return success if we didn't generate an error. */
+ return (DB::isError($this->_statement) === false);
+ }
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ *
+ * @version $Revision: 202069 $
+ * @package Log
+ */
+
+/**
+ * The Log_sqlite class is a concrete implementation of the Log::
+ * abstract class which sends messages to an Sqlite database.
+ * Each entry occupies a separate row in the database.
+ *
+ * This implementation uses PHP native Sqlite functions.
+ *
+ * CREATE TABLE log_table (
+ * id INTEGER PRIMARY KEY NOT NULL,
+ * logtime NOT NULL,
+ * ident CHAR(16) NOT NULL,
+ * priority INT NOT NULL,
+ * message
+ * );
+ *
+ * @author Bertrand Mansion <bmansion@mamasam.com>
+ * @author Jon Parise <jon@php.net>
+ * @since Log 1.8.3
+ * @package Log
+ *
+ * @example sqlite.php Using the Sqlite handler.
+ */
+class Log_sqlite extends Log
+{
+ /**
+ * Array containing the connection defaults
+ * @var array
+ * @access private
+ */
+ var $_options = array('mode' => 0666,
+ 'persistent' => false);
+
+ /**
+ * Object holding the database handle.
+ * @var object
+ * @access private
+ */
+ var $_db = null;
+
+ /**
+ * Flag indicating that we're using an existing database connection.
+ * @var boolean
+ * @access private
+ */
+ var $_existingConnection = false;
+
+ /**
+ * String holding the database table to use.
+ * @var string
+ * @access private
+ */
+ var $_table = 'log_table';
+
+
+ /**
+ * Constructs a new sql logging object.
+ *
+ * @param string $name The target SQL table.
+ * @param string $ident The identification field.
+ * @param mixed $conf Can be an array of configuration options used
+ * to open a new database connection
+ * or an already opened sqlite connection.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_sqlite($name, $ident = '', &$conf, $level = PEAR_LOG_DEBUG)
+ {
+ $this->_id = md5(microtime());
+ $this->_table = $name;
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+
+ if (is_array($conf)) {
+ foreach ($conf as $k => $opt) {
+ $this->_options[$k] = $opt;
+ }
+ } else {
+ // If an existing database connection was provided, use it.
+ $this->_db =& $conf;
+ $this->_existingConnection = true;
+ }
+ }
+
+ /**
+ * Opens a connection to the database, if it has not already
+ * been opened. This is implicitly called by log(), if necessary.
+ *
+ * @return boolean True on success, false on failure.
+ * @access public
+ */
+ function open()
+ {
+ if (is_resource($this->_db)) {
+ $this->_opened = true;
+ return $this->_createTable();
+ } else {
+ /* Set the connection function based on the 'persistent' option. */
+ if (empty($this->_options['persistent'])) {
+ $connectFunction = 'sqlite_open';
+ } else {
+ $connectFunction = 'sqlite_popen';
+ }
+
+ /* Attempt to connect to the database. */
+ if ($this->_db = $connectFunction($this->_options['filename'],
+ (int)$this->_options['mode'],
+ $error)) {
+ $this->_opened = true;
+ return $this->_createTable();
+ }
+ }
+
+ return $this->_opened;
+ }
+
+ /**
+ * Closes the connection to the database if it is still open and we were
+ * the ones that opened it. It is the caller's responsible to close an
+ * existing connection that was passed to us via $conf['db'].
+ *
+ * @return boolean True on success, false on failure.
+ * @access public
+ */
+ function close()
+ {
+ /* We never close existing connections. */
+ if ($this->_existingConnection) {
+ return false;
+ }
+
+ if ($this->_opened) {
+ $this->_opened = false;
+ sqlite_close($this->_db);
+ }
+
+ return ($this->_opened === false);
+ }
+
+ /**
+ * Inserts $message to the currently open database. Calls open(),
+ * if necessary. Also passes the message along to any Log_observer
+ * instances that are observing this Log.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param string $priority The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* If the connection isn't open and can't be opened, return failure. */
+ if (!$this->_opened && !$this->open()) {
+ return false;
+ }
+
+ // Extract the string representation of the message.
+ $message = $this->_extractMessage($message);
+
+ // Build the SQL query for this log entry insertion.
+ $q = sprintf('INSERT INTO [%s] (logtime, ident, priority, message) ' .
+ "VALUES ('%s', '%s', %d, '%s')",
+ $this->_table,
+ strftime('%Y-%m-%d %H:%M:%S', time()),
+ sqlite_escape_string($this->_ident),
+ $priority,
+ sqlite_escape_string($message));
+ if (!($res = @sqlite_unbuffered_query($this->_db, $q))) {
+ return false;
+ }
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+
+ /**
+ * Checks whether the log table exists and creates it if necessary.
+ *
+ * @return boolean True on success or false on failure.
+ * @access private
+ */
+ function _createTable()
+ {
+ $q = "SELECT name FROM sqlite_master WHERE name='" . $this->_table .
+ "' AND type='table'";
+
+ $res = sqlite_query($this->_db, $q);
+
+ if (sqlite_num_rows($res) == 0) {
+ $q = 'CREATE TABLE [' . $this->_table . '] (' .
+ 'id INTEGER PRIMARY KEY NOT NULL, ' .
+ 'logtime NOT NULL, ' .
+ 'ident CHAR(16) NOT NULL, ' .
+ 'priority INT NOT NULL, ' .
+ 'message)';
+
+ if (!($res = sqlite_unbuffered_query($this->_db, $q))) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ * $Horde: horde/lib/Log/syslog.php,v 1.6 2000/06/28 21:36:13 jon Exp $
+ *
+ * @version $Revision: 308379 $
+ * @package Log
+ */
+
+/**
+ * The Log_syslog class is a concrete implementation of the Log::
+ * abstract class which sends messages to syslog on UNIX-like machines
+ * (PHP emulates this with the Event Log on Windows machines).
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Jon Parise <jon@php.net>
+ * @since Horde 1.3
+ * @since Log 1.0
+ * @package Log
+ *
+ * @example syslog.php Using the syslog handler.
+ */
+class Log_syslog extends Log
+{
+ /**
+ * Integer holding the log facility to use.
+ * @var integer
+ * @access private
+ */
+ var $_name = LOG_SYSLOG;
+
+ /**
+ * Should we inherit the current syslog connection for this process, or
+ * should we call openlog() to start a new syslog connection?
+ * @var boolean
+ * @access private
+ */
+ var $_inherit = false;
+
+ /**
+ * Should we re-open the syslog connection for each log event?
+ * @var boolean
+ * @access private
+ */
+ var $_reopen = false;
+
+ /**
+ * Maximum message length that will be sent to syslog(). If the handler
+ * receives a message longer than this length limit, it will be split into
+ * multiple syslog() calls.
+ * @var integer
+ * @access private
+ */
+ var $_maxLength = 500;
+
+ /**
+ * String containing the format of a message.
+ * @var string
+ * @access private
+ */
+ var $_lineFormat = '%4$s';
+
+ /**
+ * String containing the timestamp format. It will be passed directly to
+ * strftime(). Note that the timestamp string will generated using the
+ * current locale.
+ * @var string
+ * @access private
+ */
+ var $_timeFormat = '%b %d %H:%M:%S';
+
+ /**
+ * Constructs a new syslog object.
+ *
+ * @param string $name The syslog facility.
+ * @param string $ident The identity string.
+ * @param array $conf The configuration array.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_syslog($name, $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ /* Ensure we have a valid integer value for $name. */
+ if (empty($name) || !is_int($name)) {
+ $name = LOG_SYSLOG;
+ }
+
+ if (isset($conf['inherit'])) {
+ $this->_inherit = $conf['inherit'];
+ $this->_opened = $this->_inherit;
+ }
+ if (isset($conf['reopen'])) {
+ $this->_reopen = $conf['reopen'];
+ }
+ if (isset($conf['maxLength'])) {
+ $this->_maxLength = $conf['maxLength'];
+ }
+ if (!empty($conf['lineFormat'])) {
+ $this->_lineFormat = str_replace(array_keys($this->_formatMap),
+ array_values($this->_formatMap),
+ $conf['lineFormat']);
+ }
+ if (!empty($conf['timeFormat'])) {
+ $this->_timeFormat = $conf['timeFormat'];
+ }
+
+ $this->_id = md5(microtime());
+ $this->_name = $name;
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+ }
+
+ /**
+ * Opens a connection to the system logger, if it has not already
+ * been opened. This is implicitly called by log(), if necessary.
+ * @access public
+ */
+ function open()
+ {
+ if (!$this->_opened || $this->_reopen) {
+ $this->_opened = openlog($this->_ident, LOG_PID, $this->_name);
+ }
+
+ return $this->_opened;
+ }
+
+ /**
+ * Closes the connection to the system logger, if it is open.
+ * @access public
+ */
+ function close()
+ {
+ if ($this->_opened && !$this->_inherit) {
+ closelog();
+ $this->_opened = false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Sends $message to the currently open syslog connection. Calls
+ * open() if necessary. Also passes the message along to any Log_observer
+ * instances that are observing this Log.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param int $priority (optional) The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* If we need to (re)open the connection and open() fails, abort. */
+ if ((!$this->_opened || $this->_reopen) && !$this->open()) {
+ return false;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+
+ /* Build a syslog priority value based on our current configuration. */
+ $priority = $this->_toSyslog($priority);
+ if ($this->_inherit) {
+ $priority |= $this->_name;
+ }
+
+ /* Apply the configured line format to the message string. */
+ $message = $this->_format($this->_lineFormat,
+ strftime($this->_timeFormat),
+ $priority, $message);
+
+ /* Split the string into parts based on our maximum length setting. */
+ $parts = str_split($message, $this->_maxLength);
+ if ($parts === false) {
+ return false;
+ }
+
+ foreach ($parts as $part) {
+ if (!syslog($priority, $part)) {
+ return false;
+ }
+ }
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+
+ /**
+ * Converts a PEAR_LOG_* constant into a syslog LOG_* constant.
+ *
+ * This function exists because, under Windows, not all of the LOG_*
+ * constants have unique values. Instead, the PEAR_LOG_* were introduced
+ * for global use, with the conversion to the LOG_* constants kept local to
+ * to the syslog driver.
+ *
+ * @param int $priority PEAR_LOG_* value to convert to LOG_* value.
+ *
+ * @return The LOG_* representation of $priority.
+ *
+ * @access private
+ */
+ function _toSyslog($priority)
+ {
+ static $priorities = array(
+ PEAR_LOG_EMERG => LOG_EMERG,
+ PEAR_LOG_ALERT => LOG_ALERT,
+ PEAR_LOG_CRIT => LOG_CRIT,
+ PEAR_LOG_ERR => LOG_ERR,
+ PEAR_LOG_WARNING => LOG_WARNING,
+ PEAR_LOG_NOTICE => LOG_NOTICE,
+ PEAR_LOG_INFO => LOG_INFO,
+ PEAR_LOG_DEBUG => LOG_DEBUG
+ );
+
+ /* If we're passed an unknown priority, default to LOG_INFO. */
+ if (!is_int($priority) || !in_array($priority, $priorities)) {
+ return LOG_INFO;
+ }
+
+ return $priorities[$priority];
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * $Header$
+ *
+ * @version $Revision: 278003 $
+ * @package Log
+ */
+
+/**
+ * The Log_win class is a concrete implementation of the Log abstract
+ * class that logs messages to a separate browser window.
+ *
+ * The concept for this log handler is based on part by Craig Davis' article
+ * entitled "JavaScript Power PHP Debugging:
+ *
+ * http://www.zend.com/zend/tut/tutorial-DebugLib.php
+ *
+ * @author Jon Parise <jon@php.net>
+ * @since Log 1.7.0
+ * @package Log
+ *
+ * @example win.php Using the window handler.
+ */
+class Log_win extends Log
+{
+ /**
+ * The name of the output window.
+ * @var string
+ * @access private
+ */
+ var $_name = 'LogWindow';
+
+ /**
+ * The title of the output window.
+ * @var string
+ * @access private
+ */
+ var $_title = 'Log Output Window';
+
+ /**
+ * Mapping of log priorities to styles.
+ * @var array
+ * @access private
+ */
+ var $_styles = array(
+ PEAR_LOG_EMERG => 'color: red;',
+ PEAR_LOG_ALERT => 'color: orange;',
+ PEAR_LOG_CRIT => 'color: yellow;',
+ PEAR_LOG_ERR => 'color: green;',
+ PEAR_LOG_WARNING => 'color: blue;',
+ PEAR_LOG_NOTICE => 'color: indigo;',
+ PEAR_LOG_INFO => 'color: violet;',
+ PEAR_LOG_DEBUG => 'color: black;'
+ );
+
+ /**
+ * String buffer that holds line that are pending output.
+ * @var array
+ * @access private
+ */
+ var $_buffer = array();
+
+ /**
+ * Constructs a new Log_win object.
+ *
+ * @param string $name Ignored.
+ * @param string $ident The identity string.
+ * @param array $conf The configuration array.
+ * @param int $level Log messages up to and including this level.
+ * @access public
+ */
+ function Log_win($name, $ident = '', $conf = array(),
+ $level = PEAR_LOG_DEBUG)
+ {
+ $this->_id = md5(microtime());
+ $this->_name = str_replace(' ', '_', $name);
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+
+ if (isset($conf['title'])) {
+ $this->_title = $conf['title'];
+ }
+ if (isset($conf['styles']) && is_array($conf['styles'])) {
+ $this->_styles = $conf['styles'];
+ }
+ if (isset($conf['colors']) && is_array($conf['colors'])) {
+ foreach ($conf['colors'] as $level => $color) {
+ $this->_styles[$level] .= "color: $color;";
+ }
+ }
+
+ register_shutdown_function(array(&$this, '_Log_win'));
+ }
+
+ /**
+ * Destructor
+ */
+ function _Log_win()
+ {
+ if ($this->_opened || (count($this->_buffer) > 0)) {
+ $this->close();
+ }
+ }
+
+ /**
+ * The first time open() is called, it will open a new browser window and
+ * prepare it for output.
+ *
+ * This is implicitly called by log(), if necessary.
+ *
+ * @access public
+ */
+ function open()
+ {
+ if (!$this->_opened) {
+ $win = $this->_name;
+ $styles = $this->_styles;
+
+ if (!empty($this->_ident)) {
+ $identHeader = "$win.document.writeln('<th>Ident</th>')";
+ } else {
+ $identHeader = '';
+ }
+
+ echo <<< EOT
+<script language="JavaScript">
+$win = window.open('', '{$this->_name}', 'toolbar=no,scrollbars,width=600,height=400');
+$win.document.writeln('<html>');
+$win.document.writeln('<head>');
+$win.document.writeln('<title>{$this->_title}</title>');
+$win.document.writeln('<style type="text/css">');
+$win.document.writeln('body { font-family: monospace; font-size: 8pt; }');
+$win.document.writeln('td,th { font-size: 8pt; }');
+$win.document.writeln('td,th { border-bottom: #999999 solid 1px; }');
+$win.document.writeln('td,th { border-right: #999999 solid 1px; }');
+$win.document.writeln('tr { text-align: left; vertical-align: top; }');
+$win.document.writeln('td.l0 { $styles[0] }');
+$win.document.writeln('td.l1 { $styles[1] }');
+$win.document.writeln('td.l2 { $styles[2] }');
+$win.document.writeln('td.l3 { $styles[3] }');
+$win.document.writeln('td.l4 { $styles[4] }');
+$win.document.writeln('td.l5 { $styles[5] }');
+$win.document.writeln('td.l6 { $styles[6] }');
+$win.document.writeln('td.l7 { $styles[7] }');
+$win.document.writeln('</style>');
+$win.document.writeln('<script type="text/javascript">');
+$win.document.writeln('function scroll() {');
+$win.document.writeln(' body = document.getElementById("{$this->_name}");');
+$win.document.writeln(' body.scrollTop = body.scrollHeight;');
+$win.document.writeln('}');
+$win.document.writeln('<\/script>');
+$win.document.writeln('</head>');
+$win.document.writeln('<body id="{$this->_name}" onclick="scroll()">');
+$win.document.writeln('<table border="0" cellpadding="2" cellspacing="0">');
+$win.document.writeln('<tr><th>Time</th>');
+$identHeader
+$win.document.writeln('<th>Priority</th><th width="100%">Message</th></tr>');
+</script>
+EOT;
+ $this->_opened = true;
+ }
+
+ return $this->_opened;
+ }
+
+ /**
+ * Closes the output stream if it is open. If there are still pending
+ * lines in the output buffer, the output window will be opened so that
+ * the buffer can be drained.
+ *
+ * @access public
+ */
+ function close()
+ {
+ /*
+ * If there are still lines waiting to be written, open the output
+ * window so that we can drain the buffer.
+ */
+ if (!$this->_opened && (count($this->_buffer) > 0)) {
+ $this->open();
+ }
+
+ if ($this->_opened) {
+ $this->_writeln('</table>');
+ $this->_writeln('</body></html>');
+ $this->_drainBuffer();
+ $this->_opened = false;
+ }
+
+ return ($this->_opened === false);
+ }
+
+ /**
+ * Writes the contents of the output buffer to the output window.
+ *
+ * @access private
+ */
+ function _drainBuffer()
+ {
+ $win = $this->_name;
+ foreach ($this->_buffer as $line) {
+ echo "<script language='JavaScript'>\n";
+ echo "$win.document.writeln('" . addslashes($line) . "');\n";
+ echo "self.focus();\n";
+ echo "</script>\n";
+ }
+
+ /* Now that the buffer has been drained, clear it. */
+ $this->_buffer = array();
+ }
+
+ /**
+ * Writes a single line of text to the output buffer.
+ *
+ * @param string $line The line of text to write.
+ *
+ * @access private
+ */
+ function _writeln($line)
+ {
+ /* Add this line to our output buffer. */
+ $this->_buffer[] = $line;
+
+ /* Buffer the output until this page's headers have been sent. */
+ if (!headers_sent()) {
+ return;
+ }
+
+ /* If we haven't already opened the output window, do so now. */
+ if (!$this->_opened && !$this->open()) {
+ return;
+ }
+
+ /* Drain the buffer to the output window. */
+ $this->_drainBuffer();
+ }
+
+ /**
+ * Logs $message to the output window. The message is also passed along
+ * to any Log_observer instances that are observing this Log.
+ *
+ * @param mixed $message String or object containing the message to log.
+ * @param string $priority The priority of the message. Valid
+ * values are: PEAR_LOG_EMERG, PEAR_LOG_ALERT,
+ * PEAR_LOG_CRIT, PEAR_LOG_ERR, PEAR_LOG_WARNING,
+ * PEAR_LOG_NOTICE, PEAR_LOG_INFO, and PEAR_LOG_DEBUG.
+ * @return boolean True on success or false on failure.
+ * @access public
+ */
+ function log($message, $priority = null)
+ {
+ /* If a priority hasn't been specified, use the default value. */
+ if ($priority === null) {
+ $priority = $this->_priority;
+ }
+
+ /* Abort early if the priority is above the maximum logging level. */
+ if (!$this->_isMasked($priority)) {
+ return false;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+ $message = preg_replace('/\r\n|\n|\r/', '<br />', $message);
+
+ list($usec, $sec) = explode(' ', microtime());
+
+ /* Build the output line that contains the log entry row. */
+ $line = '<tr>';
+ $line .= sprintf('<td>%s.%s</td>',
+ strftime('%H:%M:%S', $sec), substr($usec, 2, 2));
+ if (!empty($this->_ident)) {
+ $line .= '<td>' . $this->_ident . '</td>';
+ }
+ $line .= '<td>' . ucfirst($this->priorityToString($priority)) . '</td>';
+ $line .= sprintf('<td class="l%d">%s</td>', $priority, $message);
+ $line .= '</tr>';
+
+ $this->_writeln($line);
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+
+}
--- /dev/null
+=================
+ The Log Package
+=================
+
+--------------------
+ User Documentation
+--------------------
+
+:Author: Jon Parise
+:Contact: jon@php.net
+:Date: $Date: 2011-02-15 21:13:19 -0800 (Tue, 15 Feb 2011) $
+:Revision: $Revision: 308379 $
+
+.. contents:: Contents
+.. section-numbering::
+
+Using Log Handlers
+==================
+
+The Log package is implemented as a framework that supports the notion of
+backend-specific log handlers. The base logging object (defined by the `Log
+class`_) is primarily an abstract interface to the currently configured
+handler.
+
+A wide variety of handlers are distributed with the Log package, and, should
+none of them fit your application's needs, it's easy to `write your own`__.
+
+.. _Log class: http://cvs.php.net/viewvc.cgi/pear/Log/Log.php
+__ `Custom Handlers`_
+
+Creating a Log Object
+---------------------
+There are three ways to create Log objects:
+
+ - Using the ``Log::factory()`` method
+ - Using the ``Log::singleton()`` method
+ - Direct instantiation
+
+The Factory Method
+~~~~~~~~~~~~~~~~~~
+The ``Log::factory()`` method implements the `Factory Pattern`_. It allows
+for the parameterized construction of concrete Log instances at runtime. The
+first parameter to the ``Log::factory()`` method indicates the name of the
+concrete handler to create. The rest of the parameters will be passed on to
+the handler's constructor (see `Configuring a Handler`_ below).
+
+The new ``Log`` instance is returned by reference.
+
+::
+
+ require_once 'Log.php';
+
+ $console = Log::factory('console', '', 'TEST');
+ $console->log('Logging to the console.');
+
+ $file = Log::factory('file', 'out.log', 'TEST');
+ $file->log('Logging to out.log.');
+
+.. _Factory Pattern: http://wikipedia.org/wiki/Factory_method_pattern
+
+The Singleton Method
+~~~~~~~~~~~~~~~~~~~~
+The ``Log::singleton()`` method implements the `Singleton Pattern`_. The
+singleton pattern ensures that only a single instance of a given log type and
+configuration is ever created. This has two benefits: first, it prevents
+duplicate ``Log`` instances from being constructed, and, second, it gives all
+of your code access to the same ``Log`` instance. The latter is especially
+important when logging to files because only a single file handler will need
+to be managed.
+
+The ``Log::singleton()`` method's parameters match the ``Log::factory()``
+method. The new ``Log`` instance is returned by reference.
+
+::
+
+ require_once 'Log.php';
+
+ /* Same construction parameters */
+ $a = Log::singleton('console', '', 'TEST');
+ $b = Log::singleton('console', '', 'TEST');
+
+ if ($a === $b) {
+ echo '$a and $b point to the same Log instance.' . "\n";
+ }
+
+ /* Different construction parameters */
+ $c = Log::singleton('console', '', 'TEST1');
+ $d = Log::singleton('console', '', 'TEST2');
+
+ if ($c !== $d) {
+ echo '$c and $d point to different Log instances.' . "\n";
+ }
+
+.. _Singleton Pattern: http://wikipedia.org/wiki/Singleton_pattern
+
+Direct Instantiation
+~~~~~~~~~~~~~~~~~~~~
+It is also possible to directly instantiate concrete ``Log`` handler
+instances. However, this method is **not recommended** because it creates a
+tighter coupling between your application code and the Log package than is
+necessary. Use of `the factory method`_ or `the singleton method`_ is
+preferred.
+
+
+Configuring a Handler
+---------------------
+A log handler's configuration is determined by the arguments used in its
+construction. Here's an overview of those parameters::
+
+ /* Using the factory method ... */
+ Log::factory($handler, $name, $ident, $conf, $maxLevel);
+
+ /* Using the singleton method ... */
+ Log::singleton($handler, $name, $ident, $conf, $maxLevel);
+
+ /* Using direct instantiation ... */
+ new Log_handler($name, $ident, $conf, $maxLevel);
+
++---------------+-----------+-----------------------------------------------+
+| Parameter | Type | Description |
++===============+===========+===============================================+
+| ``$handler`` | String | The type of Log handler to construct. This |
+| | | parameter is only available when `the factory |
+| | | method`_ or `the singleton method`_ are used. |
++---------------+-----------+-----------------------------------------------+
+| ``$name`` | String | The name of the log resource to which the |
+| | | events will be logged. The use of this value |
+| | | is determined by the handler's implementation.|
+| | | It defaults to an empty string. |
++---------------+-----------+-----------------------------------------------+
+| ``$ident`` | String | An identification string that will be included|
+| | | in all log events logged by this handler. |
+| | | This value defaults to an empty string and can|
+| | | be changed at runtime using the ``setIdent()``|
+| | | method. |
++---------------+-----------+-----------------------------------------------+
+| ``$conf`` | Array | Associative array of key-value pairs that are |
+| | | used to specify any handler-specific settings.|
++---------------+-----------+-----------------------------------------------+
+| ``$level`` | Integer | Log messages up to and including this level. |
+| | | This value defaults to ``PEAR_LOG_DEBUG``. |
+| | | See `Log Levels`_ and `Log Level Masks`_. |
++---------------+-----------+-----------------------------------------------+
+
+
+Logging an Event
+----------------
+Events are logged using the ``log()`` method::
+
+ $logger->log('Message', PEAR_LOG_NOTICE);
+
+The first argument contains the log event's message. Even though the event is
+always logged as a string, it is possible to pass an object to the ``log()``
+method. If the object implements a ``getString()`` method, a ``toString()``
+method or Zend Engine 2's special ``__toString()`` casting method, it will be
+used to determine the object's string representation. Otherwise, the
+`serialized`_ form of the object will be logged.
+
+The second, optional argument specifies the log event's priority. See the
+`Log Levels`_ table for the complete list of priorities. The default priority
+is PEAR_LOG_INFO.
+
+The ``log()`` method will return ``true`` if the event was successfully
+logged.
+
+"Shortcut" methods are also available for logging an event at a specific log
+level. See the `Log Levels`_ table for the complete list.
+
+.. _serialized: http://www.php.net/serialize
+
+
+Log Levels
+----------
+This table is ordered by highest priority (``PEAR_LOG_EMERG``) to lowest
+priority (``PEAR_LOG_DEBUG``).
+
++-----------------------+---------------+-----------------------------------+
+| Level | Shortcut | Description |
++=======================+===============+===================================+
+| ``PEAR_LOG_EMERG`` | ``emerg()`` | System is unusable |
++-----------------------+---------------+-----------------------------------+
+| ``PEAR_LOG_ALERT`` | ``alert()`` | Immediate action required |
++-----------------------+---------------+-----------------------------------+
+| ``PEAR_LOG_CRIT`` | ``crit()`` | Critical conditions |
++-----------------------+---------------+-----------------------------------+
+| ``PEAR_LOG_ERR`` | ``err()`` | Error conditions |
++-----------------------+---------------+-----------------------------------+
+| ``PEAR_LOG_WARNING`` | ``warning()`` | Warning conditions |
++-----------------------+---------------+-----------------------------------+
+| ``PEAR_LOG_NOTICE`` | ``notice()`` | Normal but significant |
++-----------------------+---------------+-----------------------------------+
+| ``PEAR_LOG_INFO`` | ``info()`` | Informational |
++-----------------------+---------------+-----------------------------------+
+| ``PEAR_LOG_DEBUG`` | ``debug()`` | Debug-level messages |
++-----------------------+---------------+-----------------------------------+
+
+
+Log Level Masks
+---------------
+Defining a log level mask allows you to include and/or exclude specific levels
+of events from being logged. The ``$level`` construction parameter (see
+`Configuring a Handler`_) uses this mechanism to exclude log events below a
+certain priority, and it's possible to define more complex masks once the Log
+object has been constructed.
+
+Each priority has a specific mask associated with it. To compute a priority's
+mask, use the static ``Log::MASK()`` method::
+
+ $mask = Log::MASK(PEAR_LOG_INFO);
+
+To compute the mask for all priorities up to, and including, a certain level,
+use the ``Log::MAX()`` static method::
+
+ $mask = Log::MAX(PEAR_LOG_INFO);
+
+To compute the mask for all priorities greater than or equal to a certain
+level, use the ``Log::MIN()`` static method::
+
+ $mask = Log::MIN(PEAR_LOG_INFO);
+
+The apply the mask, use the ``setMask()`` method::
+
+ $logger->setMask($mask);
+
+Masks can be be combined using bitwise operations. To restrict logging to
+only those events marked as ``PEAR_LOG_NOTICE`` or ``PEAR_LOG_DEBUG``::
+
+ $mask = Log::MASK(PEAR_LOG_NOTICE) | Log::MASK(PEAR_LOG_DEBUG);
+ $logger->setMask($mask);
+
+For convenience, two special masks are predefined: ``PEAR_LOG_NONE`` and
+``PEAR_LOG_ALL``. ``PEAR_LOG_ALL`` is especially useful for excluding only
+specific priorities::
+
+ $mask = PEAR_LOG_ALL ^ Log::MASK(PEAR_LOG_NOTICE);
+ $logger->setMask($mask);
+
+It is also possible to retrieve and modify a Log object's existing mask::
+
+ $mask = $logger->getMask() | Log::MASK(PEAR_LOG_INFO);
+ $logger->setMask($mask);
+
+
+Log Line Format
+---------------
+Most log handlers support configurable line formats. The following is a list
+of special tokens that will be expanded at runtime with contextual information
+related to the log event. Each token has an alternate shorthand notation, as
+well.
+
++------------------+-----------+--------------------------------------------+
+| Token | Alternate | Description |
++==================+===========+============================================+
+| ``%{timestamp}`` | ``%1$s`` | Timestamp. This is often configurable. |
++------------------+-----------+--------------------------------------------+
+| ``%{ident}`` | ``%2$s`` | The log handler's identification string. |
++------------------+-----------+--------------------------------------------+
+| ``%{priority}`` | ``%3$s`` | The log event's priority. |
++------------------+-----------+--------------------------------------------+
+| ``%{message}`` | ``%4$s`` | The log event's message text. |
++------------------+-----------+--------------------------------------------+
+| ``%{file}`` | ``%5$s`` | The full filename of the logging file. |
++------------------+-----------+--------------------------------------------+
+| ``%{line}`` | ``%6$s`` | The line number on which the event occured.|
++------------------+-----------+--------------------------------------------+
+| ``%{function}`` | ``%7$s`` | The function from which the event occurred.|
++------------------+-----------+--------------------------------------------+
+| ``%{class}`` | ``%8$s`` | The class in which the event occurred. |
++------------------+-----------+--------------------------------------------+
+
+
+Flushing Log Events
+-------------------
+Some log handlers (such as `the console handler`_) support explicit
+"buffering". When buffering is enabled, log events won't actually be written
+to the output stream until the handler is closed. Other handlers (such as
+`the file handler`_) support implicit buffering because they use the operating
+system's IO routines, which may buffer the output.
+
+It's possible to force these handlers to flush their output, however, by
+calling their ``flush()`` method::
+
+ $conf = array('buffering' => true);
+ $logger = Log::singleton('console', '', 'test', $conf);
+
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log('This event will be buffered.');
+ }
+
+ /* Flush all of the buffered log events. */
+ $logger->flush();
+
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log('This event will be buffered.');
+ }
+
+ /* Implicitly flush the buffered events on close. */
+ $logger->close();
+
+At this time, the ``flush()`` method is only implemented by `the console
+handler`_, `the file handler`_, `the Firebug handler`_, and `the mail
+handler`_.
+
+
+Standard Log Handlers
+=====================
+
+The Console Handler
+-------------------
+The Console handler outputs log events directly to the console. It supports
+output buffering and configurable string formats.
+
+Configuration
+~~~~~~~~~~~~~
++-------------------+-----------+---------------+---------------------------+
+| Parameter | Type | Default | Description |
++===================+===========+===============+===========================+
+| ``stream`` | File | STDOUT_ | The output stream to use. |
++-------------------+-----------+---------------+---------------------------+
+| ``buffering`` | Boolean | False | Should the output be |
+| | | | buffered until shutdown? |
++-------------------+-----------+---------------+---------------------------+
+| ``lineFormat`` | String | ``%1$s %2$s | `Log line format`_ |
+| | | [%3$s] %4$s`` | specification. |
++-------------------+-----------+---------------+---------------------------+
+| ``timeFormat`` | String | ``%b %d | Time stamp format |
+| | | %H:%M:%S`` | (for strftime_). |
++-------------------+-----------+---------------+---------------------------+
+
+.. _STDOUT: http://www.php.net/wrappers.php
+.. _strftime: http://www.php.net/strftime
+
+Example
+~~~~~~~
+::
+
+ $logger = Log::singleton('console', '', 'ident');
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+ }
+
+
+The Display Handler
+-------------------
+The Display handler simply prints the log events back to the browser. It
+respects the ``error_prepend_string`` and ``error_append_string`` `error
+handling values`_ and is useful when `logging from standard error handlers`_.
+
+Configuration
+~~~~~~~~~~~~~
++-------------------+-----------+---------------+---------------------------+
+| Parameter | Type | Default | Description |
++===================+===========+===============+===========================+
+| ``lineFormat`` | String | ``<b>%3$s</b>:| `Log line format`_ |
+| | | %4$s`` | specification. |
++-------------------+-----------+---------------+---------------------------+
+| ``timeFormat`` | String | ``%b %d | Time stamp format |
+| | | %H:%M:%S`` | (for strftime_). |
++-------------------+-----------+---------------+---------------------------+
+| ``error_prepend`` | String | PHP INI value | This string will be |
+| | | | prepended to the line |
+| | | | format. |
++-------------------+-----------+---------------+---------------------------+
+| ``error_append`` | String | PHP INI value | This string will be |
+| | | | appended to the line |
+| | | | format. |
++-------------------+-----------+---------------+---------------------------+
+| ``linebreak`` | String | ``<br />\n`` | This string is used to |
+| | | | represent a line break. |
++-------------------+-----------+---------------+---------------------------+
+| ``rawText`` | Boolean | False | Should message text be |
+| | | | passed directly to the log|
+| | | | system? Otherwise, it |
+| | | | will be converted to an |
+| | | | HTML-safe representation. |
++-------------------+-----------+---------------+---------------------------+
+
+.. _error handling values: http://www.php.net/errorfunc
+
+Example
+~~~~~~~
+::
+
+ $conf = array('error_prepend' => '<font color="#ff0000"><tt>',
+ 'error_append' => '</tt></font>');
+ $logger = Log::singleton('display', '', '', $conf, PEAR_LOG_DEBUG);
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+ }
+
+
+The Error_Log Handler
+---------------------
+The Error_Log handler sends log events to PHP's `error_log()`_ function.
+
+Configuration
+~~~~~~~~~~~~~
++-------------------+-----------+---------------+---------------------------+
+| Parameter | Type | Default | Description |
++===================+===========+===============+===========================+
+| ``destination`` | String | '' `(empty)` | Optional destination value|
+| | | | for `error_log()`_. See |
+| | | | `Error_Log Types`_ for |
+| | | | more details. |
++-------------------+-----------+---------------+---------------------------+
+| ``extra_headers`` | String | '' `(empty)` | Additional headers to pass|
+| | | | to the `mail()`_ function |
+| | | | when the |
+| | | | ``PEAR_LOG_TYPE_MAIL`` |
+| | | | type is specified. |
++-------------------+-----------+---------------+---------------------------+
+| ``lineFormat`` | String | ``%2$s: %4$s``| `Log line format`_ |
+| | | | specification. |
++-------------------+-----------+---------------+---------------------------+
+| ``timeFormat`` | String | ``%b %d | Time stamp format |
+| | | %H:%M:%S`` | (for strftime_). |
++-------------------+-----------+---------------+---------------------------+
+
+Error_Log Types
+~~~~~~~~~~~~~~~
+All of the available log types are detailed in the `error_log()`_ section of
+the PHP manual. For your convenience, the Log package also defines the
+following constants that can be used for the ``$name`` handler construction
+parameter.
+
++---------------------------+-----------------------------------------------+
+| Constant | Description |
++===========================+===============================================+
+| ``PEAR_LOG_TYPE_SYSTEM`` | Log events are sent to PHP's system logger, |
+| | which uses the operating system's logging |
+| | mechanism or a file (depending on the value |
+| | of the `error_log configuration directive`_). |
++---------------------------+-----------------------------------------------+
+| ``PEAR_LOG_TYPE_MAIL`` | Log events are sent via email to the address |
+| | specified in the ``destination`` value. |
++---------------------------+-----------------------------------------------+
+| ``PEAR_LOG_TYPE_DEBUG`` | Log events are sent through PHP's debugging |
+| | connection. This will only work if |
+| | `remote debugging`_ has been enabled. The |
+| | ``destination`` value is used to specify the |
+| | host name or IP address of the target socket. |
++---------------------------+-----------------------------------------------+
+| ``PEAR_LOG_TYPE_FILE`` | Log events will be appended to the file named |
+| | by the ``destination`` value. |
++---------------------------+-----------------------------------------------+
+| ``PEAR_LOG_TYPE_SAPI`` | Log events will be sent directly to the SAPI |
+| | logging handler. |
++---------------------------+-----------------------------------------------+
+
+.. _error_log(): http://www.php.net/error_log
+.. _mail(): http://www.php.net/mail
+.. _error_log configuration directive: http://www.php.net/errorfunc#ini.error-log
+.. _remote debugging: http://www.php.net/install.configure#install.configure.enable-debugger
+
+Example
+~~~~~~~
+::
+
+ $logger = Log::singleton('error_log', PEAR_LOG_TYPE_SYSTEM, 'ident');
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+ }
+
+
+The File Handler
+----------------
+The File handler writes log events to a text file using configurable string
+formats.
+
+Configuration
+~~~~~~~~~~~~~
++-------------------+-----------+---------------+---------------------------+
+| Parameter | Type | Default | Description |
++===================+===========+===============+===========================+
+| ``append`` | Boolean | True | Should new log entries be |
+| | | | append to an existing log |
+| | | | file, or should the a new |
+| | | | log file overwrite an |
+| | | | existing one? |
++-------------------+-----------+---------------+---------------------------+
+| ``locking`` | Boolean | False | Should advisory file |
+| | | | locking (using flock_) be |
+| | | | used? |
++-------------------+-----------+---------------+---------------------------+
+| ``mode`` | Integer | 0644 | Octal representation of |
+| | | | the log file's permissions|
+| | | | mode. |
++-------------------+-----------+---------------+---------------------------+
+| ``dirmode`` | Integer | 0755 | Octal representation of |
+| | | | the file permission mode |
+| | | | that will be used when |
+| | | | creating directories that |
+| | | | do not already exist. |
++-------------------+-----------+---------------+---------------------------+
+| ``eol`` | String | OS default | The end-of-line character |
+| | | | sequence. |
++-------------------+-----------+---------------+---------------------------+
+| ``lineFormat`` | String | ``%1$s %2$s | `Log line format`_ |
+| | | [%3$s] %4$s`` | specification. |
++-------------------+-----------+---------------+---------------------------+
+| ``timeFormat`` | String | ``%b %d | Time stamp format |
+| | | %H:%M:%S`` | (for strftime_). |
++-------------------+-----------+---------------+---------------------------+
+
+.. _flock: http://www.php.net/flock
+.. _strftime: http://www.php.net/strftime
+
+The file handler will only attempt to set the ``mode`` value if it was
+responsible for creating the file.
+
+Example
+~~~~~~~
+::
+
+ $conf = array('mode' => 0600, 'timeFormat' => '%X %x');
+ $logger = Log::singleton('file', 'out.log', 'ident', $conf);
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+ }
+
+
+The Firebug Handler
+-------------------
+The Firebug handler outputs log events to the Firebug_ console. It supports
+output buffering and configurable string formats.
+
+Configuration
+~~~~~~~~~~~~~
++-------------------+-----------+---------------+---------------------------+
+| Parameter | Type | Default | Description |
++===================+===========+===============+===========================+
+| ``buffering`` | Boolean | False | Should the output be |
+| | | | buffered until shutdown? |
++-------------------+-----------+---------------+---------------------------+
+| ``lineFormat`` | String | ``%2$s [%3$s] | `Log line format`_ |
+| | | %4$s`` | specification. |
++-------------------+-----------+---------------+---------------------------+
+| ``timeFormat`` | String | ``%b %d | Time stamp format |
+| | | %H:%M:%S`` | (for strftime_). |
++-------------------+-----------+---------------+---------------------------+
+
+.. _Firebug: http://www.getfirebug.com/
+.. _strftime: http://www.php.net/strftime
+
+Example
+~~~~~~~
+::
+
+ $logger = Log::singleton('firebug', '', 'ident');
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+ }
+
+
+The Mail Handler
+----------------
+
+The Mail handler aggregates a session's log events and sends them in the body
+of an email message using either the `PEAR Mail`_ package or PHP's native
+`mail()`_ function.
+
+If an empty ``mailBackend`` value is specified, the `mail()`_ function will be
+used instead of the `PEAR Mail`_ package.
+
+Multiple recipients can be specified by separating their email addresses with
+commas in the ``$name`` construction parameter.
+
+Configuration
+~~~~~~~~~~~~~
++-------------------+-----------+---------------+---------------------------+
+| Parameter | Type | Default | Description |
++===================+===========+===============+===========================+
+| ``from`` | String | sendmail_from | Value for the message's |
+| | | INI value | ``From:`` header. |
++-------------------+-----------+---------------+---------------------------+
+| ``subject`` | String | ``[Log_mail] | Value for the message's |
+| | | Log message`` | ``Subject:`` header. |
++-------------------+-----------+---------------+---------------------------+
+| ``preamble`` | String | `` `(empty)` | Preamble for the message. |
++-------------------+-----------+---------------+---------------------------+
+| ``lineFormat`` | String | ``%1$s %2$s | `Log line format`_ |
+| | | [%3$s] %4$s`` | specification. |
++-------------------+-----------+---------------+---------------------------+
+| ``timeFormat`` | String | ``%b %d | Time stamp format |
+| | | %H:%M:%S`` | (for strftime_). |
++-------------------+-----------+---------------+---------------------------+
+| ``mailBackend`` | String | `` `(empty)` | Name of the Mail package |
+| | | | backend to use. |
++-------------------+-----------+---------------+---------------------------+
+| ``mailParams`` | Array | `(empty)` | Array of parameters that |
+| | | | will be passed to the |
+| | | | Mail package backend. |
++-------------------+-----------+---------------+---------------------------+
+
+.. _PEAR Mail: http://pear.php.net/package/Mail
+.. _mail(): http://www.php.net/mail
+
+Example
+~~~~~~~
+::
+
+ $conf = array('subject' => 'Important Log Events');
+ $logger = Log::singleton('mail', 'webmaster@example.com', 'ident', $conf);
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+ }
+
+
+The MDB2 Handler
+----------------
+The MDB2 handler is similar to `the SQL (DB) handler`_, but instead of using
+the PEAR DB package, it uses the `MDB2 database abstraction package`_.
+
+Configuration
+~~~~~~~~~~~~~
++-------------------+-----------+---------------+---------------------------+
+| Parameter | Type | Default | Description |
++===================+===========+===============+===========================+
+| ``dsn`` | Mixed | '' `(empty)` | A `Data Source Name`_. |
+| | | | |required| |
++-------------------+-----------+---------------+---------------------------+
+| ``options`` | Array | ``persistent``| An array of `MDB2`_ |
+| | | | options. |
++-------------------+-----------+---------------+---------------------------+
+| ``db`` | Object | NULL | An existing `MDB2`_ |
+| | | | object. If specified, |
+| | | | this object will be used, |
+| | | | and ``dsn`` will be |
+| | | | ignored. |
++-------------------+-----------+---------------+---------------------------+
+| ``sequence`` | String | ``log_id`` | The name of the sequence |
+| | | | to use when generating |
+| | | | unique event IDs. Under |
+| | | | many databases, this will |
+| | | | be used as the name of |
+| | | | the sequence table. |
++-------------------+-----------+---------------+---------------------------+
+| ``identLimit`` | Integer | 16 | The maximum length of the |
+| | | | ``ident`` string. |
+| | | | **Changing this value may |
+| | | | require updates to the SQL|
+| | | | schema, as well.** |
++-------------------+-----------+---------------+---------------------------+
+| ``singleton`` | Boolean | false | Is true, use a singleton |
+| | | | database object using |
+| | | | `MDB2::singleton()`_. |
++-------------------+-----------+---------------+---------------------------+
+
+.. _MDB2: http://pear.php.net/package/MDB2
+.. _MDB2 database abstraction package: MDB2_
+.. _MDB2::singleton(): http://pear.php.net/package/MDB2/docs/latest/MDB2/MDB2.html#methodsingleton
+
+The Null Handler
+----------------
+The Null handler simply consumes log events (akin to sending them to
+``/dev/null``). `Log level masks`_ are respected, and the event will still be
+sent to any registered `log observers`_.
+
+Example
+~~~~~~~
+::
+
+ $logger = Log::singleton('null');
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+ }
+
+
+The SQL (DB) Handler
+--------------------
+
+The SQL handler sends log events to a database using `PEAR's DB abstraction
+layer`_.
+
+**Note:** Due to the constraints of the default database schema, the SQL
+handler limits the length of the ``$ident`` string to sixteen (16) characters.
+This limit can be adjusted using the ``identLimit`` configuration parameter.
+
+The Log Table
+~~~~~~~~~~~~~
+The default SQL table used by this handler looks like this::
+
+ CREATE TABLE log_table (
+ id INT NOT NULL,
+ logtime TIMESTAMP NOT NULL,
+ ident CHAR(16) NOT NULL,
+ priority INT NOT NULL,
+ message VARCHAR(200),
+ PRIMARY KEY (id)
+ );
+
+This is the "lowest common denominator" that should work across all SQL
+compliant database. You may want to make database- or site-specific changes
+to this schema to support your specific needs, however. For example,
+`PostgreSQL`_ users may prefer to use a ``TEXT`` type for the ``message``
+field.
+
+.. _PostgreSQL: http://www.postgresql.org/
+
+Configuration
+~~~~~~~~~~~~~
++-------------------+-----------+---------------+---------------------------+
+| Parameter | Type | Default | Description |
++===================+===========+===============+===========================+
+| ``dsn`` | Mixed | '' `(empty)` | A `Data Source Name`_. |
+| | | | |required| |
++-------------------+-----------+---------------+---------------------------+
+| ``sql`` | String | |sql-default| | SQL insertion statement. |
++-------------------+-----------+---------------+---------------------------+
+| ``options`` | Array | ``persistent``| An array of `DB`_ options.|
++-------------------+-----------+---------------+---------------------------+
+| ``db`` | Object | NULL | An existing `DB`_ object. |
+| | | | If specified, this object |
+| | | | will be used, and ``dsn`` |
+| | | | will be ignored. |
++-------------------+-----------+---------------+---------------------------+
+| ``sequence`` | String | ``log_id`` | The name of the sequence |
+| | | | to use when generating |
+| | | | unique event IDs. Under |
+| | | | many databases, this will |
+| | | | be used as the name of |
+| | | | the sequence table. |
++-------------------+-----------+---------------+---------------------------+
+| ``identLimit`` | Integer | 16 | The maximum length of the |
+| | | | ``ident`` string. |
+| | | | **Changing this value may |
+| | | | require updates to the SQL|
+| | | | schema, as well.** |
++-------------------+-----------+---------------+---------------------------+
+
+The name of the database table to which the log entries will be written is
+specified using the ``$name`` construction parameter (see `Configuring a
+Handler`_).
+
+.. |sql-default| replace:: ``INSERT INTO $table (id, logtime, ident, priority, message) VALUES(?, CURRENT_TIMESTAMP, ?, ?, ?)``
+
+.. _DB: http://pear.php.net/package/DB
+.. _PEAR's DB abstraction layer: DB_
+.. _Data Source Name: http://pear.php.net/manual/en/package.database.db.intro-dsn.php
+
+Examples
+~~~~~~~~
+Using a `Data Source Name`_ to create a new database connection::
+
+ $conf = array('dsn' => 'pgsql://jon@localhost+unix/logs');
+ $logger = Log::singleton('sql', 'log_table', 'ident', $conf);
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+ }
+
+Using an existing `DB`_ object::
+
+ require_once 'DB.php';
+ $db = &DB::connect('pgsql://jon@localhost+unix/logs');
+
+ $conf['db'] = $db;
+ $logger = Log::singleton('sql', 'log_table', 'ident', $conf);
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+ }
+
+
+The Sqlite Handler
+------------------
+:Author: Bertrand Mansion
+
+The Sqlite handler sends log events to an Sqlite database using the `native
+PHP sqlite functions`_.
+
+It is faster than `the SQL (DB) handler`_ because requests are made directly
+to the database without using an abstraction layer. It is also interesting to
+note that Sqlite database files can be moved, copied, and deleted on your
+system just like any other files, which makes log management easier. Last but
+not least, using a database to log your events allows you to use SQL queries
+to create reports and statistics.
+
+When using a database and logging a lot of events, it is recommended to split
+the database into smaller databases. This is allowed by Sqlite, and you can
+later use the Sqlite `ATTACH`_ statement to query your log database files
+globally.
+
+If the database does not exist when the log is opened, sqlite will try to
+create it automatically. If the log table does not exist, it will also be
+automatically created. The table creation uses the following SQL request::
+
+ CREATE TABLE log_table (
+ id INTEGER PRIMARY KEY NOT NULL,
+ logtime NOT NULL,
+ ident CHAR(16) NOT NULL,
+ priority INT NOT NULL,
+ message
+ );
+
+Configuration
+~~~~~~~~~~~~~
++-------------------+-----------+---------------+---------------------------+
+| Parameter | Type | Default | Description |
++===================+===========+===============+===========================+
+| ``filename`` | String | '' `(empty)` | Path to an Sqlite |
+| | | | database. |required| |
++-------------------+-----------+---------------+---------------------------+
+| ``mode`` | Integer | 0666 | Octal mode used to open |
+| | | | the database. |
++-------------------+-----------+---------------+---------------------------+
+| ``persistent`` | Boolean | false | Use a persistent |
+| | | | connection. |
++-------------------+-----------+---------------+---------------------------+
+
+An already opened database connection can also be passed as parameter instead
+of the above configuration. In this case, closing the database connection is
+up to the user.
+
+.. _native PHP sqlite functions: http://www.php.net/sqlite
+.. _ATTACH: http://www.sqlite.org/lang.html#attach
+
+Examples
+~~~~~~~~
+Using a configuration to create a new database connection::
+
+ $conf = array('filename' => 'log.db', 'mode' => 0666, 'persistent' => true);
+ $logger = Log::factory('sqlite', 'log_table', 'ident', $conf);
+ $logger->log('logging an event', PEAR_LOG_WARNING);
+
+Using an existing connection::
+
+ $db = sqlite_open('log.db', 0666, $error);
+ $logger = Log::factory('sqlite', 'log_table', 'ident', $db);
+ $logger->log('logging an event', PEAR_LOG_WARNING);
+ sqlite_close($db);
+
+
+The Syslog Handler
+------------------
+The Syslog handler sends log events to the system logging service (syslog on
+Unix-like environments or the Event Log on Windows systems). The events are
+sent using PHP's `syslog()`_ function.
+
+Configuration
+~~~~~~~~~~~~~
++-------------------+-----------+---------------+---------------------------+
+| Parameter | Type | Default | Description |
++===================+===========+===============+===========================+
+| ``inherit`` | Boolean | false | Inherit the current syslog|
+| | | | connection for this |
+| | | | process, or start a new |
+| | | | one via `openlog()`_? |
++-------------------+-----------+---------------+---------------------------+
+| ``reopen`` | Boolean | false | Reopen the syslog |
+| | | | connection for each log |
+| | | | event? |
++-------------------+-----------+---------------+---------------------------+
+| ``maxLength`` | Integer | 500 | Maximum message length |
+| | | | that will be sent to the |
+| | | | `syslog()`_ function. |
+| | | | Longer messages will be |
+| | | | split across multiple |
+| | | | `syslog()`_ calls. |
++-------------------+-----------+---------------+---------------------------+
+| ``lineFormat`` | String | ``%4$s`` | `Log line format`_ |
+| | | | specification. |
++-------------------+-----------+---------------+---------------------------+
+| ``timeFormat`` | String | ``%b %d | Time stamp format |
+| | | %H:%M:%S`` | (for strftime_). |
++-------------------+-----------+---------------+---------------------------+
+
+Facilities
+~~~~~~~~~~
++-------------------+-------------------------------------------------------+
+| Constant | Category Description |
++===================+=======================================================+
+| ``LOG_AUTH`` | Security / authorization messages; ``LOG_AUTHPRIV`` is|
+| | preferred on systems where it is defined. |
++-------------------+-------------------------------------------------------+
+| ``LOG_AUTHPRIV`` | Private security / authorization messages |
++-------------------+-------------------------------------------------------+
+| ``LOG_CRON`` | Clock daemon (``cron`` and ``at``) |
++-------------------+-------------------------------------------------------+
+| ``LOG_DAEMON`` | System daemon processes |
++-------------------+-------------------------------------------------------+
+| ``LOG_KERN`` | Kernel messages |
++-------------------+-------------------------------------------------------+
+| ``LOG_LOCAL0`` .. | Reserved for local use; **not** available under |
+| ``LOG_LOCAL7`` | Windows. |
++-------------------+-------------------------------------------------------+
+| ``LOG_LPR`` | Printer subsystem |
++-------------------+-------------------------------------------------------+
+| ``LOG_MAIL`` | Mail subsystem |
++-------------------+-------------------------------------------------------+
+| ``LOG_NEWS`` | USENET news subsystem |
++-------------------+-------------------------------------------------------+
+| ``LOG_SYSLOG`` | Internal syslog messages |
++-------------------+-------------------------------------------------------+
+| ``LOG_USER`` | Generic user-level messages |
++-------------------+-------------------------------------------------------+
+| ``LOG_UUCP`` | UUCP subsystem |
++-------------------+-------------------------------------------------------+
+
+.. _syslog(): http://www.php.net/syslog
+.. _openlog(): http://www.php.net/openlog
+
+Example
+~~~~~~~
+::
+
+ $logger = Log::singleton('syslog', LOG_LOCAL0, 'ident');
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+ }
+
+
+The Window Handler
+------------------
+The Window handler sends log events to a separate browser window. The
+original idea for this handler was inspired by Craig Davis' Zend.com article
+entitled `"JavaScript Power PHP Debugging"`_.
+
+Configuration
+~~~~~~~~~~~~~
++-------------------+-----------+---------------+---------------------------+
+| Parameter | Type | Default | Description |
++===================+===========+===============+===========================+
+| ``title`` | String | ``Log Output | The title of the output |
+| | | Window`` | window. |
++-------------------+-----------+---------------+---------------------------+
+| ``styles`` | Array | `ROY G BIV`_ | Mapping of log priorities |
+| | | (high to low) | to CSS styles. |
++-------------------+-----------+---------------+---------------------------+
+
+**Note:** The Window handler may not work reliably when PHP's `output
+buffering`_ system is enabled.
+
+.. _"JavaScript Power PHP Debugging": http://www.zend.com/zend/tut/tutorial-DebugLib.php
+.. _ROY G BIV: http://www.cis.rit.edu/
+.. _output buffering: http://www.php.net/outcontrol
+
+Example
+~~~~~~~
+::
+
+ $conf = array('title' => 'Sample Log Output');
+ $logger = Log::singleton('win', 'LogWindow', 'ident', $conf);
+ for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+ }
+
+
+Composite Handlers
+==================
+It is often useful to log events to multiple handlers. The Log package
+provides a compositing system that marks this task trivial.
+
+Start by creating the individual log handlers::
+
+ $console = Log::singleton('console', '', 'TEST');
+ $file = Log::singleton('file', 'out.log', 'TEST');
+
+Then, construct a composite handler and add the individual handlers as
+children of the composite::
+
+ $composite = Log::singleton('composite');
+ $composite->addChild($console);
+ $composite->addChild($file);
+
+The composite handler implements the standard ``Log`` interface so you can use
+it just like any of the other handlers::
+
+ $composite->log('This event will be logged to both handlers.');
+
+Children can be removed from the composite when they're not longer needed::
+
+ $composite->removeChild($file);
+
+
+Log Observers
+=============
+Log observers provide an implementation of the `observer pattern`_. In the
+content of the Log package, they provide a mechanism by which you can examine
+(i.e. observe) each event as it is logged. This allows the implementation of
+special behavior based on the contents of a log event. For example, the
+observer code could send an alert email if a log event contained the string
+``PANIC``.
+
+Creating a log observer involves implementing a subclass of the
+``Log_observer`` class. The subclass must override the base class's
+``notify()`` method. This method is passed a hash containing the event's
+priority and event. The subclass's implementation is free to act upon this
+information in any way it likes.
+
+Log observers are attached to ``Log`` instances via the ``attach()`` method::
+
+ $observer = Log_observer::factory('yourType');
+ $logger->attach($observer);
+
+Observers can be detached using the ``detach()`` method::
+
+ $logger->detach($observer);
+
+At this time, no concrete ``Log_observer`` implementations are distributed
+with the Log package.
+
+.. _observer pattern: http://wikipedia.org/wiki/Observer_pattern
+
+
+Logging From Standard Error Handlers
+====================================
+
+Logging PHP Errors
+------------------
+PHP's default error handler can be overridden using the `set_error_handler()`_
+function. The custom error handling function can use a global Log instance to
+log the PHP errors.
+
+**Note:** Fatal PHP errors cannot be handled by a custom error handler at this
+time.
+
+::
+
+ function errorHandler($code, $message, $file, $line)
+ {
+ global $logger;
+
+ /* Map the PHP error to a Log priority. */
+ switch ($code) {
+ case E_WARNING:
+ case E_USER_WARNING:
+ $priority = PEAR_LOG_WARNING;
+ break;
+ case E_NOTICE:
+ case E_USER_NOTICE:
+ $priority = PEAR_LOG_NOTICE;
+ break;
+ case E_ERROR:
+ case E_USER_ERROR:
+ $priority = PEAR_LOG_ERR;
+ break;
+ default:
+ $priority = PEAR_LOG_INFO;
+ }
+
+ $logger->log($message . ' in ' . $file . ' at line ' . $line,
+ $priority);
+ }
+
+ set_error_handler('errorHandler');
+ trigger_error('This is an information log message.', E_USER_NOTICE);
+
+.. _set_error_handler(): http://www.php.net/set_error_handler
+
+Logging PHP Assertions
+----------------------
+PHP allows user-defined `assert()`_ callback handlers. The assertion callback
+is configured using the `assert_options()`_ function.
+
+::
+
+ function assertCallback($file, $line, $message)
+ {
+ global $logger;
+
+ $logger->log($message . ' in ' . $file . ' at line ' . $line,
+ PEAR_LOG_ALERT);
+ }
+
+ assert_options(ASSERT_CALLBACK, 'assertCallback');
+ assert(false);
+
+.. _assert(): http://www.php.net/assert
+.. _assert_options(): http://www.php.net/assert_options
+
+Logging PHP Exceptions
+----------------------
+PHP 5 and later support the concept of `exceptions`_. A custom exception
+handler can be assigned using the `set_exception_handler()`_ function.
+
+::
+
+ function exceptionHandler($exception)
+ {
+ global $logger;
+
+ $logger->log($exception->getMessage(), PEAR_LOG_ALERT);
+ }
+
+ set_exception_handler('exceptionHandler');
+ throw new Exception('Uncaught Exception');
+
+.. _exceptions: http://www.php.net/exceptions
+.. _set_exception_handler(): http://www.php.net/set_exception_handler
+
+Logging PEAR Errors
+-------------------
+The Log package can be used with `PEAR::setErrorHandling()`_'s
+``PEAR_ERROR_CALLBACK`` mechanism by writing an error handling function that
+uses a global Log instance. Here's an example::
+
+ function errorHandler($error)
+ {
+ global $logger;
+
+ $message = $error->getMessage();
+
+ if (!empty($error->backtrace[1]['file'])) {
+ $message .= ' (' . $error->backtrace[1]['file'];
+ if (!empty($error->backtrace[1]['line'])) {
+ $message .= ' at line ' . $error->backtrace[1]['line'];
+ }
+ $message .= ')';
+ }
+
+ $logger->log($message, $error->code);
+ }
+
+ PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'errorHandler');
+ PEAR::raiseError('This is an information log message.', PEAR_LOG_INFO);
+
+.. _PEAR::setErrorHandling(): http://pear.php.net/manual/en/core.pear.pear.seterrorhandling.php
+
+
+Custom Handlers
+===============
+There are times when the standard handlers aren't a perfect match for your
+needs. In those situations, the solution might be to write a custom handler.
+
+Using a Custom Handler
+----------------------
+Using a custom Log handler is very simple. Once written (see `Writing New
+Handlers`_ and `Extending Existing Handlers`_ below), you have the choice of
+placing the file in your PEAR installation's main ``Log/`` directory (usually
+something like ``/usr/local/lib/php/Log`` or ``C:\php\pear\Log``), where it
+can be found and use by any PHP application on the system, or placing the file
+somewhere in your application's local hierarchy and including it before the
+the custom Log object is constructed.
+
+Method 1: Handler in the Standard Location
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+After copying the handler file to your PEAR installation's ``Log/`` directory,
+simply treat the handler as if it were part of the standard distributed. If
+your handler is named ``custom`` (and therefore implemented by a class named
+``Log_custom``)::
+
+ require_once 'Log.php';
+
+ $logger = Log::factory('custom', '', 'CUSTOM');
+
+
+Method 2: Handler in a Custom Location
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If you prefer storing your handler in your application's local hierarchy,
+you'll need to include that file before you can create a Log instance based on
+it.
+
+::
+
+ require_once 'Log.php';
+ require_once 'LocalHandlers/custom.php';
+
+ $logger = Log::factory('custom', '', 'CUSTOM');
+
+
+Writing New Handlers
+--------------------
+Writing a new Log handler is as simple as authoring a new class that extends
+the ``Log`` class and that implements a relatively small set of standard
+methods.
+
+Every handler's class name must start with ``Log_`` in order for it to be
+recognized by the Log package.
+
+::
+
+ class Log_custom extends Log
+
+The handler's constructor will be called with four parameters. These values
+are discussed in detail in the `Configuring a Handler`_ section.
+
+::
+
+ Log_custom($name, $ident = '', $conf = array(), $level = PEAR_LOG_DEBUG)
+
+The constructor is responsible for configuring the handler based on these
+values. Handler-specific parameters are passed as part of the ``$conf``
+array. At a minimum, the handler's constructor must set the following values
+defined by the ``Log`` base class::
+
+ $this->_id = md5(microtime());
+ $this->_name = $name;
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+
+The `Handler Methods`_ section below details the various standard methods that
+can be implemented by a log handler. The `Utility Methods`_ section describes
+some useful utility methods provided by the ``Log`` base class which may be
+useful when implementing a log handler.
+
+
+Extending Existing Handlers
+---------------------------
+Extending existing handlers is very similar to `writing new handlers`_ with
+the exception that, instead of inheriting from the ``Log`` base class
+directly, the handler extends an existing handler's class. This is a useful
+way of adding some custom behavior to an existing handler without writing an
+entirely new class (in the spirit of object-oriented programming).
+
+For example, `the mail handler`_ could be extended to support sending messages
+with MIME-encoded attachments simply by authoring a new ``Log_mail_mime``
+class with a compliant constructor and a custom ``log()`` method. The rest of
+the standard methods would fall back on the ``Log_mail`` base class's
+implementations.
+
+Obviously, the specific details involved in extending an existing handler
+require a good working understanding of that handler's implementation.
+
+
+Handler Methods
+---------------
+
+bool open()
+~~~~~~~~~~~
+The ``open()`` method is called to open the log resource for output. Handlers
+can call ``open()`` immediately upon construction or lazily at runtime
+(perhaps when the first log event is received).
+
+The ``Log`` base class provides a protected ``$_opened`` member variable which
+should be set to ``true`` when the log handler is opened and ``false`` when it
+is closed. Handler methods can inspect this value to determine whether or not
+the handler is currently open and ready for output.
+
+If the ``open()`` method fails to ready the handler for output, it should
+return ``false`` and set ``$this->_opened`` to ``false``.
+
+bool close()
+~~~~~~~~~~~~
+The ``close()`` method is called to close the log resource. This method is
+the analog of the ``open()`` method. It should be safe to call ``close()``
+even when the handler is not open for output.
+
+If the ``close()`` method fails to close the handler, it should return
+``false``. Otherwise, it should return ``true``. The ``$this->_opened``
+flag should also be updated appropriately.
+
+bool flush()
+~~~~~~~~~~~~
+The ``flush()`` method flushes any buffered log events, as described in
+`Flushing Log Events`_. The implementation of this method will be largely
+handler-specific. If the handler does not support buffered output,
+implementing this method is not necessary; the ``Log`` class's ``flush()``
+method will be called instead.
+
+bool log($message, $priority = null)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The ``log()`` method is the core of every log handler. It is called whenever
+the user wishes to log an event. The implementation of this method is very
+handler-specific. It should return ``true`` or ``false``, depending on
+whether or not the message was successfully logged by the handler.
+
+The ``log()`` implementation should be sure to call `_announce()`__ whenever
+an event is successfully logged.
+
+.. __: `void _announce($event)`_
+
+Utility Methods
+---------------
+These utility methods are provided by the ``Log`` base class and provide
+common, useful functionality to handler implementations.
+
+string _extractMessage($message)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This method returns the string representation of the provided message data.
+
+If ``$message`` is an object, ``_extractMessage()`` will attempt to extract
+the message text using a known method (such as a `PEAR_Error`_ object's
+`getMessage()`_ method). If a known method, cannot be found, the serialized
+representation of the object will be returned.
+
+If the message data is already a string, it will be returned unchanged.
+
+.. _PEAR_Error: http://pear.php.net/manual/en/core.pear.pear-error.php
+.. _getMessage(): http://pear.php.net/manual/en/core.pear.pear-error.getmessage.php
+
+string _format($format, $timestamp, $priority, $message)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This method produces a formatted log line based on a format string and a set
+of `tokens`_ representing the current log record and state.
+
+.. _tokens: `Log Line Format`_
+
+bool _isMasked($priority)
+~~~~~~~~~~~~~~~~~~~~~~~~~
+This method checks if the given priority is included in the handler's current
+level mask. This is useful for determining whether or not a log event should
+be written to the handler's log.
+
+void _announce($event)
+~~~~~~~~~~~~~~~~~~~~~~
+This method informs any registered `log observers`_ that a new event has been
+logged. ``$event`` is an array containing two named elements::
+
+ array('priority' => $priority, 'message' => $message)
+
+``_announce()`` should be called from a handler's `log()`_ method whenever an
+event is successfully logged. Otherwise, registered observers will never
+become aware of the event.
+
+.. _log(): `bool log($message, $priority = null)`_
+
+.. |required| replace:: **[required]**
+
+.. vim: tabstop=4 shiftwidth=4 softtabstop=4 expandtab textwidth=78 ft=rst:
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+$console = &Log::singleton('console', '', 'TEST');
+$file = &Log::singleton('file', 'out.log', 'TEST');
+
+$composite = &Log::singleton('composite');
+$composite->addChild($console);
+$composite->addChild($file);
+
+$composite->log('This event will be logged to both handlers.');
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+$logger = &Log::singleton('console', '', 'ident');
+for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+}
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+$conf = array('error_prepend' => '<font color="#ff0000"><tt>',
+ 'error_append' => '</tt></font>');
+$logger = &Log::singleton('display', '', '', $conf, PEAR_LOG_DEBUG);
+for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+}
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+$logger = &Log::singleton('error_log', PEAR_LOG_TYPE_SYSTEM, 'ident');
+for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+}
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+$conf = array('mode' => 0600, 'timeFormat' => '%X %x');
+$logger = &Log::singleton('file', 'out.log', 'ident', $conf);
+for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+}
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+$logger = &Log::singleton('firebug', '',
+ 'PHP',
+ array('buffering' => true),
+ PEAR_LOG_DEBUG);
+
+for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+}
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+$conf = array('subject' => 'Important Log Events');
+$logger = &Log::singleton('mail', 'webmaster@example.com', 'ident', $conf);
+for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+}
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+$logger = &Log::singleton('null');
+for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+}
--- /dev/null
+<?php
+
+require_once 'Log/observer.php';
+
+class Log_observer_mail extends Log_observer
+{
+ var $_to = '';
+ var $_subject = '';
+ var $_pattern = '';
+
+ function Log_observer_mail($priority, $conf)
+ {
+ /* Call the base class constructor. */
+ $this->Log_observer($priority);
+
+ /* Configure the observer. */
+ $this->_to = $conf['to'];
+ $this->_subject = $conf['subject'];
+ $this->_pattern = $conf['pattern'];
+ }
+
+ function notify($event)
+ {
+ if (preg_match($this->_pattern, $event['message']) != 0) {
+ mail($this->_to, $this->_subject, $event['message']);
+ }
+ }
+}
+
+?>
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+function errorHandler($error)
+{
+ global $logger;
+
+ $message = $error->getMessage();
+
+ if (!empty($error->backtrace[1]['file'])) {
+ $message .= ' (' . $error->backtrace[1]['file'];
+ if (!empty($error->backtrace[1]['line'])) {
+ $message .= ' at line ' . $error->backtrace[1]['line'];
+ }
+ $message .= ')';
+ }
+
+ $logger->log($message, $error->code);
+}
+
+$logger = &Log::singleton('console', '', 'ident');
+
+PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'errorHandler');
+PEAR::raiseError('This is an information log message.', PEAR_LOG_INFO);
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+function errorHandler($code, $message, $file, $line)
+{
+ global $logger;
+
+ /* Map the PHP error to a Log priority. */
+ switch ($code) {
+ case E_WARNING:
+ case E_USER_WARNING:
+ $priority = PEAR_LOG_WARNING;
+ break;
+ case E_NOTICE:
+ case E_USER_NOTICE:
+ $priority = PEAR_LOG_NOTICE;
+ break;
+ case E_ERROR:
+ case E_USER_ERROR:
+ $priority = PEAR_LOG_ERR;
+ break;
+ default:
+ $priotity = PEAR_LOG_INFO;
+ }
+
+ $logger->log($message . ' in ' . $file . ' at line ' . $line,
+ $priority);
+}
+
+$logger = &Log::singleton('console', '', 'ident');
+
+set_error_handler('errorHandler');
+trigger_error('This is an information log message.', E_USER_NOTICE);
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+$conf = array('dsn' => 'pgsql://jon@localhost+unix/logs');
+$logger = &Log::singleton('sql', 'log_table', 'ident', $conf);
+for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+}
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+/* Creating a new database connection. */
+$conf = array('filename' => 'log.db', 'mode' => 0666, 'persistent' => true);
+$logger =& Log::factory('sqlite', 'log_table', 'ident', $conf);
+$logger->log('logging an event', PEAR_LOG_WARNING);
+
+/* Using an existing database connection. */
+$db = sqlite_open('log.db', 0666, $error);
+$logger =& Log::factory('sqlite', 'log_table', 'ident', $db);
+$logger->log('logging an event', PEAR_LOG_WARNING);
+sqlite_close($db);
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+$logger = &Log::singleton('syslog', LOG_LOCAL0, 'ident');
+for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+}
--- /dev/null
+<?php
+
+require_once 'Log.php';
+
+$conf = array('title' => 'Sample Log Output');
+$logger = &Log::singleton('win', 'LogWindow', 'ident', $conf);
+for ($i = 0; $i < 10; $i++) {
+ $logger->log("Log entry $i");
+}
--- /dev/null
+-- $Id: log.sql 215378 2006-06-26 15:25:35Z jon $
+
+CREATE TABLE log_table (
+ id INT NOT NULL,
+ logtime TIMESTAMP NOT NULL,
+ ident CHAR(16) NOT NULL,
+ priority INT NOT NULL,
+ message VARCHAR(200),
+ PRIMARY KEY (id)
+);
--- /dev/null
+--TEST--
+Log: Backtrace Vars
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$conf = array('lineFormat' => '%6$s [%8$s::%7$s] %4$s');
+$logger = Log::singleton('console', '', 'ident', $conf);
+
+# Top-level Logger
+#
+$logger->log("Top-level Logger - log()");
+$logger->info("Top-level Logger - info()");
+
+# Function Logger
+#
+function functionLog($logger)
+{
+ $logger->log("Function Logger - log()");
+ $logger->info("Function Logger - info()");
+}
+
+functionLog($logger);
+
+# Class Logger
+#
+class ClassLogger
+{
+ function log($logger)
+ {
+ $logger->log("Class Logger - log()");
+ $logger->info("Class Logger - info()");
+ }
+}
+
+$classLogger = new ClassLogger();
+$classLogger->log($logger);
+
+# Composite Logger
+#
+$composite = Log::singleton('composite');
+$composite->addChild($logger);
+
+$composite->log("Composite Logger - log()");
+$composite->info("Composite Logger - info()");
+
+# Composite Logger via Class
+#
+$classLogger->log($composite);
+
+# Deeper Backtrace
+function deeperLog($logger)
+{
+ $logger->log("Deeper Logger - log()");
+ $logger->info("Deeper Logger - info()");
+}
+
+$logger->setBacktraceDepth(1);
+deeperLog($logger);
+
+--EXPECT--
+10 [::(none)] Top-level Logger - log()
+11 [::(none)] Top-level Logger - info()
+17 [::functionLog] Function Logger - log()
+18 [::functionLog] Function Logger - info()
+29 [ClassLogger::log] Class Logger - log()
+30 [ClassLogger::log] Class Logger - info()
+42 [::(none)] Composite Logger - log()
+43 [::(none)] Composite Logger - info()
+29 [ClassLogger::log] Class Logger - log()
+30 [ClassLogger::log] Class Logger - info()
+57 [::(none)] Deeper Logger - log()
+53 [::deeperLog] Deeper Logger - info()
--- /dev/null
+--TEST--
+Log: Composite Handler
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+function printOpenStates($children) {
+ foreach ($children as $child) {
+ $state = ($child->_opened) ? 'OPEN' : 'CLOSED';
+ echo "$child->_ident : $state\n";
+ }
+}
+
+function printIdents($children) {
+ foreach ($children as $child) {
+ echo "$child->_ident\n";
+ }
+}
+
+function testPriority($composite, $priority) {
+ $name = Log::priorityToString($priority);
+ $success = $composite->log($name, $priority);
+ echo "$name : " . (($success) ? 'GOOD' : 'BAD') . "\n";
+}
+
+/* Create three handlers with different priority masks. */
+$conf = array('lineFormat' => '%2$s [%3$s] %4$s');
+$children = array(
+ Log::singleton('console', '', 'CONSOLE1', $conf),
+ Log::singleton('console', '', 'CONSOLE2', $conf),
+ Log::singleton('console', '', 'CONSOLE3', $conf)
+);
+
+$children[0]->setMask(Log::MASK(PEAR_LOG_DEBUG));
+$children[1]->setMask(Log::MASK(PEAR_LOG_INFO));
+$children[2]->setMask(Log::MASK(PEAR_LOG_ERR));
+
+$composite = Log::singleton('composite');
+$composite->addChild($children[0]);
+$composite->addChild($children[1]);
+$composite->addChild($children[2]);
+
+/* Verify that all of the children are initially closed. */
+printOpenStates($children);
+
+/* Verify that the composite handler's open() opens all of the children. */
+$composite->open();
+printOpenStates($children);
+
+/* Verify that the composite handler's close() closes all of the children. */
+$composite->close();
+printOpenStates($children);
+
+/* Verify the log results at different priorities. */
+testPriority($composite, PEAR_LOG_DEBUG);
+printOpenStates($children);
+testPriority($composite, PEAR_LOG_INFO);
+printOpenStates($children);
+testPriority($composite, PEAR_LOG_ERR);
+printOpenStates($children);
+
+/* Verify that changing the ident affects all children. */
+$composite->setIdent('IDENT');
+printIdents($children);
+
+--EXPECT--
+CONSOLE1 : CLOSED
+CONSOLE2 : CLOSED
+CONSOLE3 : CLOSED
+CONSOLE1 : OPEN
+CONSOLE2 : OPEN
+CONSOLE3 : OPEN
+CONSOLE1 : CLOSED
+CONSOLE2 : CLOSED
+CONSOLE3 : CLOSED
+CONSOLE1 [debug] debug
+debug : GOOD
+CONSOLE1 : OPEN
+CONSOLE2 : CLOSED
+CONSOLE3 : CLOSED
+CONSOLE2 [info] info
+info : GOOD
+CONSOLE1 : OPEN
+CONSOLE2 : OPEN
+CONSOLE3 : CLOSED
+CONSOLE3 [error] error
+error : GOOD
+CONSOLE1 : OPEN
+CONSOLE2 : OPEN
+CONSOLE3 : OPEN
+IDENT
+IDENT
+IDENT
--- /dev/null
+--TEST--
+Log: Console Handler
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$conf = array('lineFormat' => '%2$s [%3$s] %4$s');
+$logger = Log::singleton('console', '', 'ident', $conf);
+for ($i = 0; $i < 3; $i++) {
+ $logger->log("Log entry $i");
+}
+
+echo "\n[Buffering / Flush Test]\n";
+$conf = array('lineFormat' => '%2$s [%3$s] %4$s', 'buffering' => true);
+$buffered_logger = Log::singleton('console', '', 'buffered', $conf);
+for ($i = 0; $i < 3; $i++) {
+ $buffered_logger->log("Pre-flush buffered log entry $i");
+}
+echo "Pre-flush\n";
+$buffered_logger->flush();
+echo "Post-flush\n";
+for ($i = 0; $i < 3; $i++) {
+ $buffered_logger->log("Post-flush buffered log entry $i");
+}
+echo "Shutdown\n";
+$buffered_logger->close();
+
+--EXPECT--
+ident [info] Log entry 0
+ident [info] Log entry 1
+ident [info] Log entry 2
+
+[Buffering / Flush Test]
+Pre-flush
+buffered [info] Pre-flush buffered log entry 0
+buffered [info] Pre-flush buffered log entry 1
+buffered [info] Pre-flush buffered log entry 2
+Post-flush
+Shutdown
+buffered [info] Post-flush buffered log entry 0
+buffered [info] Post-flush buffered log entry 1
+buffered [info] Post-flush buffered log entry 2
--- /dev/null
+--TEST--
+Log: Display Handler
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+function test($name, $conf)
+{
+ echo "\nTesting $name Configuration\n";
+ echo "------------------------------------------------------\n";
+
+ $logger = Log::factory('display', '', $name, $conf);
+
+ $logger->log("Info", PEAR_LOG_INFO);
+ $logger->log("Error", PEAR_LOG_ERR);
+ $logger->log("Debug", PEAR_LOG_DEBUG);
+ $logger->log("Multi\nLine\nEntry", PEAR_LOG_INFO);
+
+ echo "\n";
+}
+
+test('Default', array());
+test('Line Break', array('linebreak' => "\n"));
+test('Format', array('lineFormat' => '<!-- %4$s -->'));
+test('Prepend / Append', array('error_prepend' => '<tt>',
+ 'error_append' => '</tt>'));
+
+--EXPECT--
+Testing Default Configuration
+------------------------------------------------------
+<b>info</b>: Info<br />
+<b>error</b>: Error<br />
+<b>debug</b>: Debug<br />
+<b>info</b>: Multi<br />
+Line<br />
+Entry<br />
+
+
+Testing Line Break Configuration
+------------------------------------------------------
+<b>info</b>: Info
+<b>error</b>: Error
+<b>debug</b>: Debug
+<b>info</b>: Multi<br />
+Line<br />
+Entry
+
+
+Testing Format Configuration
+------------------------------------------------------
+<!-- Info --><br />
+<!-- Error --><br />
+<!-- Debug --><br />
+<!-- Multi<br />
+Line<br />
+Entry --><br />
+
+
+Testing Prepend / Append Configuration
+------------------------------------------------------
+<tt><b>info</b>: Info</tt><br />
+<tt><b>error</b>: Error</tt><br />
+<tt><b>debug</b>: Debug</tt><br />
+<tt><b>info</b>: Multi<br />
+Line<br />
+Entry</tt><br />
--- /dev/null
+--TEST--
+Log: Error_Log Handler
+--SKIPIF--
+<?php if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') die("skip\n"); ?>
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+/* Default Configuration */
+$logger1 = Log::singleton('error_log', PEAR_LOG_TYPE_SYSTEM, 'ident');
+for ($i = 0; $i < 3; $i++) {
+ $logger1->log("Log entry $i");
+}
+
+/* Custom line format */
+$conf = array('lineFormat' => '%2$s: [%3$s] %4$s');
+$logger2 = Log::singleton('error_log', PEAR_LOG_TYPE_SYSTEM, 'ident', $conf);
+for ($i = 0; $i < 3; $i++) {
+ $logger2->log("Log entry $i");
+}
+
+--EXPECT--
+ident: Log entry 0
+ident: Log entry 1
+ident: Log entry 2
+ident: [info] Log entry 0
+ident: [info] Log entry 1
+ident: [info] Log entry 2
--- /dev/null
+--TEST--
+Log: _extractMessage() [Zend Engine 2.0]
+--SKIPIF--
+<?php
+if (version_compare(zend_version(), "2.0.0", "<") ||
+ version_compare(zend_version(), "2.2.0", ">=")) die('skip');
+?>
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$conf = array('lineFormat' => '%2$s [%3$s] %4$s');
+$logger = Log::singleton('console', '', 'ident', $conf);
+
+/* Logging a regular string. */
+$logger->log('String');
+
+/* Logging a bare object. */
+class BareObject {}
+$logger->log(new BareObject());
+
+/* Logging an object with a getMessage() method. */
+class GetMessageObject { function getMessage() { return "getMessage"; } }
+$logger->log(new GetMessageObject());
+
+/* Logging an object with a toString() method. */
+class ToStringObject { function toString() { return "toString"; } }
+$logger->log(new ToStringObject());
+
+/* Logging an object with a __toString() method using casting. */
+class CastableObject { function __toString() { return "__toString"; } }
+$logger->log(new CastableObject());
+
+/* Logging a PEAR_Error object. */
+require_once 'PEAR.php';
+$logger->log(new PEAR_Error('PEAR_Error object', 100));
+
+/* Logging an array. */
+$logger->log(array(1, 2, 'three' => 3));
+
+/* Logging an array with scalar 'message' keys. */
+$logger->log(array('message' => 'Message Key'));
+$logger->log(array('message' => 50));
+
+/* Logging an array with a non-scalar 'message' key. */
+$logger->log(array('message' => array(1, 2, 3)));
+
+--EXPECT--
+ident [info] String
+ident [info] BareObject::__set_state(array(
+))
+ident [info] getMessage
+ident [info] toString
+ident [info] Object id #2
+ident [info] PEAR_Error object
+ident [info] array (
+ 0 => 1,
+ 1 => 2,
+ 'three' => 3,
+
+ident [info] Message Key
+ident [info] 50
+ident [info] array (
+ 0 => 1,
+ 1 => 2,
+ 2 => 3,
+)
--- /dev/null
+--TEST--
+Log: _extractMessage() [Zend Engine 2.2]
+--SKIPIF--
+<?php if (version_compare(zend_version(), "2.2.0", "<")) die('skip'); ?>
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$conf = array('lineFormat' => '%2$s [%3$s] %4$s');
+$logger = Log::singleton('console', '', 'ident', $conf);
+
+/* Logging a regular string. */
+$logger->log('String');
+
+/* Logging a bare object. */
+class BareObject {}
+$logger->log(new BareObject());
+
+/* Logging an object with a getMessage() method. */
+class GetMessageObject { function getMessage() { return "getMessage"; } }
+$logger->log(new GetMessageObject());
+
+/* Logging an object with a toString() method. */
+class ToStringObject { function toString() { return "toString"; } }
+$logger->log(new ToStringObject());
+
+/* Logging an object with a __toString() method using casting. */
+class CastableObject { function __toString() { return "__toString"; } }
+$logger->log(new CastableObject());
+
+/* Logging a PEAR_Error object. */
+require_once 'PEAR.php';
+$logger->log(new PEAR_Error('PEAR_Error object', 100));
+
+/* Logging an array. */
+$logger->log(array(1, 2, 'three' => 3));
+
+/* Logging an array with scalar 'message' keys. */
+$logger->log(array('message' => 'Message Key'));
+$logger->log(array('message' => 50));
+
+/* Logging an array with a non-scalar 'message' key. */
+$logger->log(array('message' => array(1, 2, 3)));
+
+--EXPECT--
+ident [info] String
+ident [info] BareObject::__set_state(array(
+))
+ident [info] getMessage
+ident [info] toString
+ident [info] __toString
+ident [info] PEAR_Error object
+ident [info] array (
+ 0 => 1,
+ 1 => 2,
+ 'three' => 3,
+)
+ident [info] Message Key
+ident [info] 50
+ident [info] array (
+ 0 => 1,
+ 1 => 2,
+ 2 => 3,
+)
--- /dev/null
+--TEST--
+Log: Factory
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$console1 = Log::factory('console');
+$console2 = Log::factory('console');
+
+if (is_a($console1, 'Log_console') && is_a($console2, 'Log_console'))
+{
+ echo "Two Log_console objects.\n";
+}
+
+if ($console1->_id != $console2->_id) {
+ echo "The objects have different IDs.\n";
+}
+
+--EXPECT--
+Two Log_console objects.
+The objects have different IDs.
--- /dev/null
+--TEST--
+Log: File Handler
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$filename = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test.log';
+if (file_exists($filename)) unlink($filename);
+
+/* Write some entries to the log file. */
+$conf = array('lineFormat' => '%2$s [%3$s] %4$s');
+$logger = Log::singleton('file', $filename, '', $conf);
+
+for ($i = 0; $i < 3; $i++) {
+ $logger->log("Log entry $i");
+}
+$logger->close();
+
+/* Dump the contents of the log file. */
+echo file_get_contents($filename);
+
+/* Clean up. */
+if (file_exists($filename)) unlink($filename);
+
+--EXPECT--
+ [info] Log entry 0
+ [info] Log entry 1
+ [info] Log entry 2
--- /dev/null
+--TEST--
+Log: Firebug Handler
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$conf = array();
+print "** UNBUFFERED **\n";
+$logger = Log::singleton('firebug', '', 'PHP', $conf);
+$logger->log('Debug', PEAR_LOG_DEBUG);
+$logger->log('Info', PEAR_LOG_INFO);
+$logger->log('Notice', PEAR_LOG_NOTICE);
+$logger->log('Warning', PEAR_LOG_WARNING);
+$logger->log('Error', PEAR_LOG_ERR);
+$logger->log('Critical', PEAR_LOG_CRIT);
+$logger->log('Alert', PEAR_LOG_ALERT);
+$logger->log('Emergency', PEAR_LOG_EMERG);
+unset($logger);
+
+print "\n** START BUFFERING **\n";
+$conf = array('buffering' => true);
+$logger = Log::singleton('firebug', '', 'PHP', $conf);
+$logger->log('Debug', PEAR_LOG_DEBUG);
+$logger->log('Info', PEAR_LOG_INFO);
+$logger->log('Notice', PEAR_LOG_NOTICE);
+$logger->log('Warning', PEAR_LOG_WARNING);
+$logger->flush();
+print "** FLUSHED **\n";
+print "** REST OF BUFFERED **\n";
+$logger->log('Error', PEAR_LOG_ERR);
+$logger->log('Critical', PEAR_LOG_CRIT);
+$logger->log('Alert', PEAR_LOG_ALERT);
+$logger->log('Emergency', PEAR_LOG_EMERG);
+--EXPECT--
+** UNBUFFERED **
+<script type="text/javascript">
+if ('console' in window) {
+ console.debug("PHP [debug] Debug");
+}
+</script>
+<script type="text/javascript">
+if ('console' in window) {
+ console.info("PHP [info] Info");
+}
+</script>
+<script type="text/javascript">
+if ('console' in window) {
+ console.info("PHP [notice] Notice");
+}
+</script>
+<script type="text/javascript">
+if ('console' in window) {
+ console.warn("PHP [warning] Warning");
+}
+</script>
+<script type="text/javascript">
+if ('console' in window) {
+ console.error("PHP [error] Error");
+}
+</script>
+<script type="text/javascript">
+if ('console' in window) {
+ console.error("PHP [critical] Critical");
+}
+</script>
+<script type="text/javascript">
+if ('console' in window) {
+ console.error("PHP [alert] Alert");
+}
+</script>
+<script type="text/javascript">
+if ('console' in window) {
+ console.error("PHP [emergency] Emergency");
+}
+</script>
+
+** START BUFFERING **
+<script type="text/javascript">
+if ('console' in window) {
+ console.debug("PHP [debug] Debug");
+ console.info("PHP [info] Info");
+ console.info("PHP [notice] Notice");
+ console.warn("PHP [warning] Warning");
+}
+</script>
+** FLUSHED **
+** REST OF BUFFERED **
+<script type="text/javascript">
+if ('console' in window) {
+ console.error("PHP [error] Error");
+ console.error("PHP [critical] Critical");
+ console.error("PHP [alert] Alert");
+ console.error("PHP [emergency] Emergency");
+}
+</script>
--- /dev/null
+--TEST--
+Log: Line Format
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$conf = array('lineFormat' => '%{timestamp} %{ident} %{priority} %{message} %{file} %{line} %{function} %{class}');
+$logger = Log::singleton('console', '', 'ident', $conf);
+$logger->log('Message');
+
+--EXPECTREGEX--
+^\w{3} \d+ \d{2}:\d{2}:\d{2} ident info Message .*format\.php \d+ [\(\)\w]+$
--- /dev/null
+--TEST--
+Log: Levels
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+function verify($exp, $msg)
+{
+ echo $msg . ': ';
+ echo ($exp) ? 'pass' : 'fail';
+ echo "\n";
+}
+
+function testLevels($mask)
+{
+ echo "Mask: " . ($mask & 0xffff) . "\n";
+
+ for ($priority = PEAR_LOG_EMERG; $priority <= PEAR_LOG_DEBUG; $priority++) {
+ $masked = (Log::MASK($priority) & $mask);
+ echo "Priority $priority: ";
+ echo($masked) ? "masked\n" : "unmasked\n";
+ }
+
+ echo "\n";
+}
+
+testLevels(PEAR_LOG_NONE);
+testLevels(PEAR_LOG_ALL);
+testLevels(Log::MIN(PEAR_LOG_WARNING));
+testLevels(Log::MAX(PEAR_LOG_WARNING));
+
+--EXPECT--
+Mask: 0
+Priority 0: unmasked
+Priority 1: unmasked
+Priority 2: unmasked
+Priority 3: unmasked
+Priority 4: unmasked
+Priority 5: unmasked
+Priority 6: unmasked
+Priority 7: unmasked
+
+Mask: 65535
+Priority 0: masked
+Priority 1: masked
+Priority 2: masked
+Priority 3: masked
+Priority 4: masked
+Priority 5: masked
+Priority 6: masked
+Priority 7: masked
+
+Mask: 65520
+Priority 0: unmasked
+Priority 1: unmasked
+Priority 2: unmasked
+Priority 3: unmasked
+Priority 4: masked
+Priority 5: masked
+Priority 6: masked
+Priority 7: masked
+
+Mask: 31
+Priority 0: masked
+Priority 1: masked
+Priority 2: masked
+Priority 3: masked
+Priority 4: masked
+Priority 5: unmasked
+Priority 6: unmasked
+Priority 7: unmasked
--- /dev/null
+--TEST--
+Log: Masks
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+/* Levels */
+for ($level = PEAR_LOG_EMERG; $level <= PEAR_LOG_DEBUG; $level++) {
+
+ printf("Level %d: 0x%08x, 0x%08x, 0x%08x\n",
+ $level,
+ Log::MASK($level),
+ Log::MIN($level),
+ Log::MAX($level));
+}
+echo "\n";
+
+/* Mask */
+$conf = array('lineFormat' => '%2$s [%3$s] %4$s');
+$logger = Log::singleton('console', '', 'ident', $conf);
+
+$logger->setMask(Log::MAX(PEAR_LOG_INFO));
+$logger->info('Info 1');
+$logger->setMask(Log::MAX(PEAR_LOG_ERR));
+$logger->info('Info 2');
+
+--EXPECT--
+Level 0: 0x00000001, 0xffffffff, 0x00000001
+Level 1: 0x00000002, 0xfffffffe, 0x00000003
+Level 2: 0x00000004, 0xfffffffc, 0x00000007
+Level 3: 0x00000008, 0xfffffff8, 0x0000000f
+Level 4: 0x00000010, 0xfffffff0, 0x0000001f
+Level 5: 0x00000020, 0xffffffe0, 0x0000003f
+Level 6: 0x00000040, 0xffffffc0, 0x0000007f
+Level 7: 0x00000080, 0xffffff80, 0x000000ff
+
+ident [info] Info 1
--- /dev/null
+--TEST--
+Log: Null Handler
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$logger = Log::singleton('null');
+for ($i = 0; $i < 3; $i++) {
+ $logger->log("Log entry $i");
+}
+
+--EXPECT--
--- /dev/null
+--TEST--
+Log: Priorities
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$conf = array('lineFormat' => '[%3$s] %4$s');
+$logger = Log::singleton('console', '', 'ident', $conf);
+
+/* Log at the default PEAR_LOG_INFO level. */
+$logger->log('Log message');
+
+/* Set the default priority to PEAR_LOG_DEBUG. */
+$logger->setPriority(PEAR_LOG_DEBUG);
+$logger->log('Log message');
+
+/* Verify that the getPriority() method also things we're at PEAR_LOG_DEBUG. */
+$priority = $logger->priorityToString($logger->getPriority());
+echo "$priority\n";
+
+/* Verify that stringToPriority() can convert back to a constant. */
+$priority = $logger->stringToPriority($priority);
+echo "$priority\n";
+
+--EXPECT--
+[info] Log message
+[debug] Log message
+debug
+7
--- /dev/null
+--TEST--
+Log: Singleton
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$console1 = Log::singleton('console');
+$console2 = Log::singleton('console');
+
+if (is_a($console1, 'Log_console') && is_a($console2, 'Log_console'))
+{
+ echo "Two Log_console objects.\n";
+}
+
+if ($console1->_id == $console2->_id) {
+ echo "The objects have the same ID.\n";
+}
+
+--EXPECT--
+Two Log_console objects.
+The objects have the same ID.
--- /dev/null
+--TEST--
+Log: SQL setIdent()
+--SKIPIF--
+<?php
+
+require_once 'PEAR/Registry.php';
+$registry = new PEAR_Registry();
+
+if (!$registry->packageExists('DB')) die("skip\n");
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$ident = '12345678901234567890';
+
+$logger = Log::singleton('sql', 'log_table', $ident, array('dsn' => ''));
+echo $logger->getIdent() . "\n";
+
+$logger->setIdent($ident);
+echo $logger->getIdent() . "\n";
+
+--EXPECT--
+1234567890123456
+1234567890123456
--- /dev/null
+--TEST--
+Log: Sqlite Handler
+--SKIPIF--
+<?php if (!function_exists('sqlite_open')) die("skip\n"); ?>
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$filename = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'sqlite-log.db';
+if (file_exists($filename)) unlink($filename);
+
+$db = sqlite_open($filename, 0666, $error);
+$ident = time();
+$message = 'logging an event';
+$logger = Log::factory('sqlite', 'log_table', $ident, $db);
+$logger->log($message, PEAR_LOG_WARNING);
+
+$q = "SELECT message FROM log_table WHERE ident='$ident'";
+$res = sqlite_query($db, $q);
+if (sqlite_fetch_string($res) == $message) {
+ echo 'ok';
+}
+
+sqlite_close($db);
+if (file_exists($filename)) unlink($filename);
+
+--EXPECT--
+ok
--- /dev/null
+--TEST--
+Log: Syslog Handler
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$logger = Log::singleton('syslog', '', 'Test');
+for ($i = 0; $i < 3; $i++) {
+ $logger->notice("Log entry $i");
+}
+
+--EXPECT--
--- /dev/null
+--TEST--
+Log: Window Handler (Output Buffering)
+--INI--
+date.timezone=UTC
+output_buffering=on
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$conf = array('title' => 'Test Output');
+$logger = Log::singleton('win', 'test', 'ident', $conf);
+
+for ($i = 0; $i < 3; $i++) {
+ $logger->log("Log entry $i");
+}
+
+--EXPECTF--
+<script language="JavaScript">
+test = window.open('', 'test', 'toolbar=no,scrollbars,width=600,height=400');
+test.document.writeln('<html>');
+test.document.writeln('<head>');
+test.document.writeln('<title>Test Output</title>');
+test.document.writeln('<style type="text/css">');
+test.document.writeln('body { font-family: monospace; font-size: 8pt; }');
+test.document.writeln('td,th { font-size: 8pt; }');
+test.document.writeln('td,th { border-bottom: #999999 solid 1px; }');
+test.document.writeln('td,th { border-right: #999999 solid 1px; }');
+test.document.writeln('tr { text-align: left; vertical-align: top; }');
+test.document.writeln('td.l0 { color: red; }');
+test.document.writeln('td.l1 { color: orange; }');
+test.document.writeln('td.l2 { color: yellow; }');
+test.document.writeln('td.l3 { color: green; }');
+test.document.writeln('td.l4 { color: blue; }');
+test.document.writeln('td.l5 { color: indigo; }');
+test.document.writeln('td.l6 { color: violet; }');
+test.document.writeln('td.l7 { color: black; }');
+test.document.writeln('</style>');
+test.document.writeln('<script type="text/javascript">');
+test.document.writeln('function scroll() {');
+test.document.writeln(' body = document.getElementById("test");');
+test.document.writeln(' body.scrollTop = body.scrollHeight;');
+test.document.writeln('}');
+test.document.writeln('<\/script>');
+test.document.writeln('</head>');
+test.document.writeln('<body id="test" onclick="scroll()">');
+test.document.writeln('<table border="0" cellpadding="2" cellspacing="0">');
+test.document.writeln('<tr><th>Time</th>');
+test.document.writeln('<th>Ident</th>')
+test.document.writeln('<th>Priority</th><th width="100%">Message</th></tr>');
+</script><script language='JavaScript'>
+test.document.writeln('<tr><td>%i:%i:%i.%i</td><td>ident</td><td>Info</td><td class=\"l6\">Log entry 0</td></tr>');
+self.focus();
+</script>
+<script language='JavaScript'>
+test.document.writeln('<tr><td>%i:%i:%i.%i</td><td>ident</td><td>Info</td><td class=\"l6\">Log entry 1</td></tr>');
+self.focus();
+</script>
+<script language='JavaScript'>
+test.document.writeln('<tr><td>%i:%i:%i.%i</td><td>ident</td><td>Info</td><td class=\"l6\">Log entry 2</td></tr>');
+self.focus();
+</script>
+<script language='JavaScript'>
+test.document.writeln('</table>');
+self.focus();
+</script>
+<script language='JavaScript'>
+test.document.writeln('</body></html>');
+self.focus();
+</script>
--- /dev/null
+--TEST--
+Log: Window Handler
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+
+require_once 'Log.php';
+
+$conf = array('title' => 'Test Output');
+$logger = Log::singleton('win', 'test', 'ident', $conf);
+
+for ($i = 0; $i < 3; $i++) {
+ $logger->log("Log entry $i");
+}
+
+--EXPECTF--
+<script language="JavaScript">
+test = window.open('', 'test', 'toolbar=no,scrollbars,width=600,height=400');
+test.document.writeln('<html>');
+test.document.writeln('<head>');
+test.document.writeln('<title>Test Output</title>');
+test.document.writeln('<style type="text/css">');
+test.document.writeln('body { font-family: monospace; font-size: 8pt; }');
+test.document.writeln('td,th { font-size: 8pt; }');
+test.document.writeln('td,th { border-bottom: #999999 solid 1px; }');
+test.document.writeln('td,th { border-right: #999999 solid 1px; }');
+test.document.writeln('tr { text-align: left; vertical-align: top; }');
+test.document.writeln('td.l0 { color: red; }');
+test.document.writeln('td.l1 { color: orange; }');
+test.document.writeln('td.l2 { color: yellow; }');
+test.document.writeln('td.l3 { color: green; }');
+test.document.writeln('td.l4 { color: blue; }');
+test.document.writeln('td.l5 { color: indigo; }');
+test.document.writeln('td.l6 { color: violet; }');
+test.document.writeln('td.l7 { color: black; }');
+test.document.writeln('</style>');
+test.document.writeln('<script type="text/javascript">');
+test.document.writeln('function scroll() {');
+test.document.writeln(' body = document.getElementById("test");');
+test.document.writeln(' body.scrollTop = body.scrollHeight;');
+test.document.writeln('}');
+test.document.writeln('<\/script>');
+test.document.writeln('</head>');
+test.document.writeln('<body id="test" onclick="scroll()">');
+test.document.writeln('<table border="0" cellpadding="2" cellspacing="0">');
+test.document.writeln('<tr><th>Time</th>');
+test.document.writeln('<th>Ident</th>')
+test.document.writeln('<th>Priority</th><th width="100%">Message</th></tr>');
+</script><script language='JavaScript'>
+test.document.writeln('<tr><td>%i:%i:%i.%i</td><td>ident</td><td>Info</td><td class=\"l6\">Log entry 0</td></tr>');
+self.focus();
+</script>
+<script language='JavaScript'>
+test.document.writeln('<tr><td>%i:%i:%i.%i</td><td>ident</td><td>Info</td><td class=\"l6\">Log entry 1</td></tr>');
+self.focus();
+</script>
+<script language='JavaScript'>
+test.document.writeln('<tr><td>%i:%i:%i.%i</td><td>ident</td><td>Info</td><td class=\"l6\">Log entry 2</td></tr>');
+self.focus();
+</script>
+<script language='JavaScript'>
+test.document.writeln('</table>');
+self.focus();
+</script>
+<script language='JavaScript'>
+test.document.writeln('</body></html>');
+self.focus();
+</script>