Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/inc/Log
diff options
context:
space:
mode:
authorFrank Karlitschek <frank@dev.(none)>2010-03-10 15:03:40 +0300
committerFrank Karlitschek <frank@dev.(none)>2010-03-10 15:03:40 +0300
commit16f3bd4e2334491152510598f861a1f6c1ecdae2 (patch)
tree73370c91c4259f9f20f90137c2e39f366d6d078a /inc/Log
parentef2028148691c01c1841745fde9868ce27d9a3a5 (diff)
commiting ownCloud 1.0 beta 1v1.0.0beta1
Diffstat (limited to 'inc/Log')
-rwxr-xr-xinc/Log/composite.php196
-rwxr-xr-xinc/Log/console.php190
-rwxr-xr-xinc/Log/daemon.php229
-rwxr-xr-xinc/Log/display.php108
-rwxr-xr-xinc/Log/error_log.php104
-rwxr-xr-xinc/Log/file.php286
-rwxr-xr-xinc/Log/mail.php222
-rwxr-xr-xinc/Log/mcal.php171
-rwxr-xr-xinc/Log/null.php68
-rwxr-xr-xinc/Log/observer.php126
-rwxr-xr-xinc/Log/sql.php225
-rwxr-xr-xinc/Log/sqlite.php238
-rwxr-xr-xinc/Log/syslog.php160
-rwxr-xr-xinc/Log/win.php256
14 files changed, 2579 insertions, 0 deletions
diff --git a/inc/Log/composite.php b/inc/Log/composite.php
new file mode 100755
index 00000000000..104c8966c42
--- /dev/null
+++ b/inc/Log/composite.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * $Header: /repository/pear/Log/Log/composite.php,v 1.23 2004/08/09 06:04:11 jon Exp $
+ * $Horde: horde/lib/Log/composite.php,v 1.2 2000/06/28 21:36:13 jon Exp $
+ *
+ * @version $Revision: 1.23 $
+ * @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 = false, $ident = false, $conf = false,
+ $level = PEAR_LOG_DEBUG)
+ {
+ }
+
+ /**
+ * Opens the child connections.
+ *
+ * @access public
+ */
+ function open()
+ {
+ if (!$this->_opened) {
+ foreach ($this->_children as $id => $child) {
+ $this->_children[$id]->open();
+ }
+ $this->_opened = true;
+ }
+ }
+
+ /**
+ * Closes any child instances.
+ *
+ * @access public
+ */
+ function close()
+ {
+ if ($this->_opened) {
+ foreach ($this->_children as $id => $child) {
+ $this->_children[$id]->close();
+ }
+ $this->_opened = false;
+ }
+ }
+
+ /**
+ * Flushes all open child instances.
+ *
+ * @access public
+ * @since Log 1.8.2
+ */
+ function flush()
+ {
+ if ($this->_opened) {
+ foreach ($this->_children as $id => $child) {
+ $this->_children[$id]->flush();
+ }
+ }
+ }
+
+ /**
+ * Sends $message and $priority to each child of this composite.
+ *
+ * @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;
+ }
+
+ foreach ($this->_children as $id => $child) {
+ $this->_children[$id]->log($message, $priority);
+ }
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+
+ /**
+ * 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)
+ {
+ foreach ($this->_children as $id => $child) {
+ $this->_children[$id]->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;
+ }
+}
+
+?>
diff --git a/inc/Log/console.php b/inc/Log/console.php
new file mode 100755
index 00000000000..62032e79644
--- /dev/null
+++ b/inc/Log/console.php
@@ -0,0 +1,190 @@
+<?php
+/**
+ * $Header: /repository/pear/Log/Log/console.php,v 1.19 2004/01/19 08:02:40 jon Exp $
+ *
+ * @version $Revision: 1.19 $
+ * @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 = STDOUT;
+
+ /**
+ * 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';
+
+ /**
+ * Hash that maps canonical format keys to position arguments for the
+ * "line format" string.
+ * @var array
+ * @access private
+ */
+ var $_formatMap = array('%{timestamp}' => '%1$s',
+ '%{ident}' => '%2$s',
+ '%{priority}' => '%3$s',
+ '%{message}' => '%4$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'];
+ }
+
+ 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->flush();
+ }
+
+ /**
+ * 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 = '';
+ }
+
+ return fflush($this->_stream);
+ }
+
+ /**
+ * 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 = sprintf($this->_lineFormat, strftime($this->_timeFormat),
+ $this->_ident, $this->priorityToString($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;
+ }
+}
+
+?>
diff --git a/inc/Log/daemon.php b/inc/Log/daemon.php
new file mode 100755
index 00000000000..739270c9a32
--- /dev/null
+++ b/inc/Log/daemon.php
@@ -0,0 +1,229 @@
+<?php
+// $Id: daemon.php,v 1.1 2004/12/21 06:55:38 jon Exp $
+
+/**
+ * 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: 1.1 $
+ * @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];
+ }
+}
diff --git a/inc/Log/display.php b/inc/Log/display.php
new file mode 100755
index 00000000000..0d5a93d79da
--- /dev/null
+++ b/inc/Log/display.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * $Header: /repository/pear/Log/Log/display.php,v 1.6 2004/11/27 21:46:50 jon Exp $
+ *
+ * @version $Revision: 1.6 $
+ * @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 to output before an error message
+ * @var string
+ * @access private
+ */
+ var $_error_prepend = '';
+
+ /**
+ * String to output after an error message
+ * @var string
+ * @access private
+ */
+ var $_error_append = '';
+
+
+ /**
+ * 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);
+
+ if (!empty($conf['error_prepend'])) {
+ $this->_error_prepend = $conf['error_prepend'];
+ } else {
+ $this->_error_prepend = ini_get('error_prepend_string');
+ }
+
+ if (!empty($conf['error_append'])) {
+ $this->_error_append = $conf['error_append'];
+ } else {
+ $this->_error_append = ini_get('error_append_string');
+ }
+ }
+
+ /**
+ * 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);
+
+ /* Build and output the complete log line. */
+ echo $this->_error_prepend .
+ '<b>' . ucfirst($this->priorityToString($priority)) . '</b>: '.
+ nl2br(htmlspecialchars($message)) .
+ $this->_error_append . "<br />\n";
+
+ /* Notify observers about this log message. */
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+}
+
+?>
diff --git a/inc/Log/error_log.php b/inc/Log/error_log.php
new file mode 100755
index 00000000000..04c0952cd7a
--- /dev/null
+++ b/inc/Log/error_log.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * $Header: /repository/pear/Log/Log/error_log.php,v 1.6 2004/01/19 08:02:40 jon Exp $
+ *
+ * @version $Revision: 1.6 $
+ * @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 = '';
+
+ /**
+ * Constructs a new Log_error_log 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_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'];
+ }
+ }
+
+ /**
+ * 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);
+
+ $success = error_log($this->_ident . ': ' . $message, $this->_type,
+ $this->_destination, $this->_extra_headers);
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return $success;
+ }
+}
+
+?>
diff --git a/inc/Log/file.php b/inc/Log/file.php
new file mode 100755
index 00000000000..36f30b42978
--- /dev/null
+++ b/inc/Log/file.php
@@ -0,0 +1,286 @@
+<?php
+/**
+ * $Header: /repository/pear/Log/Log/file.php,v 1.37 2004/01/19 08:02:40 jon Exp $
+ *
+ * @version $Revision: 1.37 $
+ * @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;
+
+ /**
+ * Integer (in octal) containing the log file's permissions mode.
+ * @var integer
+ * @access private
+ */
+ var $_mode = 0644;
+
+ /**
+ * 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';
+
+ /**
+ * Hash that maps canonical format keys to position arguments for the
+ * "line format" string.
+ * @var array
+ * @access private
+ */
+ var $_formatMap = array('%{timestamp}' => '%1$s',
+ '%{ident}' => '%2$s',
+ '%{priority}' => '%3$s',
+ '%{message}' => '%4$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 (!empty($conf['mode'])) {
+ $this->_mode = $conf['mode'];
+ }
+
+ 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.
+ *
+ * @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)
+ {
+ static $depth = 0;
+
+ /* Guard against potentially infinite recursion. */
+ if ($depth++ > 25) {
+ trigger_error("_mkpath(): Maximum recursion depth (25) exceeded",
+ E_USER_WARNING);
+ return false;
+ }
+
+ /* We're only interested in the directory component of the path. */
+ $path = dirname($path);
+
+ /* If the directory already exists, return success immediately. */
+ if (is_dir($path)) {
+ $depth = 0;
+ return true;
+ }
+
+ /*
+ * In order to understand recursion, you must first understand
+ * recursion ...
+ */
+ if ($this->_mkpath($path, $mode) === false) {
+ return false;
+ }
+
+ return @mkdir($path, $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);
+ }
+
+ /* Obtain a handle to the log file. */
+ $this->_fp = fopen($this->_filename, ($this->_append) ? 'a' : 'w');
+
+ $this->_opened = ($this->_fp !== false);
+
+ /* Attempt to set the log file's mode. */
+ @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()
+ {
+ return fflush($this->_fp);
+ }
+
+ /**
+ * 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 = sprintf($this->_lineFormat, strftime($this->_timeFormat),
+ $this->_ident, $this->priorityToString($priority),
+ $message) . $this->_eol;
+
+ /* Write the log line to the log file. */
+ $success = (fwrite($this->_fp, $line) !== false);
+
+ /* Notify observers about this log message. */
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return $success;
+ }
+}
+
+?>
diff --git a/inc/Log/mail.php b/inc/Log/mail.php
new file mode 100755
index 00000000000..064f13c0ed5
--- /dev/null
+++ b/inc/Log/mail.php
@@ -0,0 +1,222 @@
+<?php
+/**
+ * $Header: /repository/pear/Log/Log/mail.php,v 1.21 2004/01/19 08:02:40 jon Exp $
+ *
+ * @version $Revision: 1.21 $
+ * @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 recipient's email address.
+ * @var string
+ * @access private
+ */
+ var $_recipient = '';
+
+ /**
+ * 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 holding the mail message body.
+ * @var string
+ * @access private
+ */
+ var $_message = '';
+
+
+ /**
+ * 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.
+ *
+ * @param string $name The filename of the logfile.
+ * @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->_recipient = $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'];
+ }
+
+ /* 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 . "\n\n";
+ }
+ $this->_opened = true;
+ }
+
+ 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 (!empty($this->_message)) {
+ $headers = "From: $this->_from\n";
+ $headers .= "User-Agent: Log_mail";
+
+ if (mail($this->_recipient, $this->_subject, $this->_message,
+ $headers) == false) {
+ error_log("Log_mail: Failure executing mail()", 0);
+ return false;
+ }
+
+ /* Clear the message string now that the email has been sent. */
+ $this->_message = '';
+ }
+ $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);
+
+ $entry = sprintf("%s %s [%s] %s\n", strftime('%b %d %H:%M:%S'),
+ $this->_ident, Log::priorityToString($priority),
+ $message);
+
+ $this->_message .= $entry;
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+}
+
+?>
diff --git a/inc/Log/mcal.php b/inc/Log/mcal.php
new file mode 100755
index 00000000000..a5c46f3dfc6
--- /dev/null
+++ b/inc/Log/mcal.php
@@ -0,0 +1,171 @@
+<?php
+/**
+ * $Header: /repository/pear/Log/Log/mcal.php,v 1.17 2004/01/19 08:02:40 jon Exp $
+ * $Horde: horde/lib/Log/mcal.php,v 1.2 2000/06/28 21:36:13 jon Exp $
+ *
+ * @version $Revision: 1.17 $
+ * @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;
+ }
+}
+
+?>
diff --git a/inc/Log/null.php b/inc/Log/null.php
new file mode 100755
index 00000000000..23de3f1a9e5
--- /dev/null
+++ b/inc/Log/null.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * $Header: /repository/pear/Log/Log/null.php,v 1.3 2004/01/19 08:02:40 jon Exp $
+ *
+ * @version $Revision: 1.3 $
+ * @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);
+ }
+
+ /**
+ * 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;
+ }
+}
+
+?>
diff --git a/inc/Log/observer.php b/inc/Log/observer.php
new file mode 100755
index 00000000000..187d5070f74
--- /dev/null
+++ b/inc/Log/observer.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * $Header: /repository/pear/Log/Log/observer.php,v 1.12 2004/01/11 20:49:49 jon Exp $
+ * $Horde: horde/lib/Log/observer.php,v 1.5 2000/06/28 21:36:13 jon Exp $
+ *
+ * @version $Revision: 1.12 $
+ * @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 an false on an error.
+ */
+ function &factory($type, $priority = PEAR_LOG_INFO, $conf = array())
+ {
+ $type = strtolower($type);
+ $class = 'Log_observer_' . $type;
+
+ /* Support both the new-style and old-style file naming conventions. */
+ if (file_exists(dirname(__FILE__) . '/observer_' . $type . '.php')) {
+ $classfile = 'Log/observer_' . $type . '.php';
+ $newstyle = true;
+ } else {
+ $classfile = 'Log/' . $type . '.php';
+ $newstyle = false;
+ }
+
+ /* Issue a warning if the old-style conventions are being used. */
+ if (!$newstyle)
+ {
+ trigger_error('Using old-style Log_observer conventions',
+ E_USER_WARNING);
+ }
+
+ /*
+ * 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) {
+ return new $class($priority, $conf);
+ } else {
+ return new $class($priority);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * 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);
+ }
+}
+
+?>
diff --git a/inc/Log/sql.php b/inc/Log/sql.php
new file mode 100755
index 00000000000..3a20a0e2faf
--- /dev/null
+++ b/inc/Log/sql.php
@@ -0,0 +1,225 @@
+<?php
+/**
+ * $Header: /repository/pear/Log/Log/sql.php,v 1.34 2004/08/19 06:35:57 jon Exp $
+ * $Horde: horde/lib/Log/sql.php,v 1.12 2000/08/16 20:27:34 chuck Exp $
+ *
+ * @version $Revision: 1.34 $
+ * @package Log
+ */
+
+/** PEAR's DB package */
+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 {
+
+ /**
+ * Array containing the dsn information.
+ * @var string
+ * @access private
+ */
+ var $_dsn = '';
+
+ /**
+ * 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';
+
+ /**
+ * 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);
+
+ /* 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) {
+ $this->_db = &DB::connect($this->_dsn, true);
+ if (DB::isError($this->_db)) {
+ return false;
+ }
+ $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;
+ 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;
+ }
+
+ /* Extract the string representation of the message. */
+ $message = $this->_extractMessage($message);
+
+ /* Build the SQL query for this log entry insertion. */
+ $id = $this->_db->nextId($this->_sequence);
+ $q = sprintf('insert into %s (id, logtime, ident, priority, message)' .
+ 'values(%d, CURRENT_TIMESTAMP, %s, %d, %s)',
+ $this->_table, $id, $this->_db->quote($this->_ident),
+ $priority, $this->_db->quote($message));
+
+ $result = $this->_db->query($q);
+ if (DB::isError($result)) {
+ return false;
+ }
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+}
+
+?>
diff --git a/inc/Log/sqlite.php b/inc/Log/sqlite.php
new file mode 100755
index 00000000000..83b908a9396
--- /dev/null
+++ b/inc/Log/sqlite.php
@@ -0,0 +1,238 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4.0 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2004 The PHP Group |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available at through the world-wide-web at |
+// | http://www.php.net/license/2_02.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Authors: Bertrand Mansion <bmansion@mamasam.com> |
+// +----------------------------------------------------------------------+
+//
+// $Id: sqlite.php,v 1.3 2004/01/19 08:02:40 jon Exp $
+
+/**
+ * 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;
+ }
+}
+
+?>
diff --git a/inc/Log/syslog.php b/inc/Log/syslog.php
new file mode 100755
index 00000000000..4bafbaa2d9a
--- /dev/null
+++ b/inc/Log/syslog.php
@@ -0,0 +1,160 @@
+<?php
+/**
+ * $Header: /repository/pear/Log/Log/syslog.php,v 1.22 2004/01/19 08:02:40 jon Exp $
+ * $Horde: horde/lib/Log/syslog.php,v 1.6 2000/06/28 21:36:13 jon Exp $
+ *
+ * @version $Revision: 1.22 $
+ * @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>
+ * @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 string
+ * @access private
+ */
+ var $_name = LOG_SYSLOG;
+
+ /**
+ * 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;
+ }
+
+ $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) {
+ openlog($this->_ident, LOG_PID, $this->_name);
+ $this->_opened = true;
+ }
+
+ return $this->_opened;
+ }
+
+ /**
+ * Closes the connection to the system logger, if it is open.
+ * @access public
+ */
+ function close()
+ {
+ if ($this->_opened) {
+ closelog();
+ $this->_opened = false;
+ }
+
+ return ($this->_opened === false);
+ }
+
+ /**
+ * 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 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);
+
+ if (!syslog($this->_toSyslog($priority), $message)) {
+ 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];
+ }
+}
+?>
diff --git a/inc/Log/win.php b/inc/Log/win.php
new file mode 100755
index 00000000000..e8a09d16e81
--- /dev/null
+++ b/inc/Log/win.php
@@ -0,0 +1,256 @@
+<?php
+/**
+ * $Header: /repository/pear/Log/Log/win.php,v 1.16 2004/09/08 23:35:53 jon Exp $
+ *
+ * @version $Revision: 1.16 $
+ * @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 colors.
+ * @var array
+ * @access private
+ */
+ var $_colors = array(
+ PEAR_LOG_EMERG => 'red',
+ PEAR_LOG_ALERT => 'orange',
+ PEAR_LOG_CRIT => 'yellow',
+ PEAR_LOG_ERR => 'green',
+ PEAR_LOG_WARNING => 'blue',
+ PEAR_LOG_NOTICE => 'indigo',
+ PEAR_LOG_INFO => 'violet',
+ PEAR_LOG_DEBUG => '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 = $name;
+ $this->_ident = $ident;
+ $this->_mask = Log::UPTO($level);
+
+ if (isset($conf['title'])) {
+ $this->_title = $conf['title'];
+ }
+ if (isset($conf['colors']) && is_array($conf['colors'])) {
+ $this->_colors = $conf['colors'];
+ }
+
+ 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;
+
+ if (!empty($this->_ident)) {
+ $identHeader = "$win.document.writeln('<th>Ident</th>')";
+ } else {
+ $identHeader = '';
+ }
+
+ echo <<< END_OF_SCRIPT
+<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('</style>');
+$win.document.writeln('</head>');
+$win.document.writeln('<body>');
+$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>
+END_OF_SCRIPT;
+ $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->_opened = false;
+ }
+
+ return ($this->_opened === false);
+ }
+
+ /**
+ * Writes a single line of text to the output window.
+ *
+ * @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 false;
+ }
+
+ /* Drain the buffer to the output window. */
+ $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();
+ }
+
+ /**
+ * 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);
+
+ list($usec, $sec) = explode(' ', microtime());
+
+ /* Build the output line that contains the log entry row. */
+ $line = '<tr align="left" valign="top">';
+ $line .= sprintf('<td>%s.%s</td>',
+ strftime('%T', $sec), substr($usec, 2, 2));
+ if (!empty($this->_ident)) {
+ $line .= '<td>' . $this->_ident . '</td>';
+ }
+ $line .= '<td>' . ucfirst($this->priorityToString($priority)) . '</td>';
+ $line .= sprintf('<td style="color: %s">%s</td>',
+ $this->_colors[$priority],
+ preg_replace('/\r\n|\n|\r/', '<br />', $message));
+ $line .= '</tr>';
+
+ $this->_writeln($line);
+
+ $this->_announce(array('priority' => $priority, 'message' => $message));
+
+ return true;
+ }
+}
+
+?>