From ed0be8ec473eb746658ba5a93bc1166574979d25 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Fri, 7 Feb 2014 13:40:50 +0100 Subject: [PATCH] [UPGRADE] Upgraded KLogger Library * [REMOVED] Logfile name not possible right now * [ADDED] All loglevels supplied by KLogger --- public/include/classes/logger.class.php | 49 +- public/include/config/security.inc.dist.php | 12 +- public/include/lib/KLogger.php | 550 +++++++++++++++----- 3 files changed, 444 insertions(+), 167 deletions(-) mode change 100755 => 100644 public/include/lib/KLogger.php diff --git a/public/include/classes/logger.class.php b/public/include/classes/logger.class.php index 35624a44..31a172cf 100644 --- a/public/include/classes/logger.class.php +++ b/public/include/classes/logger.class.php @@ -5,30 +5,49 @@ class Logger { private $logging = false; public function __construct($config) { if ($config['logging']['enabled'] && $config['logging']['level'] > 0) { - $this->KLogger = new KLogger($config['logging']['path']."/".$config['logging']['file'], $config['logging']['level']); + $this->KLogger = KLogger::instance($config['logging']['path'], $config['logging']['level']); $this->logging = true; } } - public function log($type, $message) { + public function log($strType, $strMessage) { // Logmask, we add some infos into the KLogger $strMask = "[ %12s ] [ %8s | %-8s ] : %s"; $strIPAddress = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'unknown'; $strPage = isset($_REQUEST['page']) ? $_REQUEST['page'] : 'none'; $strAction = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'none'; + $strMessage = sprintf($strMask, $strIPAddress, $strPage, $strAction, $strMessage); if ($this->logging) { - switch ($type) { - case 'info': - $this->KLogger->LogInfo(sprintf($strMask, $strIPAddress, $strPage, $strAction, $message)); - break; - case 'warn': - $this->KLogger->LogWarn(sprintf($strMask, $strIPAddress, $strPage, $strAction, $message)); - break; - case 'error': - $this->KLogger->LogError(sprintf($strMask, $strIPAddress, $strPage, $strAction, $message)); - break; - case 'fatal': - $this->KLogger->LogFatal(sprintf($strMask, $strIPAddress, $strPage, $strAction, $message)); - break; + switch ($strType) { + case 'emerg': + $this->KLogger->LogEmerg($strMessage); + break; + case 'alert': + $this->KLogger->LogAlert($strMessage); + break; + case 'crit': + $this->KLogger->LogCrit($strMessage); + break; + case 'error': + $this->KLogger->LogError($strMessage); + break; + case 'warn': + $this->KLogger->LogWarn($strMessage); + break; + case 'notice': + $this->KLogger->LogNotice($strMessage); + break; + case 'info': + $this->KLogger->LogInfo($strMessage); + break; + case 'fatal': + $this->KLogger->LogFatal($strMessage); + break; + case 'debug': + $this->KLogger->LogDebug($strMessage); + break; + case '': + $this->KLogger->LogFatal($strMessage); + break; } return true; } else { diff --git a/public/include/config/security.inc.dist.php b/public/include/config/security.inc.dist.php index 28607523..2ff1a188 100644 --- a/public/include/config/security.inc.dist.php +++ b/public/include/config/security.inc.dist.php @@ -12,17 +12,13 @@ $config['protect_session_state'] = false; /** * Logging - * 0 = Nothing - * 1 = Everything - * 2 = INFO only - * 3 = + WARN - * 4 = + ERROR - * 5 = + FATAL + * Emergency = 0, Alert = 1, Critical = 2 + * Error = 3, Warn = 4, Notice = 5 + * Info = 6, Debug = 7, Nothing = 8 */ $config['logging']['enabled'] = true; -$config['logging']['level'] = 5; +$config['logging']['level'] = 6; $config['logging']['path'] = realpath(BASEPATH.'../logs'); -$config['logging']['file'] = date('Y-m-d').'.security.log'; /** * Memcache Rate Limiting diff --git a/public/include/lib/KLogger.php b/public/include/lib/KLogger.php old mode 100755 new mode 100644 index 9f53788e..6766df35 --- a/public/include/lib/KLogger.php +++ b/public/include/lib/KLogger.php @@ -1,148 +1,410 @@ - * Date : July 26, 2008 - * Comments : Originally written for use with wpSearch - * Website : http://codefury.net - * Version : 1.0 - * - * Usage: - * $log = new KLogger ( "log.txt" , KLogger::INFO ); - * $log->LogInfo("Returned a million search results"); //Prints to the log file - * $log->LogFATAL("Oh dear."); //Prints to the log file - * $log->LogDebug("x = 5"); //Prints nothing due to priority setting - */ - - class KLogger - { - - const DEBUG = 1; // Most Verbose - const INFO = 2; // ... - const WARN = 3; // ... - const ERROR = 4; // ... - const FATAL = 5; // Least Verbose - const OFF = 6; // Nothing at all. - - const LOG_OPEN = 1; - const OPEN_FAILED = 2; - const LOG_CLOSED = 3; - - /* Public members: Not so much of an example of encapsulation, but that's okay. */ - public $Log_Status = KLogger::LOG_CLOSED; - public $DateFormat = "Y-m-d G:i:s"; - public $MessageQueue; - - private $log_file; - private $priority = KLogger::INFO; - - private $file_handle; - - public function __construct( $filepath , $priority ) - { - if ( $priority == KLogger::OFF ) return; - - $this->log_file = $filepath; - $this->MessageQueue = array(); - $this->priority = $priority; - - if ( file_exists( $this->log_file ) ) - { - if ( !is_writable($this->log_file) ) - { - $this->Log_Status = KLogger::OPEN_FAILED; - $this->MessageQueue[] = "The file exists, but could not be opened for writing. Check that appropriate permissions have been set."; - return; - } - } - - if ( $this->file_handle = fopen( $this->log_file , "a" ) ) - { - $this->Log_Status = KLogger::LOG_OPEN; - $this->MessageQueue[] = "The log file was opened successfully."; - } - else - { - $this->Log_Status = KLogger::OPEN_FAILED; - $this->MessageQueue[] = "The file could not be opened. Check permissions."; - } - - return; - } - - public function __destruct() - { - if ( $this->file_handle ) - fclose( $this->file_handle ); - } - - public function LogInfo($line) - { - $this->Log( $line , KLogger::INFO ); - } - - public function LogDebug($line) - { - $this->Log( $line , KLogger::DEBUG ); - } - - public function LogWarn($line) - { - $this->Log( $line , KLogger::WARN ); - } - - public function LogError($line) - { - $this->Log( $line , KLogger::ERROR ); - } - public function LogFatal($line) - { - $this->Log( $line , KLogger::FATAL ); - } - - public function Log($line, $priority) - { - if ( $this->priority <= $priority ) - { - $status = $this->getTimeLine( $priority ); - $this->WriteFreeFormLine ( "$status $line \n" ); - } - } - - public function WriteFreeFormLine( $line ) - { - if ( $this->Log_Status == KLogger::LOG_OPEN && $this->priority != KLogger::OFF ) - { - if (fwrite( $this->file_handle , $line ) === false) { - $this->MessageQueue[] = "The file could not be written to. Check that appropriate permissions have been set."; - } - } - } - - private function getTimeLine( $level ) - { - $time = date( $this->DateFormat ); - - switch( $level ) - { - case KLogger::INFO: - return "$time - INFO -->"; - case KLogger::WARN: - return "$time - WARN -->"; - case KLogger::DEBUG: - return "$time - DEBUG -->"; - case KLogger::ERROR: - return "$time - ERROR -->"; - case KLogger::FATAL: - return "$time - FATAL -->"; - default: - return "$time - LOG -->"; - } - } - - } +/** + * Finally, a light, permissions-checking logging class. + * + * Originally written for use with wpSearch + * + * Usage: + * $log = new KLogger('/var/log/', KLogger::INFO); + * $log->logInfo('Returned a million search results'); //Prints to the log file + * $log->logFatal('Oh dear.'); //Prints to the log file + * $log->logDebug('x = 5'); //Prints nothing due to current severity threshhold + * + * @author Kenny Katzgrau + * @since July 26, 2008 — Last update July 1, 2012 + * @link http://codefury.net + * @version 0.2.0 + */ +/** + * Class documentation + */ +class KLogger +{ + /** + * Error severity, from low to high. From BSD syslog RFC, secion 4.1.1 + * @link http://www.faqs.org/rfcs/rfc3164.html + */ + const EMERG = 0; // Emergency: system is unusable + const ALERT = 1; // Alert: action must be taken immediately + const CRIT = 2; // Critical: critical conditions + const ERR = 3; // Error: error conditions + const WARN = 4; // Warning: warning conditions + const NOTICE = 5; // Notice: normal but significant condition + const INFO = 6; // Informational: informational messages + const DEBUG = 7; // Debug: debug messages -?> \ No newline at end of file + //custom logging level + /** + * Log nothing at all + */ + const OFF = 8; + /** + * Alias for CRIT + * @deprecated + */ + const FATAL = 2; + + /** + * Internal status codes + */ + const STATUS_LOG_OPEN = 1; + const STATUS_OPEN_FAILED = 2; + const STATUS_LOG_CLOSED = 3; + + /** + * We need a default argument value in order to add the ability to easily + * print out objects etc. But we can't use NULL, 0, FALSE, etc, because those + * are often the values the developers will test for. So we'll make one up. + */ + const NO_ARGUMENTS = 'KLogger::NO_ARGUMENTS'; + + /** + * Current status of the log file + * @var integer + */ + private $_logStatus = self::STATUS_LOG_CLOSED; + /** + * Holds messages generated by the class + * @var array + */ + private $_messageQueue = array(); + /** + * Path to the log file + * @var string + */ + private $_logFilePath = null; + /** + * Current minimum logging threshold + * @var integer + */ + private $_severityThreshold = self::INFO; + /** + * This holds the file handle for this instance's log file + * @var resource + */ + private $_fileHandle = null; + + /** + * Standard messages produced by the class. Can be modified for il8n + * @var array + */ + private $_messages = array( + //'writefail' => 'The file exists, but could not be opened for writing. Check that appropriate permissions have been set.', + 'writefail' => 'The file could not be written to. Check that appropriate permissions have been set.', + 'opensuccess' => 'The log file was opened successfully.', + 'openfail' => 'The file could not be opened. Check permissions.', + ); + + /** + * Default severity of log messages, if not specified + * @var integer + */ + private static $_defaultSeverity = self::DEBUG; + /** + * Valid PHP date() format string for log timestamps + * @var string + */ + private static $_dateFormat = 'Y-m-d G:i:s'; + /** + * Octal notation for default permissions of the log file + * @var integer + */ + private static $_defaultPermissions = 0777; + /** + * Array of KLogger instances, part of Singleton pattern + * @var array + */ + private static $instances = array(); + + /** + * Partially implements the Singleton pattern. Each $logDirectory gets one + * instance. + * + * @param string $logDirectory File path to the logging directory + * @param integer $severity One of the pre-defined severity constants + * @return KLogger + */ + public static function instance($logDirectory = false, $severity = false) + { + if ($severity === false) { + $severity = self::$_defaultSeverity; + } + + if ($logDirectory === false) { + if (count(self::$instances) > 0) { + return current(self::$instances); + } else { + $logDirectory = dirname(__FILE__); + } + } + + if (in_array($logDirectory, self::$instances)) { + return self::$instances[$logDirectory]; + } + + self::$instances[$logDirectory] = new self($logDirectory, $severity); + + return self::$instances[$logDirectory]; + } + + /** + * Class constructor + * + * @param string $logDirectory File path to the logging directory + * @param integer $severity One of the pre-defined severity constants + * @return void + */ + public function __construct($logDirectory, $severity) + { + $logDirectory = rtrim($logDirectory, '\\/'); + + if ($severity === self::OFF) { + return; + } + + $this->_logFilePath = $logDirectory + . DIRECTORY_SEPARATOR + . 'log_' + . date('Y-m-d') + . '.txt'; + + $this->_severityThreshold = $severity; + if (!file_exists($logDirectory)) { + mkdir($logDirectory, self::$_defaultPermissions, true); + } + + if (file_exists($this->_logFilePath) && !is_writable($this->_logFilePath)) { + $this->_logStatus = self::STATUS_OPEN_FAILED; + $this->_messageQueue[] = $this->_messages['writefail']; + return; + } + + if (($this->_fileHandle = fopen($this->_logFilePath, 'a'))) { + $this->_logStatus = self::STATUS_LOG_OPEN; + $this->_messageQueue[] = $this->_messages['opensuccess']; + } else { + $this->_logStatus = self::STATUS_OPEN_FAILED; + $this->_messageQueue[] = $this->_messages['openfail']; + } + } + + /** + * Class destructor + */ + public function __destruct() + { + if ($this->_fileHandle) { + fclose($this->_fileHandle); + } + } + /** + * Writes a $line to the log with a severity level of DEBUG + * + * @param string $line Information to log + * @return void + */ + public function logDebug($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::DEBUG); + } + + /** + * Returns (and removes) the last message from the queue. + * @return string + */ + public function getMessage() + { + return array_pop($this->_messageQueue); + } + + /** + * Returns the entire message queue (leaving it intact) + * @return array + */ + public function getMessages() + { + return $this->_messageQueue; + } + + /** + * Empties the message queue + * @return void + */ + public function clearMessages() + { + $this->_messageQueue = array(); + } + + /** + * Sets the date format used by all instances of KLogger + * + * @param string $dateFormat Valid format string for date() + */ + public static function setDateFormat($dateFormat) + { + self::$_dateFormat = $dateFormat; + } + + /** + * Writes a $line to the log with a severity level of INFO. Any information + * can be used here, or it could be used with E_STRICT errors + * + * @param string $line Information to log + * @return void + */ + public function logInfo($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::INFO, $args); + } + + /** + * Writes a $line to the log with a severity level of NOTICE. Generally + * corresponds to E_STRICT, E_NOTICE, or E_USER_NOTICE errors + * + * @param string $line Information to log + * @return void + */ + public function logNotice($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::NOTICE, $args); + } + + /** + * Writes a $line to the log with a severity level of WARN. Generally + * corresponds to E_WARNING, E_USER_WARNING, E_CORE_WARNING, or + * E_COMPILE_WARNING + * + * @param string $line Information to log + * @return void + */ + public function logWarn($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::WARN, $args); + } + + /** + * Writes a $line to the log with a severity level of ERR. Most likely used + * with E_RECOVERABLE_ERROR + * + * @param string $line Information to log + * @return void + */ + public function logError($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::ERR, $args); + } + + /** + * Writes a $line to the log with a severity level of FATAL. Generally + * corresponds to E_ERROR, E_USER_ERROR, E_CORE_ERROR, or E_COMPILE_ERROR + * + * @param string $line Information to log + * @return void + * @deprecated Use logCrit + */ + public function logFatal($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::FATAL, $args); + } + + /** + * Writes a $line to the log with a severity level of ALERT. + * + * @param string $line Information to log + * @return void + */ + public function logAlert($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::ALERT, $args); + } + + /** + * Writes a $line to the log with a severity level of CRIT. + * + * @param string $line Information to log + * @return void + */ + public function logCrit($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::CRIT, $args); + } + + /** + * Writes a $line to the log with a severity level of EMERG. + * + * @param string $line Information to log + * @return void + */ + public function logEmerg($line, $args = self::NO_ARGUMENTS) + { + $this->log($line, self::EMERG, $args); + } + + /** + * Writes a $line to the log with the given severity + * + * @param string $line Text to add to the log + * @param integer $severity Severity level of log message (use constants) + */ + public function log($line, $severity, $args = self::NO_ARGUMENTS) + { + if ($this->_severityThreshold >= $severity) { + $status = $this->_getTimeLine($severity); + + $line = "$status $line"; + + if($args !== self::NO_ARGUMENTS) { + /* Print the passed object value */ + $line = $line . '; ' . var_export($args, true); + } + + $this->writeFreeFormLine($line . PHP_EOL); + } + } + + /** + * Writes a line to the log without prepending a status or timestamp + * + * @param string $line Line to write to the log + * @return void + */ + public function writeFreeFormLine($line) + { + if ($this->_logStatus == self::STATUS_LOG_OPEN + && $this->_severityThreshold != self::OFF) { + if (fwrite($this->_fileHandle, $line) === false) { + $this->_messageQueue[] = $this->_messages['writefail']; + } + } + } + + private function _getTimeLine($level) + { + $time = date(self::$_dateFormat); + + switch ($level) { + case self::EMERG: + return "$time - EMERG -->"; + case self::ALERT: + return "$time - ALERT -->"; + case self::CRIT: + return "$time - CRIT -->"; + case self::FATAL: # FATAL is an alias of CRIT + return "$time - FATAL -->"; + case self::NOTICE: + return "$time - NOTICE -->"; + case self::INFO: + return "$time - INFO -->"; + case self::WARN: + return "$time - WARN -->"; + case self::DEBUG: + return "$time - DEBUG -->"; + case self::ERR: + return "$time - ERROR -->"; + default: + return "$time - LOG -->"; + } + } +}