Source for file LogUtil.class.php
Documentation is available at LogUtil.class.php
* Zikula Application Framework
* @copyright Robert Gasch
* @link http://www.zikula.org
* @version $Id: LogUtil.class.php 24342 2008-06-06 12:03:14Z markwest $
* @license GNU/GPL - http://www.gnu.org/copyleft/gpl.html
* @author Robert Gasch rgasch@gmail.com
* Returns an array of status messages
* @param $override whether to override status messages with error messages
* @return array of messages
if (!empty($errs) && $override) {
* Returns a string of the available status messages, separated by the given delimeter
* @param $delimeter The string to use as the delimeter between the array of messages
* @param $override whether to override status messages with error messages
* @return string the generated error message
return implode ($delimeter, $msgs);
* Get an array of error messages
* @return array of messages
* Get an error message text
* @param $delimeter The string to use as the delimeter between the array of messages
* @return string the generated error message
return implode ($delimeter, $msgs);
return (bool) !empty($msgs);
* Set an error message text
* @param $message string the error message
return pn_exit ('Empty message received ...');
* Register a failed authid check. This method calls registerError and
* then redirects back to the specified URL.
* @param $url The URL to redirect to (optional) (default=null)
* Register a failed permission check. This method calls registerError and
* then logs the failed permission check so that it can be analyzed later.
* @param $url The URL to redirect to (optional) (default=null)
static $strLevels = array();
$strLevels[ACCESS_INVALID] = 'INVALID';
$strLevels[ACCESS_NONE] = 'NONE';
$strLevels[ACCESS_OVERVIEW] = 'OVERVIEW';
$strLevels[ACCESS_READ] = 'READ';
$strLevels[ACCESS_COMMENT] = 'COMMENT';
$strLevels[ACCESS_MODERATE] = 'MODERATE';
$strLevels[ACCESS_EDIT] = 'EDIT';
$strLevels[ACCESS_ADD] = 'ADD';
$strLevels[ACCESS_DELETE] = 'DELETE';
$strLevels[ACCESS_ADMIN] = 'ADMIN';
$obj['component'] = 'PERMISSION';
$obj['sec_component'] = $PNRuntime['security']['last_failed_check']['component'];
$obj['sec_instance'] = $PNRuntime['security']['last_failed_check']['instance'];
$obj['sec_permission'] = $strLevels[$PNRuntime['security']['last_failed_check']['level']];
* Set an error message text. Also adds method, file and line where the error occured
* @param $message string the error message
* @param $type type of error (numeric and corresponding to a HTTP status code) (optional) (default=null)
* @param $url the url to redirect to (optional) (default=null)
return pn_exit ('Empty message received ...');
$cf1 = isset ($bt[1]) ? $bt[1] : array('function' => '', 'args' => '');
$func = !empty($cf1['function']) ? '['. $cf1['function']. ']' : '';
$msg = pnML('_ERROR_ADMIN', array('message' => $message, 'func' => $func, 'line' => $line, 'file' => $file), true);
if (defined('_PNINSTALLVER') && $PNConfig['System']['development']) {
// no html encoding should be used here - not htmlentities nor DataUtil methods
// as the message *may* contain pre-formatted html
// note for bug #4439 - we dont want to pass messages through HTML tag
// filter, only ensure the HTML is valid since this is system generated
// check if we've got an error type
// check if we want to redirect
// since we're registering an error, it makes sense to return false here.
// This allows the calling code to just return the result of pnRegisterError
// if it wishes to return 'false' (which is what ususally happens).
* Log the given messge under the given level
* @param msg The message to log
* @param level The log to log this message under
function log ($msg, $level= 'DEFAULT')
$haveConfig = count($PNConfig['Log']) > 0;
$logLevels = $PNConfig['Log']['log_levels'];
$showErrors = $PNConfig['Log']['log_show_errors'];
$logUser = $PNConfig['Log']['log_user'];
if ($logUser && $logUser != $suid) {
print "<p><strong>Logging configuration can't be loaded .... logging is disabled</strong></p>";
elseif ($level == "ALL" && $showErrors == true) {
print "<p><strong>You should not add an event log with log_level 'ALL'</strong></p>";
* Generate the filename of todays log file
* @returns the generated filename
$logfileSpec = $PNConfig['Log']['log_file'];
$dateFormat = $PNConfig['Log']['log_file_date_format'];
if ($level && isset ($PNConfig['Log']['log_level_files'][$level]) && $PNConfig['Log']['log_level_files'][$level]) {
$logfileSpec = $PNConfig['Log']['log_level_files'][$level];
if (strpos($logfileSpec, "%s") !== false)
if ($PNConfig['Log']['log_file_uid'])
$perc = strpos ($logfileSpec, '%s');
$start = substr ($logfileSpec, 0, $perc+ 2);
$end = substr ($logfileSpec, $perc+ 2);
$logfileSpec = $start . '-%d' . $end;
$logfile = sprintf($logfileSpec, date($dateFormat), $uid);
* Write the error message to the log file.
* Prints log file full error (if $log_show_errors is true)
* @param msg The message to log
* @param level The log level to log this message under
* @returns Logging file write error (file or directory unwritable) (if $log_show_errors is true)
function _write ($msg, $level= 'DEFAULT', $securityInfo= null)
$logEnabled = $PNConfig['Log']['log_enabled'];
$logShowErr = $PNConfig['Log']['log_show_errors'];
$logDateFmt = $PNConfig['Log']['log_date_format'];
$logDest = $PNConfig['Log']['log_dest'];
if ($level && isset ($PNConfig['Log']['log_level_dest'][$level]) && $PNConfig['Log']['log_level_dest'][$level]) {
$logDest = $PNConfig['Log']['log_level_dest'][$level];
// permission to be logged to DB or FILE
if ($level == 'PERMISSION' && ($logDest!= 'DB' && $logDest!= 'FILE')) {
if ($logDest == 'FILE') {
$title = date($logDateFmt) . ", level=$level, uid=$uid, module=$module, type=$type, func=$func\n";
$title .= "++ sec_component=$securityInfo[sec_component], sec_instance=$securityInfo[sec_instance], sec_permission=$securityInfo[sec_permission]\n";
$logline = '+ ' . $title;
$logfile = LogUtil::getLogFileName($level);
$logfileOK = LogUtil::_checkLogFile($logfile, $level, $reason);
$fp = fopen($logfile, 'a');
if ($reason == 'NOWRITE') {
print "<p><strong>Logging Disabled. Log file ($logfile) unwritable.</strong></p>";
elseif ($reason == 'TOOBIG') {
print "<p><strong>Log file ($logfile) is full.</strong></p>";
elseif ($logDest == 'PRINT') {
print '<div class="pn-sub" style="text-align:left;">' . $logline . '</div>';
elseif ($logDest == 'MAIL') {
$title = date($logDateFmt) . ", level=$level, uid=$uid\n";
$args['fromname'] = 'Zikula ' . pnConfigGetVar('slogan', 'Site Slogan');
$args['fromaddress'] = $adminmail;
$args['toname'] = 'Site Administrator';
$args['toaddress'] = $adminmail;
$args['subject'] = "Log Message: level=$level, uid=$uid";
$args['body'] = $logline;
$rc = pnModFunc ('Mailer', 'userapi', 'sendmessage', $args);
elseif ($logDest == 'DB') {
$obj['date'] = date($logDateFmt);
$obj['component'] = $level;
$obj['module'] = $module;
$obj['function'] = $func;
if ($securityInfo && is_array($securityInfo)) {
print '<div class="pn-sub" style="text-align:left;">';
print 'Failed to insert log record into log_event table<br />';
print 'Failed to load logging table definition from SecurityCenter module<br />';
print "Unknown log destination [$logDest] ... ";
* Check the log file is writable and not full.
* returns unwritable The file or directory cannot be written to
* returns toobig The log file size is bigger than $log_length in logging.conf.php.
* @returns boolean Whether or not the file is ready for writing
$logSize = $PNConfig['Log']['log_maxsize'];
$size = filesize($logfile) / 1024 / 1024;
} elseif ($logSize && $size > $logSize) {
SessionUtil::setVar('_PNStatusMsg', "Logfile [$logfile] size [$size] exceeds [$logSize] ...");
* Cleans up unneeded old log files
$log_keep_days = $PNConfig['Log']['log_keep_days'];
if (!$log_keep_days) $log_keep_days = 30; // temporary default value for migration
$log_keep_seconds = $log_keep_days * $oneday;
if (time() - $lastcheck > $oneday) {
$logfilepath = $PNConfig['Log']['log_dir'];
foreach($logfiles as $logfile) {
if ($currenttime - filemtime($logfile) > $log_keep_seconds) {
|