. * * Consult LICENSE file for details ************************************************/ class ZLog { static private $devid = ''; static private $user = ''; static private $authUser = false; static private $pidstr; static private $wbxmlDebug = ''; static private $lastLogs = array(); static private $userLog = false; static private $unAuthCache = array(); static private $syslogEnabled = false; /** * Initializes the logging * * @access public * @return boolean */ static public function Initialize() { global $specialLogUsers; if (defined('LOG_SYSLOG_ENABLED') && LOG_SYSLOG_ENABLED) { self::$syslogEnabled = true; ZSyslog::Initialize(); } // define some constants for the logging if (!defined('LOGUSERLEVEL')) define('LOGUSERLEVEL', LOGLEVEL_OFF); if (!defined('LOGLEVEL')) define('LOGLEVEL', LOGLEVEL_OFF); list($user,) = Utils::SplitDomainUser(strtolower(Request::GetGETUser())); self::$userLog = in_array($user, $specialLogUsers); if (!defined('WBXML_DEBUG') && $user) { // define the WBXML_DEBUG mode on user basis depending on the configurations if (LOGLEVEL >= LOGLEVEL_WBXML || (LOGUSERLEVEL >= LOGLEVEL_WBXML && self::$userLog)) define('WBXML_DEBUG', true); else define('WBXML_DEBUG', false); } if ($user) self::$user = '['. $user .'] '; else self::$user = ''; // log the device id if the global loglevel is set to log devid or the user is in and has the right log level if (Request::GetDeviceID() != "" && (LOGLEVEL >= LOGLEVEL_DEVICEID || (LOGUSERLEVEL >= LOGLEVEL_DEVICEID && self::$userLog))) self::$devid = '['. Request::GetDeviceID() .'] '; else self::$devid = ''; return true; } /** * Writes a log line * * @param int $loglevel one of the defined LOGLEVELS * @param string $message * @param boolean $truncate indicate if the message should be truncated, default true * * @access public * @return */ static public function Write($loglevel, $message, $truncate = true) { // truncate messages longer than 10 KB $messagesize = strlen($message); if ($truncate && $messagesize > 10240) $message = substr($message, 0, 10240) . sprintf(" ", $messagesize); self::$lastLogs[$loglevel] = $message; $data = self::buildLogString($loglevel) . $message . "\n"; if ($loglevel <= LOGLEVEL) { self::writeToLog($loglevel, $data, LOGFILE); } // should we write this into the user log? if ($loglevel <= LOGUSERLEVEL && self::$userLog) { // padd level for better reading $data = str_replace(self::getLogLevelString($loglevel), self::getLogLevelString($loglevel,true), $data); // is the user authenticated? if (self::logToUserFile()) { // something was logged before the user was authenticated, write this to the log if (!empty(self::$unAuthCache)) { self::writeToLog($loglevel, implode('', self::$unAuthCache), LOGFILEDIR . self::logToUserFile() . ".log"); self::$unAuthCache = array(); } // only use plain old a-z characters for the generic log file self::writeToLog($loglevel, $data, LOGFILEDIR . self::logToUserFile() . ".log"); } // the user is not authenticated yet, we save the log into memory for now else { self::$unAuthCache[] = $data; } } if (($loglevel & LOGLEVEL_FATAL) || ($loglevel & LOGLEVEL_ERROR)) { self::writeToLog($loglevel, $data, LOGERRORFILE); } if ($loglevel & LOGLEVEL_WBXMLSTACK) { self::$wbxmlDebug .= $message. "\n"; } } /** * Returns logged information about the WBXML stack * * @access public * @return string */ static public function GetWBXMLDebugInfo() { return trim(self::$wbxmlDebug); } /** * Returns the last message logged for a log level * * @param int $loglevel one of the defined LOGLEVELS * * @access public * @return string/false returns false if there was no message logged in that level */ static public function GetLastMessage($loglevel) { return (isset(self::$lastLogs[$loglevel]))?self::$lastLogs[$loglevel]:false; } /**---------------------------------------------------------------------------------------------------------- * private log stuff */ /** * Returns the filename logs for a WBXML debug log user should be saved to * * @access private * @return string */ static private function logToUserFile() { global $specialLogUsers; if (self::$authUser === false) { if (RequestProcessor::isUserAuthenticated()) { $authuser = Request::GetAuthUser(); if ($authuser && in_array($authuser, $specialLogUsers)) self::$authUser = preg_replace('/[^a-z0-9]/', '_', strtolower($authuser)); } } return self::$authUser; } /** * Returns the string to be logged * * @access private * @return string */ static private function buildLogString($loglevel) { if (!isset(self::$pidstr)) self::$pidstr = '[' . str_pad(@getmypid(),5," ",STR_PAD_LEFT) . '] '; if (!isset(self::$user)) self::$user = ''; if (!isset(self::$devid)) self::$devid = ''; if (self::$syslogEnabled) return self::$pidstr . self::getLogLevelString($loglevel, (LOGLEVEL > LOGLEVEL_INFO)) . " " . self::$user . self::$devid; else return Utils::GetFormattedTime() . " " . self::$pidstr . self::getLogLevelString($loglevel, (LOGLEVEL > LOGLEVEL_INFO)) . " " . self::$user . self::$devid; } /** * Returns the string representation of the LOGLEVEL. * String can be padded * * @param int $loglevel one of the LOGLEVELs * @param boolean $pad * * @access private * @return string */ static private function getLogLevelString($loglevel, $pad = false) { if ($pad) $s = " "; else $s = ""; switch($loglevel) { case LOGLEVEL_OFF: return ""; break; case LOGLEVEL_FATAL: return "[FATAL]"; break; case LOGLEVEL_ERROR: return "[ERROR]"; break; case LOGLEVEL_WARN: return "[".$s."WARN]"; break; case LOGLEVEL_INFO: return "[".$s."INFO]"; break; case LOGLEVEL_DEBUG: return "[DEBUG]"; break; case LOGLEVEL_WBXML: return "[WBXML]"; break; case LOGLEVEL_DEVICEID: return "[DEVICEID]"; break; case LOGLEVEL_WBXMLSTACK: return "[WBXMLSTACK]"; break; } } /** * Write the message to the log facility. * * @param int $loglevel * @param string $data * @param string $logfile * * @access private * @return void */ static private function writeToLog($loglevel, $data, $logfile = null) { if (self::$syslogEnabled) { if (ZSyslog::send($loglevel, $data) === false) { error_log("Unable to send to syslog"); error_log($data); } } else { if (@file_put_contents($logfile, $data, FILE_APPEND) === false) { error_log(sprintf("Unable to write in %s", $logfile)); error_log($data); } } } }