1
0
mirror of https://github.com/e107inc/e107.git synced 2025-08-08 07:36:32 +02:00

Update routine uses new combined admin logging and messaging API

This commit is contained in:
e107steved
2010-04-20 21:35:20 +00:00
parent 321adb9dc0
commit ee3e6ed9d9
4 changed files with 1629 additions and 1520 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
<?php <?php
/* /*
* e107 website system * e107 website system
* *
* Copyright (C) 2008-2010 e107 Inc (e107.org) * Copyright (C) 2008-2010 e107 Inc (e107.org)
@@ -12,413 +12,449 @@
* $Id$ * $Id$
* *
*/ */
if (!defined('e107_INIT')) if (!defined('e107_INIT'))
{ {
exit; exit;
} }
define('LOG_MESSAGE_NODISPLAY', 'nodisplay'); define('LOG_MESSAGE_NODISPLAY', 'nodisplay');
/** /**
* Admin logging class. * Admin logging class.
* *
* @package e107 * @package e107
* @subpackage e107_handlers * @subpackage e107_handlers
* @version $Id$; * @version $Id$;
* @author e107steved * @author e107steved
*/ */
class e_admin_log class e_admin_log
{ {
/** /**
* Contains default class options, plus any that are overidden by the constructor * Contains default class options, plus any that are overidden by the constructor
* *
* @var array * @var array
*/ */
protected $_options = array('log_level'=>2, 'backtrace'=>false, ); protected $_options = array('log_level'=>2, 'backtrace'=>false, );
public $rldb = NULL; // Database used by logging routine
protected $rldb = NULL; // Database used by logging routine
/** /**
* Log messages * Log messages
* @var array * @var array
*/ */
protected $_messages; protected $_messages;
/** /**
* Constructor. Sets up constants and overwrites default options where set. * Constructor. Sets up constants and overwrites default options where set.
* *
* @param array $options * @param array $options
* @return e_admin_log * @return none
*/ */
function __construct($options = array()) public function __construct($options = array())
{ {
foreach ($options as $key=>$val) foreach ($options as $key=>$val)
{ {
$this->_options[$key] = $val; $this->_options[$key] = $val;
} }
define("E_LOG_INFORMATIVE", 0); // Minimal Log Level, including really minor stuff define("E_LOG_INFORMATIVE", 0); // Minimal Log Level, including really minor stuff
define("E_LOG_NOTICE", 1); // More important than informative, but less important than notice define("E_LOG_NOTICE", 1); // More important than informative, but less important than notice
define("E_LOG_WARNING", 2); // Not anything serious, but important information define("E_LOG_WARNING", 2); // Not anything serious, but important information
define("E_LOG_FATAL", 3); // An event so bad your site ceased execution. define("E_LOG_FATAL", 3); // An event so bad your site ceased execution.
define("E_LOG_PLUGIN", 4); // Plugin information define("E_LOG_PLUGIN", 4); // Plugin information
// Logging actions // Logging actions
define("LOG_TO_ADMIN", 1); define("LOG_TO_ADMIN", 1);
define("LOG_TO_AUDIT", 2); define("LOG_TO_AUDIT", 2);
define("LOG_TO_ROLLING", 4); define("LOG_TO_ROLLING", 4);
// User audit logging (intentionally start at 10 - stick to 2 digits) // User audit logging (intentionally start at 10 - stick to 2 digits)
// The last two digits must match that for the corresponding log message // The last two digits must match that for the corresponding log message
define('USER_AUDIT_ADMIN', 10); // User data changed by admin define('USER_AUDIT_ADMIN', 10); // User data changed by admin
define('USER_AUDIT_SIGNUP', 11); // User signed up define('USER_AUDIT_SIGNUP', 11); // User signed up
define('USER_AUDIT_EMAILACK', 12); // User responded to registration email define('USER_AUDIT_EMAILACK', 12); // User responded to registration email
define('USER_AUDIT_LOGIN', 13); // User logged in define('USER_AUDIT_LOGIN', 13); // User logged in
define('USER_AUDIT_LOGOUT', 14); // User logged out define('USER_AUDIT_LOGOUT', 14); // User logged out
define('USER_AUDIT_NEW_DN', 15); // User changed display name define('USER_AUDIT_NEW_DN', 15); // User changed display name
define('USER_AUDIT_NEW_PW', 16); // User changed password define('USER_AUDIT_NEW_PW', 16); // User changed password
define('USER_AUDIT_NEW_EML', 17); // User changed email define('USER_AUDIT_NEW_EML', 17); // User changed email
define('USER_AUDIT_PW_RES', 18); // Password reset/resent activation email define('USER_AUDIT_PW_RES', 18); // Password reset/resent activation email
define('USER_AUDIT_NEW_SET', 19); // User changed other settings define('USER_AUDIT_NEW_SET', 19); // User changed other settings
define('USER_AUDIT_ADD_ADMIN', 20); // User added by admin define('USER_AUDIT_ADD_ADMIN', 20); // User added by admin
define('USER_AUDIT_MAIL_BOUNCE', 21); // User mail bounce define('USER_AUDIT_MAIL_BOUNCE', 21); // User mail bounce
define('USER_AUDIT_BANNED', 22); // User banned define('USER_AUDIT_BANNED', 22); // User banned
define('USER_AUDIT_BOUNCE_RESET', 23); // User bounce reset define('USER_AUDIT_BOUNCE_RESET', 23); // User bounce reset
define('USER_AUDIT_TEMP_ACCOUNT', 24); // User temporary account define('USER_AUDIT_TEMP_ACCOUNT', 24); // User temporary account
// Init E_MESSAGE_* constants if not already done // Init E_MESSAGE_* constants if not already done
e107::getMessage(); e107::getMessage();
$this->_messages = array(); $this->_messages = array();
} }
/**
* Alternative admin log entry point - compatible with legacy calls, and a bit simpler to use than the generic entry point. /**
* ($eventcode has been added - give it a reference to identify the source module, such as 'NEWS_12' or 'ECAL_03') * Alternative admin log entry point - compatible with legacy calls, and a bit simpler to use than the generic entry point.
* We also log everything (unlike 0.7, where admin log and debug stuff were all mixed up together) * ($eventcode has been added - give it a reference to identify the source module, such as 'NEWS_12' or 'ECAL_03')
* * We also log everything (unlike 0.7, where admin log and debug stuff were all mixed up together)
* @param string $event_title *
* @param mixed $event_detail * For multi-lingual logging (where the event title is shown in the language of the current user), LAN defines may be used in the title
* @param integer $event_type [optional] Log level *
* @param unknown $event_code [optional] * For generic calls, leave $event_code as empty, and specify a constant string STRING_nn of less than 10 characters for the event title
* @return e_admin_log * Typically the 'STRING' part of the name defines the area originating the log event, and the 'nn' is a numeric code
*/ * This is stored as 'LAN_AL_STRING_NN', and must be defined in a language file which is loaded during log display.
function log_event($event_title, $event_detail, $event_type = E_LOG_INFORMATIVE , $event_code = '') *
{ * @param string $event_title
if ($event_code == '') * @param mixed $event_detail
{ * @param integer $event_type [optional] Log level
if (strlen($event_title) <= 10) * @param unknown $event_code [optional]
{ // Assume the title is actually a reference to the event * @return e_admin_log
$event_code = $event_title; */
$event_title = 'LAN_AL_'.$event_title; public function log_event($event_title, $event_detail, $event_type = E_LOG_INFORMATIVE , $event_code = '')
} {
else if ($event_code == '')
{ {
$event_code = 'ADMIN'; if (strlen($event_title) <= 10)
} { // Assume the title is actually a reference to the event
} $event_code = $event_title;
//SecretR - now supports DB array as event_detail (see e.g. db::db_Insert()) $event_title = 'LAN_AL_'.$event_title;
if (is_array($event_detail)) }
{ else
$tmp = array(); {
if (isset($event_detail['data'])) $event_code = 'ADMIN';
{ }
$event_detail = $event_detail['data']; }
} //SecretR - now supports DB array as event_detail (see e.g. db::db_Insert())
foreach ($event_detail as $k => $v) if (is_array($event_detail))
{ {
$tmp[] = $k.'=>'.$v; $tmp = array();
} if (isset($event_detail['data']))
$event_detail = implode("[!br!]\n", $tmp); {
unset($tmp); $event_detail = $event_detail['data'];
} }
foreach ($event_detail as $k => $v)
if ($this->_options['backtrace'] == true) {
{ $tmp[] = $k.'=>'.$v;
$event_detail .= "\n\n".debug_backtrace(); }
} $event_detail = implode("[!br!]\n", $tmp);
$this->e_log_event($event_type, -1, $event_code, $event_title, $event_detail, FALSE, LOG_TO_ADMIN); unset($tmp);
}
return $this;
} if ($this->_options['backtrace'] == true)
{
/* $event_detail .= "\n\n".debug_backtrace();
Generic log entry point }
----------------------- $this->e_log_event($event_type, -1, $event_code, $event_title, $event_detail, FALSE, LOG_TO_ADMIN);
Example call: (Deliberately pick separators that shouldn't be in file names)
e_log_event(E_LOG_NOTICE,__FILE__."|".__FUNCTION__."@".__LINE__,"ECODE","Event Title","explanatory message",FALSE,LOG_TO_ADMIN); return $this;
or: }
e_log_event(E_LOG_NOTICE,debug_backtrace(),"ECODE","Event Title","explanatory message",TRUE,LOG_TO_ROLLING);
/**
Parameters: Generic log entry point
$importance - importance of event - 0..4 or so -----------------------
$source_call - either: string identifying calling file/routine Example call: (Deliberately pick separators that shouldn't be in file names)
or: a number 0..9 identifying info to log from debug_backtrace() e_log_event(E_LOG_NOTICE,__FILE__."|".__FUNCTION__."@".__LINE__,"ECODE","Event Title","explanatory message",FALSE,LOG_TO_ADMIN);
or: empty string, in which case first entry from debug_backtrace() logged or:
or: an array, assumed to be from passing debug_backtrace() as a parameter, in which case relevant e_log_event(E_LOG_NOTICE,debug_backtrace(),"ECODE","Event Title","explanatory message",TRUE,LOG_TO_ROLLING);
information is extracted and the argument list from the first entry logged *
or: -1, in which case no information logged * @param int $importance - importance of event - 0..4 or so
$eventcode - abbreviation listing event type * @param mixed $source_call - either: string identifying calling file/routine
$event_title - title of event - pass standard 'LAN_ERROR_nn' defines to allow language translation * or: a number 0..9 identifying info to log from debug_backtrace()
$explain - detail of event * or: empty string, in which case first entry from debug_backtrace() logged
$finished - if TRUE, aborts execution * or: an array, assumed to be from passing debug_backtrace() as a parameter, in which case relevant
$target_logs - flags indicating which logs to update - if entry to be posted in several logs, add (or 'OR') their defines: * information is extracted and the argument list from the first entry logged
LOG_TO_ADMIN - admin log * or: -1, in which case no information logged
LOG_TO_AUDIT - audit log * @param string $eventcode - abbreviation listing event type
LOG_TO_ROLLING - rolling log * @param string $event_title - title of event - pass standard 'LAN_ERROR_nn' defines to allow language translation
*/ * @param string $explain - detail of event
function e_log_event($importance, $source_call, $eventcode = "GEN", $event_title = "Untitled", $explain = "", $finished = FALSE, $target_logs = LOG_TO_AUDIT ) * @param bool $finished - if TRUE, aborts execution
{ * @param int $target_logs - flags indicating which logs to update - if entry to be posted in several logs, add (or 'OR') their defines:
global $pref,$e107,$tp; * LOG_TO_ADMIN - admin log
* LOG_TO_AUDIT - audit log
list($time_usec, $time_sec) = explode(" ", microtime()); // Log event time immediately to minimise uncertainty * LOG_TO_ROLLING - rolling log
$time_usec = $time_usec * 1000000; *
* @return none
if ($this->rldb == NULL)
$this->rldb = new db; // Better use our own db - don't know what else is going on * @todo - check microtime() call
*/
if (is_bool($target_logs)) public function e_log_event($importance, $source_call, $eventcode = "GEN", $event_title = "Untitled", $explain = "", $finished = FALSE, $target_logs = LOG_TO_AUDIT )
{ // Handle the legacy stuff for now - some old code used a boolean to select admin or rolling logs {
$target_logs = $target_logs ? LOG_TO_ADMIN : LOG_TO_ROLLING; global $pref,$e107,$tp;
}
list($time_usec, $time_sec) = explode(" ", microtime(FALSE)); // Log event time immediately to minimise uncertainty
//--------------------------------------- $time_usec = $time_usec * 1000000;
// Calculations common to all logs
//--------------------------------------- if ($this->rldb == NULL)
$userid = (USER === TRUE) ? USERID : 0; $this->rldb = new db; // Better use our own db - don't know what else is going on
$userstring = (USER === true ? USERNAME : "LAN_ANONYMOUS");
$userIP = $e107->getip(); if (is_bool($target_logs))
{ // Handle the legacy stuff for now - some old code used a boolean to select admin or rolling logs
$importance = $tp->toDB($importance, true, false, 'no_html'); $target_logs = $target_logs ? LOG_TO_ADMIN : LOG_TO_ROLLING;
$eventcode = $tp->toDB($eventcode, true, false, 'no_html'); }
if (is_array($explain)) //---------------------------------------
{ // Calculations common to all logs
$line = ''; //---------------------------------------
$spacer = ''; $userid = (USER === TRUE) ? USERID : 0;
foreach ($explain as $k=>$v) $userstring = (USER === true ? USERNAME : "LAN_ANONYMOUS");
{ $userIP = $e107->getip();
$line .= $spacer.$k.'=>'.$v;
$spacer = '[!br!]'; $importance = $tp->toDB($importance, true, false, 'no_html');
} $eventcode = $tp->toDB($eventcode, true, false, 'no_html');
$explain = $line;
unset($line); if (is_array($explain))
} {
$explain = mysql_real_escape_string($tp->toDB($explain, true, false, 'no_html')); $line = '';
$event_title = $tp->toDB($event_title, true, false, 'no_html'); $spacer = '';
foreach ($explain as $k=>$v)
//--------------------------------------- {
// Admin Log $line .= $spacer.$k.'=>'.$v;
//--------------------------------------- $spacer = '[!br!]';
if ($target_logs & LOG_TO_ADMIN) }
{ // Admin log - assume all fields valid $explain = $line;
$qry = " 0, ".intval($time_sec).','.intval($time_usec).", '{$importance}', '{$eventcode}', {$userid}, '{$userIP}', '{$event_title}', '{$explain}' "; unset($line);
$this->rldb->db_Insert("admin_log", $qry); }
} $explain = mysql_real_escape_string($tp->toDB($explain, true, false, 'no_html'));
$event_title = $tp->toDB($event_title, true, false, 'no_html');
//---------------------------------------
// Audit Log //---------------------------------------
//--------------------------------------- // Admin Log
// Add in audit log here //---------------------------------------
if ($target_logs & LOG_TO_ADMIN)
//--------------------------------------- { // Admin log - assume all fields valid
// Rolling Log $qry = " 0, ".intval($time_sec).','.intval($time_usec).", '{$importance}', '{$eventcode}', {$userid}, '{$userIP}', '{$event_title}', '{$explain}' ";
//--------------------------------------- $this->rldb->db_Insert("admin_log", $qry);
if (($target_logs & LOG_TO_ROLLING) && varsettrue($pref['roll_log_active'])) }
{ // Rolling log
//---------------------------------------
// Process source_call info // Audit Log
//--------------------------------------- //---------------------------------------
if (is_numeric($source_call) && ($source_call >= 0)) // Add in audit log here
{
$back_count = 1; //---------------------------------------
$i = 0; // Rolling Log
if (is_numeric($source_call) || ($source_call == '')) //---------------------------------------
{ if (($target_logs & LOG_TO_ROLLING) && varsettrue($pref['roll_log_active']))
$back_count = $source_call + 1; { // Rolling log
$source_call = debug_backtrace();
$i = 1; // Don't want to print the entry parameters to this function - we know all that! // Process source_call info
} //---------------------------------------
} if (is_numeric($source_call) && ($source_call >= 0))
{
if (is_array($source_call)) $back_count = 1;
{ // Print the debug_backtrace() array $i = 0;
while ($i < $back_count) if (is_numeric($source_call) || ($source_call == ''))
{ {
$source_call[$i]['file'] = $e107->fix_windows_paths($source_call[$i]['file']); // Needed for Windoze hosts. $back_count = $source_call + 1;
$source_call[$i]['file'] = str_replace($e107->file_path, "", $source_call[$i]['file']); // We really just want a e107 root-relative path. Strip out the root bit $source_call = debug_backtrace();
$tmp = $source_call[$i]['file']."|".$source_call[$i]['class'].$source_call[$i]['type'].$source_call[$i]['function']."@".$source_call[$i]['line']; $i = 1; // Don't want to print the entry parameters to this function - we know all that!
foreach ($source_call[$i]['args'] as $k=>$v) }
{ // Add in the arguments }
$explain .= "[!br!]".$k."=".$v;
} if (is_array($source_call))
$i++; { // Print the debug_backtrace() array
if ($i < $back_count) while ($i < $back_count)
$explain .= "[!br!]-------------------"; {
if (!isset($tmp1)) $source_call[$i]['file'] = $e107->fix_windows_paths($source_call[$i]['file']); // Needed for Windoze hosts.
$tmp1 = $tmp; // Pick off the immediate caller as the source $source_call[$i]['file'] = str_replace($e107->file_path, "", $source_call[$i]['file']); // We really just want a e107 root-relative path. Strip out the root bit
} $tmp = $source_call[$i]['file']."|".$source_call[$i]['class'].$source_call[$i]['type'].$source_call[$i]['function']."@".$source_call[$i]['line'];
if (isset($tmp1)) $source_call = $tmp1; foreach ($source_call[$i]['args'] as $k=>$v)
else $source_call = 'Root level'; { // Add in the arguments
} $explain .= "[!br!]".$k."=".$v;
else }
{ $i++;
$source_call = $e107->fix_windows_paths($source_call); // Needed for Windoze hosts. if ($i < $back_count)
$source_call = str_replace($e107->file_path, "", $source_call); // We really just want a e107 root-relative path. Strip out the root bit $explain .= "[!br!]-------------------";
$source_call = $tp->toDB($source_call, true, false, 'no_html'); if (!isset($tmp1))
} $tmp1 = $tmp; // Pick off the immediate caller as the source
// else $source_call is a string }
if (isset($tmp1)) $source_call = $tmp1;
// Save new rolling log record else $source_call = 'Root level';
$this->rldb->db_Insert("dblog", "0, ".intval($time_sec).', '.intval($time_usec).", '{$importance}', '{$eventcode}', {$userid}, '{$userstring}', '{$userIP}', '{$source_call}', '{$event_title}', '{$explain}' "); }
else
// Now delete any old stuff {
$this->rldb->db_Delete("dblog", "dblog_datestamp < '".intval(time() - (varset($pref['roll_log_days'], 7) * 86400))."' "); $source_call = $e107->fix_windows_paths($source_call); // Needed for Windoze hosts.
} $source_call = str_replace($e107->file_path, "", $source_call); // We really just want a e107 root-relative path. Strip out the root bit
$source_call = $tp->toDB($source_call, true, false, 'no_html');
if ($finished) }
exit; // Optional abort for all logs // else $source_call is a string
}
// Save new rolling log record
//-------------------------------------- $this->rldb->db_Insert("dblog", "0, ".intval($time_sec).', '.intval($time_usec).", '{$importance}', '{$eventcode}', {$userid}, '{$userstring}', '{$userIP}', '{$source_call}', '{$event_title}', '{$explain}' ");
// USER AUDIT ENTRY
//-------------------------------------- // Now delete any old stuff
// $event_code is a defined constant (see above) which specifies the event $this->rldb->db_Delete("dblog", "dblog_datestamp < '".intval(time() - (varset($pref['roll_log_days'], 7) * 86400))."' ");
// $event_data is an array of data fields whose keys and values are logged (usually user data, but doesn't have to be - can add messages here) }
// $id and $u_name are left blank except for admin edits and user login, where they specify the id and login name of the 'target' user
function user_audit($event_type, $event_data, $id = '', $u_name = '') if ($finished)
{ exit; // Optional abort for all logs
global $e107,$tp,$pref; }
list($time_usec, $time_sec) = explode(" ", microtime()); // Log event time immediately to minimise uncertainty
$time_usec = $time_usec * 1000000;
// See whether we should log this /**--------------------------------------
$user_logging_opts = array_flip(explode(',', varset($pref['user_audit_opts'], ''))); * USER AUDIT ENTRY
if (!isset($user_logging_opts[$event_type])) *--------------------------------------
return; // Finished if not set to log this event type * Log user-related events
* @param int $event_code is a defined constant (see above) which specifies the event
if ($this->rldb == NULL) * @param array $event_data is an array of data fields whose keys and values are logged (usually user data, but doesn't have to be - can add messages here)
$this->rldb = new db; // Better use our own db - don't know what else is going on * @param int $id
* @param string $u_name
if ($id) $userid = $id; * both $id and $u_name are left blank except for admin edits and user login, where they specify the id and login name of the 'target' user
else $userid = (USER === TRUE) ? USERID : 0; *
if ($u_name) $userstring = $u_name; * @return none
else $userstring = (USER === true ? USERNAME : "LAN_ANONYMOUS"); */
$userIP = $e107->getip(); function user_audit($event_type, $event_data, $id = '', $u_name = '')
$eventcode = 'USER_'.$event_type; {
global $e107,$tp,$pref;
$title = 'LAN_AUDIT_LOG_0'.$event_type; // This creates a string which will be displayed as a constant list($time_usec, $time_sec) = explode(" ", microtime()); // Log event time immediately to minimise uncertainty
$spacer = ''; $time_usec = $time_usec * 1000000;
$detail = '';
foreach ($event_data as $k=>$v) // See whether we should log this
{ $user_logging_opts = array_flip(explode(',', varset($pref['user_audit_opts'], '')));
$detail .= $spacer.$k.'=>'.$v; if (!isset($user_logging_opts[$event_type]))
$spacer = '<br />'; return; // Finished if not set to log this event type
}
$this->rldb->db_Insert("audit_log", "0, ".intval($time_sec).', '.intval($time_usec).", '{$eventcode}', {$userid}, '{$userstring}', '{$userIP}', '{$title}', '{$detail}' "); if ($this->rldb == NULL)
} $this->rldb = new db; // Better use our own db - don't know what else is going on
function get_log_events($count = 15, $offset) if ($id) $userid = $id;
{ else $userid = (USER === TRUE) ? USERID : 0;
global $sql; if ($u_name) $userstring = $u_name;
$count = intval($count); else $userstring = (USER === true ? USERNAME : "LAN_ANONYMOUS");
return "Not implemented yet"; $userIP = $e107->getip();
} $eventcode = 'USER_'.$event_type;
/** $title = 'LAN_AUDIT_LOG_0'.$event_type; // This creates a string which will be displayed as a constant
* Removes all events older than $days, or truncates the table if $days == false $spacer = '';
* $detail = '';
* @param integer|false $days foreach ($event_data as $k=>$v)
* @return void {
*/ $detail .= $spacer.$k.'=>'.$v;
function purge_log_events($days) $spacer = '<br />';
{ }
global $sql; $this->rldb->db_Insert("audit_log", "0, ".intval($time_sec).', '.intval($time_usec).", '{$eventcode}', {$userid}, '{$userstring}', '{$userIP}', '{$title}', '{$detail}' ");
if ($days == false) }
{ // $days is false, so truncate the log table
$sql->db_Select_gen("TRUNCATE TABLE #dblog ");
} /* Legacy function probably not needed
else function get_log_events($count = 15, $offset)
{ // $days is set, so remove all entries older than that. {
$days = intval($days); global $sql;
$mintime = $days * 24 * 60 * 60; $count = intval($count);
$time = time() - $mintime; return "Not implemented yet";
$sql->db_Delete("dblog", "WHERE `dblog_datestamp` < {$time}", true); }
} */
}
//--------------------------------------
// HELPER ROUTINES /**
//-------------------------------------- * Removes all events older than $days, or truncates the table if $days == false
// Generic routine to log changes to an array. Only elements in $new are checked *
// Returns true if changes, false otherwise. * @param integer|false $days
// Only makes log entry if changes detected. * @return void
// The $old array is updated with changes, but not saved anywhere */
public function purge_log_events($days)
{
global $sql;
if ($days == false)
{ // $days is false, so truncate the log table
$sql->db_Select_gen("TRUNCATE TABLE #dblog ");
}
else
{ // $days is set, so remove all entries older than that.
$days = intval($days);
$mintime = $days * 24 * 60 * 60;
$time = time() - $mintime;
$sql->db_Delete("dblog", "WHERE `dblog_datestamp` < {$time}", true);
}
}
//--------------------------------------
// HELPER ROUTINES
//--------------------------------------
/**
* Generic routine to log changes to an array. Only elements in $new are checked
*
* @param array $new - most recent data being saved
* @param array $old existing data - array is updated with changes, but not saved anywhere
* @param string $event - LAN define or string used as title in log
*
* @return bool true if changes found and logged, false otherwise.
*/
function logArrayDiffs(&$new, &$old, $event, $logNow = true) function logArrayDiffs(&$new, &$old, $event, $logNow = true)
{ {
$changes = array(); $changes = array();
foreach ($new as $k=>$v) foreach ($new as $k=>$v)
{ {
// FIXME - what about '' == '0'? // FIXME - what about '' == '0'?
if ($v != varset($old[$k], '')) if ($v != varset($old[$k], ''))
{ {
$old[$k] = $v; $old[$k] = $v;
$changes[] = $k.'=>'.$v; $changes[] = $k.'=>'.$v;
} }
} }
if (count($changes)) if (count($changes))
{ {
if($logNow) $this->log_event($event, implode('[!br!]', $changes), E_LOG_INFORMATIVE, ''); if($logNow) $this->log_event($event, implode('[!br!]', $changes), E_LOG_INFORMATIVE, '');
else $this->logMessage(implode('[!br!]', $changes), LOG_MESSAGE_NODISPLAY, E_MESSAGE_INFO); else $this->logMessage(implode('[!br!]', $changes), LOG_MESSAGE_NODISPLAY, E_MESSAGE_INFO);
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
/**
* Logs an entry with all the data from an array, one field per line.
*
* @param string $event - LAN define or string used as title in log
* @param array $target - data to be logged
* @param string $extra - if non-empty, it goes on the first line.
* @param array $niceNames - Normally data is logged in the format keyname=>value, one per line.
* If the $niceName array exists and has a definition, the 'nice Name' is displayed instead of the key name
*
* @return none
*/
public function logArrayAll($event, $target, $extra = '', $niceNames = NULL)
{
$logString = '';
if ($extra)
{
$logString = $extra.'[!br!]';
}
$spacer = '';
$checkNice = ($niceNames != NULL) && is_array($niceNames);
foreach ($target as $k=>$v)
{
if ($checkNice && isset($niceNames[$k]['niceName']))
{
$logString .= $spacer.$niceNames[$k]['niceName'].'=>'.$v;
}
else
{
$logString .= $spacer.$k.'=>'.$v;
}
$spacer = '[!br!]';
}
$this->log_event($event, $logString, E_LOG_INFORMATIVE, '');
}
// Logs an entry with all the data from an array, one field per line. /**
// If $extra is non-empty, it goes on the first line.
// Normally data is in the format keyname=>value, one per line.
// If the $niceName array exists and has a definition, the 'nice Name' is displayed instead of the key name
function logArrayAll($event, $target, $extra = '', $niceNames = NULL)
{
$logString = '';
if ($extra)
{
$logString = $extra.'[!br!]';
}
$spacer = '';
$checkNice = ($niceNames != NULL) && is_array($niceNames);
foreach ($target as $k=>$v)
{
if ($checkNice && isset($niceNames[$k]['niceName']))
{
$logString .= $spacer.$niceNames[$k]['niceName'].'=>'.$v;
}
else
{
$logString .= $spacer.$k.'=>'.$v;
}
$spacer = '[!br!]';
}
$this->log_event($event, $logString, E_LOG_INFORMATIVE, '');
}
/**
* The next two routines accept and buffers messages which are destined for both admin log and message handler * The next two routines accept and buffers messages which are destined for both admin log and message handler
*/ */
/** /**
* Add a message to the queue * Add a message to the queue
* *
* @param string $text - the message text for logging/display * @param string $text - the message text for logging/display
* @param int $type - the 'importance' of the message. E_MESSAGE_SUCCESS|E_MESSAGE_ERROR|E_MESSAGE_INFO|E_MESSAGE_DEBUG|E_MESSAGE_NODISPLAY * @param int $type - the 'importance' of the message. E_MESSAGE_SUCCESS|E_MESSAGE_ERROR|E_MESSAGE_INFO|E_MESSAGE_DEBUG|E_MESSAGE_NODISPLAY
* (Values as used in message handler, apart from the last, which causes the message to not be passed to the message handler * (Values as used in message handler, apart from the last, which causes the message to not be passed to the message handler
* @param boolean|int $logLevel - TRUE to give same importance as for message display. FALSE to not log. * @param boolean|int $logLevel - TRUE to give same importance as for message display. FALSE to not log.
* one of the values specified for $mesLevel to determine the prefix attached to the log message * one of the values specified for $mesLevel to determine the prefix attached to the log message
* @param boolean $session add session message * @param boolean $session add session message
* *
* @return e_admin_log * @return e_admin_log
*/ */
public function logMessage($text, $type = '', $logLevel = TRUE, $session = FALSE) public function logMessage($text, $type = '', $logLevel = TRUE, $session = FALSE)
{ {
if(empty($text)) return; if(empty($text)) return;
@@ -437,10 +473,10 @@ class e_admin_log
* @return e_admin_log * @return e_admin_log
*/ */
public function logSuccess($text, $message = true, $session = false) public function logSuccess($text, $message = true, $session = false)
{ {
return $this->logMessage($text, ($message ? E_MESSAGE_SUCCESS : LOG_MESSAGE_NODISPLAY), E_MESSAGE_SUCCESS, $session); return $this->logMessage($text, ($message ? E_MESSAGE_SUCCESS : LOG_MESSAGE_NODISPLAY), E_MESSAGE_SUCCESS, $session);
} }
/** /**
* Log error * Log error
* *
@@ -453,43 +489,44 @@ class e_admin_log
{ {
return $this->logMessage($text, ($message ? E_MESSAGE_ERROR : LOG_MESSAGE_NODISPLAY), E_MESSAGE_ERROR, $session); return $this->logMessage($text, ($message ? E_MESSAGE_ERROR : LOG_MESSAGE_NODISPLAY), E_MESSAGE_ERROR, $session);
} }
/** /**
* Empty the messages - pass to both admin log and message handler * Empty the messages - pass to both admin log and message handler
* *
* @param string $logTitle - title for log entry * @param string $logTitle - title for log entry
* @param int $logImportance - passed directly to admin log * @param int $logImportance - passed directly to admin log
* @param string $logEventCode - passed directly to admin log * @param string $logEventCode - passed directly to admin log
* *
* @return e_admin_log * @return e_admin_log
*/ */
public function flushMessages($logTitle, $logImportance = E_LOG_INFORMATIVE, $logEventCode = '') public function flushMessages($logTitle, $logImportance = E_LOG_INFORMATIVE, $logEventCode = '')
{ {
$mes = e107::getMessage(); $mes = e107::getMessage();
$resultTypes = array(E_MESSAGE_SUCCESS - 'Success', E_MESSAGE_ERROR => 'Fail'); // Add LANS here. Could add other codes $resultTypes = array(E_MESSAGE_SUCCESS - 'Success', E_MESSAGE_ERROR => 'Fail'); // Add LANS here. Could add other codes
$separator = ''; $separator = '';
$logString = ''; $logString = '';
foreach ($this->_messages as $m) foreach ($this->_messages as $m)
{ {
if ($m['loglevel'] !== FALSE) if ($m['loglevel'] !== FALSE)
{ {
$logString .= $separator; $logString .= $separator;
if ($m['loglevel'] == LOG_MESSAGE_NODISPLAY) { $logString .= ' '; } // Indent supplementary messages if ($m['loglevel'] == LOG_MESSAGE_NODISPLAY) { $logString .= ' '; } // Indent supplementary messages
// Not sure about next line - might want to log the <br /> as text, rather than it forcing a newline
$logString .= strip_tags(str_replace(array('<br>', '<br/>', '<br />'), '[!br!]', $m['message'])); $logString .= strip_tags(str_replace(array('<br>', '<br/>', '<br />'), '[!br!]', $m['message']));
if (isset($resultTypes[$m['loglevel']])) if (isset($resultTypes[$m['loglevel']]))
{ {
$logString .= ' - '.$resultTypes[$m['loglevel']]; $logString .= ' - '.$resultTypes[$m['loglevel']];
} }
$separator = '[!br!]'; $separator = '[!br!]';
} }
if ($m['dislevel'] != LOG_MESSAGE_NODISPLAY) if ($m['dislevel'] != LOG_MESSAGE_NODISPLAY)
{ {
$mes->add($m['message'], $m['dislevel'], $m['session']); $mes->add($m['message'], $m['dislevel'], $m['session']);
} }
} }
e107::getAdminLog()->log_event($logTitle, $logString, $logImportance, $logEventCode); e107::getAdminLog()->log_event($logTitle, $logString, $logImportance, $logEventCode);
$this->_messages = array(); // Clear the memory for reuse $this->_messages = array(); // Clear the memory for reuse
return $this; return $this;
} }
} }

View File

@@ -539,7 +539,7 @@ class e_pref extends e_admin_model
if(is_array($old)) // fix install problems - no old prefs available if(is_array($old)) // fix install problems - no old prefs available
{ {
$new = $this->getPref(); $new = $this->getPref();
$admin_log->logArrayDiffs($new, $old, 'LAN_FIXME', false); $admin_log->logArrayDiffs($new, $old, 'PREFS_02', false);
unset($new, $old); unset($new, $old);
} }
if(e107::getDb()->db_Select_gen("REPLACE INTO `#core` (e107_name,e107_value) values ('".$this->prefid."_Backup', '".addslashes($dbdata)."') ")) if(e107::getDb()->db_Select_gen("REPLACE INTO `#core` (e107_name,e107_value) values ('".$this->prefid."_Backup', '".addslashes($dbdata)."') "))
@@ -550,7 +550,7 @@ class e_pref extends e_admin_model
} }
$this->setPrefCache($this->toString(false), true); //reset pref cache - runtime & file $this->setPrefCache($this->toString(false), true); //reset pref cache - runtime & file
$admin_log->logSuccess('Settings successfully saved.', true, $session_messages)->flushMessages('LAN_FIXME'); $admin_log->logSuccess('Settings successfully saved.', true, $session_messages)->flushMessages('PREFS_01');
//BC //BC
if($this->alias === 'core') if($this->alias === 'core')
{ {
@@ -562,7 +562,7 @@ class e_pref extends e_admin_model
{ {
$admin_log->logError('mySQL error #'.e107::getDb()->getLastErrorNumber().': '.e107::getDb()->getLastErrorText(), true, $session_messages) $admin_log->logError('mySQL error #'.e107::getDb()->getLastErrorNumber().': '.e107::getDb()->getLastErrorText(), true, $session_messages)
->logError('Settings not saved.', true, $session_messages) ->logError('Settings not saved.', true, $session_messages)
->flushMessages('LAN_FIXME'); ->flushMessages('PREFS_03');
return false; return false;
} }
} }

View File

@@ -110,6 +110,8 @@ define('LAN_ROLL_LOG_11','Admin login fail');
// Prefs events // Prefs events
//------------- //-------------
define('LAN_AL_PREFS_01', 'Preferences changed'); define('LAN_AL_PREFS_01', 'Preferences changed');
define('LAN_AL_PREFS_02', 'New Preferences created');
define('LAN_AL_PREFS_03', 'Error saving prefs');
// Front Page events // Front Page events