mirror of
				https://github.com/e107inc/e107.git
				synced 2025-10-27 03:31:47 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1065 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			1065 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * e107 website system
 | |
|  *
 | |
|  * Copyright (C) 2008-2010 e107 Inc (e107.org)
 | |
|  * Released under the terms and conditions of the
 | |
|  * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
 | |
|  *
 | |
|  * Admin Log Handler
 | |
|  *
 | |
|  * USAGE:
 | |
|  *
 | |
|  * @example Log and Add to Message Handler: e107::getAdminLog()->addSuccess("Successfully executed")->save('PREF_01');
 | |
|  * @example Log Only: e107::getAdminLog()->addSuccess("Successfully executed",false)->save('PREF_01');
 | |
|  * @example Log Array Diff: e107::getAdminLog()->addArray($array1, $array2)->save('PREF_01');
 | |
|  * @example Log Array Diff and Add to Message Handler: e107::getAdminLog()->addArray($array1, $array2, E_MESSAGE_ERROR )->save('PREF_01');
 | |
|  *
 | |
|  */
 | |
| 
 | |
| if(!defined('e107_INIT'))
 | |
| {
 | |
| 	exit;
 | |
| }
 | |
| 
 | |
| define('LOG_MESSAGE_NODISPLAY', 'nodisplay');
 | |
| 
 | |
| 
 | |
| /**
 | |
|  *    Admin logging class.
 | |
|  *
 | |
|  * @package       e107
 | |
|  * @subpackage    e107_handlers
 | |
|  * @version       $Id$;
 | |
|  * @author        e107steved
 | |
|  */
 | |
| class e_admin_log
 | |
| {
 | |
| 
 | |
| 	/**
 | |
| 	 * Contains default class options, plus any that are overidden by the constructor
 | |
| 	 *
 | |
| 	 * @var array
 | |
| 	 */
 | |
| 	protected $_options = array('log_level' => 2, 'backtrace' => false,);
 | |
| 
 | |
| 	protected $rldb = null; // Database used by logging routine
 | |
| 
 | |
| 	protected $_userData = null;
 | |
| 
 | |
| 	protected $logFile = null;
 | |
| 	/**
 | |
| 	 * Log messages
 | |
| 	 *
 | |
| 	 * @var array
 | |
| 	 */
 | |
| 	protected $_messages;
 | |
| 
 | |
| 
 | |
| 	protected $_allMessages; // similar to $_messages except it is never flushed.
 | |
| 
 | |
| 
 | |
| 	protected $_current_plugin = null;
 | |
| 
 | |
| 	private $_roll_log_active = false;
 | |
| 
 | |
| 	private $_roll_log_days = 0;
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Constructor. Sets up constants and overwrites default options where set.
 | |
| 	 *
 | |
| 	 * @param array $options
 | |
| 	 * @return void
 | |
| 	 */
 | |
| 	public function __construct($options = array())
 | |
| 	{
 | |
| 
 | |
| 		if(!empty($options))
 | |
| 		{
 | |
| 			foreach($options as $key => $val)
 | |
| 			{
 | |
| 				$this->_options[$key] = $val;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if(!defined('E_LOG_INFORMATIVE'))
 | |
| 		{
 | |
| 
 | |
| 
 | |
| 			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_WARNING', 2); // Not anything serious, but important information
 | |
| 			define('E_LOG_FATAL', 3); //  An event so bad your site ceased execution.
 | |
| 			define('E_LOG_PLUGIN', 4); // Plugin information
 | |
| 
 | |
| 			// Logging actions
 | |
| 			define('LOG_TO_ADMIN', 1);
 | |
| 			define('LOG_TO_AUDIT', 2);
 | |
| 			define('LOG_TO_ROLLING', 4);
 | |
| 
 | |
| 			// User audit logging (intentionally start at 10 - stick to 2 digits)
 | |
| 			// 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_SIGNUP', 11); // User signed up
 | |
| 			define('USER_AUDIT_EMAILACK', 12); // User responded to registration email
 | |
| 			define('USER_AUDIT_LOGIN', 13); // User logged in
 | |
| 			define('USER_AUDIT_LOGOUT', 14); // User logged out
 | |
| 			define('USER_AUDIT_NEW_DN', 15); // User changed display name
 | |
| 			define('USER_AUDIT_NEW_PW', 16); // User changed password
 | |
| 			define('USER_AUDIT_NEW_EML', 17); // User changed 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_ADD_ADMIN', 20); // User added by admin
 | |
| 			define('USER_AUDIT_MAIL_BOUNCE', 21); // User mail bounce
 | |
| 			define('USER_AUDIT_BANNED', 22); // User banned
 | |
| 			define('USER_AUDIT_BOUNCE_RESET', 23); // User bounce reset
 | |
| 			define('USER_AUDIT_TEMP_ACCOUNT', 24); // User temporary account
 | |
| 			define('USER_AUDIT_NAVIGATION', 25); // User signed up
 | |
| 
 | |
| 		}
 | |
| 		// Init E_MESSAGE_* constants if not already done
 | |
| 		// e107::getMessage(); - just include, message handler is creating session in construct
 | |
| 		// it breaks stuff (see class2 - language detection and comments)
 | |
| 		require_once(e_HANDLER . 'message_handler.php');
 | |
| 		$this->_messages = array();
 | |
| 		$this->_allMessages = array();
 | |
| 
 | |
| 		$pref = e107::getPref();
 | |
| 		$this->_roll_log_active = (bool) varset($pref['roll_log_active']);
 | |
| 		$this->_roll_log_days = (int) varset($pref['roll_log_days']);
 | |
| 
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Set the user ID and name for the next log entry
 | |
| 	 * @param int $user_id
 | |
| 	 * @param string $user_name
 | |
| 	 * @return e_admin_log
 | |
| 	 */
 | |
| 	public function setUser($user_id, $user_name='')
 | |
| 	{
 | |
| 	    $this->_userData = array(
 | |
| 	        'user_id' => (int) $user_id,
 | |
| 	        'user_name' => !empty($user_name) ? e107::getParser()->toDB($user_name, true, false, 'no_html') : ''
 | |
| 	    );
 | |
| 
 | |
| 	    return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @deprecated
 | |
| 	 * BC Alias of add();
 | |
| 	 */
 | |
| 	public function log_event($event_title, $event_detail, $event_type = E_LOG_INFORMATIVE, $event_code = '')
 | |
| 	{
 | |
| 
 | |
| 		trigger_error('<b>' . __METHOD__ . ' is deprecated.</b> Use add() instead.', E_USER_DEPRECATED);
 | |
| 
 | |
| 		return $this->add($event_title, $event_detail, $event_type, $event_code);
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Save all logs in the queue to the database and render any unhidden messages with the message handler.
 | |
| 	 *
 | |
| 	 * @param string $logTitle      - title for log entry eg. 'PREF_01'
 | |
| 	 * @param int    $logImportance [optional] default E_LOG_INFORMATIVE, E_LOG_NOTICE, E_LOG_WARNING, E_LOG_FATAL - passed directly to admin log
 | |
| 	 * @param string $logEventCode  [optional] - passed directly to admin log
 | |
| 	 * @param string $mstack        [optional] message stack passed to message handler
 | |
| 	 * @param int LOG_TO_ADMIN|LOG_TO_ROLLING|LOG_TO_AUDIT
 | |
| 	 * @return \e_admin_log
 | |
| 	 * @see alias flushMessages() method below.
 | |
| 	 */
 | |
| 	public function save($logTitle, $logImportance = E_LOG_INFORMATIVE, $logEventCode = '', $mstack = false, $target = LOG_TO_ADMIN)
 | |
| 	{
 | |
| 
 | |
| 		return $this->flushMessages($logTitle, $logImportance, $logEventCode, $mstack, $target);
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Add and Save an event into the admin, rolling or user log.
 | |
| 	 *
 | |
| 	 * @param string       $event_title
 | |
| 	 * @param string|array $event_detail
 | |
| 	 * @param integer      $event_type [optional] Log level eg. E_LOG_INFORMATIVE, E_LOG_NOTICE, E_LOG_WARNING, E_LOG_FATAL
 | |
| 	 * @param string       $event_code [optional] - eg. 'BOUNCE'
 | |
| 	 * @param integer      $target     [optional]  LOG_TO_ADMIN, LOG_TO_AUDIT, LOG_TO_ROLLING
 | |
| 	 * @param null         $userData
 | |
| 	 * @return e_admin_log
 | |
| 	 *
 | |
| 	 * 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')
 | |
| 	 * We also log everything (unlike 0.7, where admin log and debug stuff were all mixed up together)
 | |
| 	 *
 | |
| 	 * 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
 | |
| 	 *
 | |
| 	 * For generic calls, leave $event_code as empty, and specify a constant string STRING_nn of less than 10 characters for the event title
 | |
| 	 * 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.
 | |
| 	 */
 | |
| 	public function add($event_title, $event_detail, $event_type = E_LOG_INFORMATIVE, $event_code = '', $target = LOG_TO_ADMIN, $userData = null)
 | |
| 	{
 | |
| 
 | |
| 		if(empty($event_code))
 | |
| 		{
 | |
| 			if(strlen($event_title) <= 12)
 | |
| 			{ // Assume the title is actually a reference to the event
 | |
| 				$event_code = $event_title;
 | |
| 				$event_title = 'LAN_AL_' . $event_title;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				$event_code = 'ADMIN';
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if(!is_array($event_detail))
 | |
| 		{
 | |
| 			// auto-format long details -
 | |
| 			$event_detail = str_replace("\n", '[!br!]', $event_detail);
 | |
| 		}
 | |
| 
 | |
| 		if($this->_options['backtrace'] == true)
 | |
| 		{
 | |
| 			$event_detail .= "\n\n" . debug_backtrace(false);
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 		$this->addEvent($event_type, -1, $event_code, $event_title, $event_detail, false, $target, $userData);
 | |
| 
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Enable/Disable the Rolling Log.
 | |
| 	 *
 | |
| 	 * @param $bool
 | |
| 	 */
 | |
| 	public function rollingLog($bool)
 | |
| 	{
 | |
| 
 | |
| 		$this->_roll_log_active = (bool) $bool;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Alias for deprecated e_log_event
 | |
| 	 *
 | |
| 	 * @param int    $importance  - importance of event - 0..4 or so
 | |
| 	 * @param mixed  $source_call - either:    string identifying calling file/routine
 | |
| 	 *                            or:        a number 0..9 identifying info to log from debug_backtrace()
 | |
| 	 *                            or:        empty string, in which case first entry from debug_backtrace() logged
 | |
| 	 *                            or:        an array, assumed to be from passing debug_backtrace() as a parameter, in which case relevant
 | |
| 	 *                            information is extracted and the argument list from the first entry logged
 | |
| 	 *                            or:        -1, in which case no information logged
 | |
| 	 * @param string $eventcode   - abbreviation listing event type
 | |
| 	 * @param string $event_title -  title of event - pass standard 'LAN_ERROR_nn' defines to allow language translation
 | |
| 	 * @param string $explain     -  detail of event
 | |
| 	 * @param bool   $finished    -  if TRUE, aborts execution
 | |
| 	 * @param int    $target_logs - table to save to : LOG_TO_ADMIN,  LOG_TO_AUDIT,  LOG_TO_ROLLING
 | |
| 	 * @param null   $userData    - attribute user to log entry. array('user_id'=>2, 'user_name'=>'whatever');
 | |
| 	 *
 | |
| 	 * @return null
 | |
| 	 */
 | |
| 	public function addEvent($importance, $source_call, $eventcode = 'GEN', $event_title = 'Untitled', $explain = '', $finished = false, $target_logs = LOG_TO_AUDIT, $userData = null)
 | |
| 	{
 | |
| 
 | |
| 		$e107 = e107::getInstance();
 | |
| 		$tp = e107::getParser();
 | |
| 
 | |
| 		list($time_usec, $time_sec) = explode(' ', microtime(false)); // Log event time immediately to minimise uncertainty
 | |
| 		$time_usec = $time_usec * 1000000;
 | |
| 
 | |
| 		if($this->rldb === null) // Better use our own db - don't know what else is going on
 | |
| 		{
 | |
| 			$this->rldb = e107::getDb('adminlog');
 | |
| 		}
 | |
| 
 | |
| 		if(is_bool($target_logs))
 | |
| 		{ // 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;
 | |
| 		}
 | |
| 
 | |
| 		//---------------------------------------
 | |
| 		// Calculations common to all logs
 | |
| 		//---------------------------------------
 | |
| 
 | |
| 		$userid = deftrue('USER') ? USERID : 0;
 | |
| 		$userstring = deftrue('USER') ? USERNAME : 'LAN_ANONYMOUS';
 | |
| 		$userIP = e107::getIPHandler()->getIP(false);
 | |
| 
 | |
| 		if(!empty($userData['user_id']))
 | |
| 		{
 | |
| 			$userid = $userData['user_id'];
 | |
| 		}
 | |
| 
 | |
| 		if(!empty($userData['user_name']))
 | |
| 		{
 | |
| 			$userstring = $userData['user_name'];
 | |
| 		}
 | |
| 
 | |
| 		if(!empty($userData['user_ip']))
 | |
| 		{
 | |
| 			$userIP = $userData['user_ip'];
 | |
| 		}
 | |
| 
 | |
| 		$importance = $tp->toDB($importance, true, false, 'no_html');
 | |
| 		$eventcode = $tp->toDB($eventcode, true, false, 'no_html');
 | |
| 
 | |
| 		if(is_array($explain))
 | |
| 		{
 | |
| 			/*
 | |
| 			$line = '';
 | |
| 			$spacer = '';
 | |
| 			foreach ($explain as $k=>$v)
 | |
| 			{
 | |
| 				$line .= $spacer.$k.'=>'.$v;
 | |
| 				$spacer = '[!br!]';
 | |
| 			}
 | |
| 			$explain = $line;
 | |
| 			unset($line);
 | |
| 			*/
 | |
| 			$explain = str_replace("\n", '[!br!]', print_r($explain, true));
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 		$explain = e107::getDb()->escape($tp->toDB($explain, true, false, 'no_html'));
 | |
| 		$event_title = $tp->toDB($event_title, true, false, 'no_html');
 | |
| 
 | |
| 		//---------------------------------------
 | |
| 		// 			Admin Log
 | |
| 		//---------------------------------------
 | |
| 		if($target_logs & LOG_TO_ADMIN) // Admin log - assume all fields valid
 | |
| 		{
 | |
| 			//	$qry = " null, ".intval($time_sec).','.intval($time_usec).", '{$importance}', '{$eventcode}', {$userid}, '{$userIP}', '{$event_title}', '{$explain}' ";
 | |
| 
 | |
| 			$adminLogInsert = array(
 | |
| 				'dblog_id'        => null,
 | |
| 				'dblog_type'      => $importance,
 | |
| 				'dblog_eventcode' => $eventcode,
 | |
| 				'dblog_datestamp' => time(),
 | |
| 				'dblog_microtime' => (int) $time_usec,
 | |
| 				'dblog_user_id'   => $userid,
 | |
| 				'dblog_ip'        => $userIP,
 | |
| 				'dblog_title'     => $event_title,
 | |
| 				'dblog_remarks'   => $explain
 | |
| 			);
 | |
| 
 | |
| 			$this->rldb->insert('admin_log', $adminLogInsert);
 | |
| 		}
 | |
| 
 | |
| 		//---------------------------------------
 | |
| 		// 			Audit Log
 | |
| 		//---------------------------------------
 | |
| 		// Add in audit log here
 | |
| 
 | |
| 		//---------------------------------------
 | |
| 		// 			Rolling Log
 | |
| 		//---------------------------------------
 | |
| 		if(($target_logs & LOG_TO_ROLLING) && $this->_roll_log_active)
 | |
| 		{ //	Rolling log
 | |
| 
 | |
| 			// 	Process source_call info
 | |
| 			//---------------------------------------
 | |
| 			if(is_numeric($source_call) && ($source_call >= 0))
 | |
| 			{
 | |
| 				$back_count = 1;
 | |
| 				$i = 0;
 | |
| 				if(($source_call == ''))
 | |
| 				{
 | |
| 					$back_count = $source_call + 1;
 | |
| 					$source_call = debug_backtrace();
 | |
| 					$i = 1; // Don't want to print the entry parameters to this function - we know all that!
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			if(is_array($source_call))
 | |
| 			{ // Print the debug_backtrace() array
 | |
| 				while($i < $back_count)
 | |
| 				{
 | |
| 					$source_call[$i]['file'] = $e107->fix_windows_paths($source_call[$i]['file']); // Needed for Windoze hosts.
 | |
| 					$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'];
 | |
| 					foreach($source_call[$i]['args'] as $k => $v)
 | |
| 					{ // Add in the arguments
 | |
| 						$explain .= '[!br!]' . $k . '=' . $v;
 | |
| 					}
 | |
| 					$i++;
 | |
| 					if($i < $back_count)
 | |
| 					{
 | |
| 						$explain .= "[!br!]-------------------";
 | |
| 					}
 | |
| 					if(!isset($tmp1))
 | |
| 					{
 | |
| 						$tmp1 = $tmp;
 | |
| 					} // Pick off the immediate caller as the source
 | |
| 				}
 | |
| 				if(isset($tmp1))
 | |
| 				{
 | |
| 					$source_call = $tmp1;
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					$source_call = 'Root level';
 | |
| 				}
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				$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');
 | |
| 			}
 | |
| 			// else $source_call is a string
 | |
| 
 | |
| 			// Save new rolling log record
 | |
| 
 | |
| 			$insertArr = array(
 | |
| 				'dblog_id'        => 0,
 | |
| 				'dblog_datestamp' => 0,
 | |
| 				'dblog_microtime' => 0,
 | |
| 				'dblog_type'      => '',
 | |
| 				'dblog_eventcode' => '',
 | |
| 				'dblog_user_id'   => '',
 | |
| 				'dblog_user_name' => '',
 | |
| 				'dblog_ip'        => '',
 | |
| 				'dblog_caller'    => '',
 | |
| 				'dblog_title'     => '',
 | |
| 				'dblog_remarks'   => ''
 | |
| 			);
 | |
| 
 | |
| 
 | |
| 			$this->rldb->insert('dblog', '0, ' . intval($time_sec) . ', ' . intval($time_usec) . ", '{$importance}', '{$eventcode}', {$userid}, '{$userstring}', '{$userIP}', '{$source_call}', '{$event_title}', '{$explain}' ");
 | |
| 
 | |
| 			// Now delete any old stuff
 | |
| 			if(!empty($this->_roll_log_days))
 | |
| 			{
 | |
| 				$this->rldb->delete('dblog', "dblog_datestamp < '" . intval(time() - ($this->_roll_log_days * 86400)) . "' ");
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if($finished)
 | |
| 		{
 | |
| 			exit;
 | |
| 		} // Optional abort for all logs
 | |
| 
 | |
| 		return null;
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @deprecated - use add() method instead or addEvent() as a direct replacement.
 | |
| 	 */
 | |
| 	public function e_log_event($importance, $source_call, $eventcode = 'GEN', $event_title = 'Untitled', $explain = '', $finished = false, $target_logs = LOG_TO_AUDIT, $userData = null)
 | |
| 	{
 | |
| 
 | |
| 		trigger_error('<b>' . __METHOD__ . ' is deprecated.</b> Use add()->save() or addEvent() instead.', E_USER_DEPRECATED);
 | |
| 
 | |
| 		return $this->addEvent($importance, $source_call, $eventcode, $event_title, $explain, $finished, $target_logs, $userData);
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * @param $plugdir
 | |
| 	 * @return $this
 | |
| 	 */
 | |
| 	public function setCurrentPlugin($plugdir)
 | |
| 	{
 | |
| 
 | |
| 		$this->_current_plugin = $plugdir;
 | |
| 
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**--------------------------------------
 | |
| 	 *        USER AUDIT ENTRY
 | |
| 	 *--------------------------------------
 | |
| 	 *    Log user-related events
 | |
| 	 *
 | |
| 	 * @param string       $event_type
 | |
| 	 * @param array|string $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)
 | |
| 	 * @param int          $id         user-id
 | |
| 	 * @param string       $u_name     user-name
 | |
| 	 *                                 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
 | |
| 	 *
 | |
| 	 * @return bool
 | |
| 	 */
 | |
| 	function user_audit($event_type, $event_data, $id = null, $u_name = '')
 | |
| 	{
 | |
| 
 | |
| 		list($time_usec, $time_sec) = explode(' ', microtime()); // Log event time immediately to minimise uncertainty
 | |
| 
 | |
| 		$time_usec = $time_usec * 1000000;
 | |
| 
 | |
| 		if(!is_numeric($event_type))
 | |
| 		{
 | |
| 			$title = 'User Audit Event-Type Failure: ';
 | |
| 			$title .= (string) $event_type;
 | |
| 			$debug = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 4);
 | |
| 			$debug[0] = e_REQUEST_URI;
 | |
| 
 | |
| 			$this->addEvent(4, $debug[1]['file'] . '|' . $debug[1]['function'] . '@' . $debug[1]['line'], 'USERAUDIT', $title, $debug, false);
 | |
| 
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// See whether we should log this
 | |
| 		$user_logging_opts = e107::getConfig()->get('user_audit_opts');
 | |
| 
 | |
| 		if(!isset($user_logging_opts[$event_type]))  // Finished if not set to log this event type
 | |
| 		{
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		if(empty($event_data))
 | |
| 		{
 | |
| 			$backt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 4);
 | |
| 			$event_data = $backt;
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 		if($this->rldb == null)
 | |
| 		{
 | |
| 			$this->rldb = e107::getDb('rldb'); // Better use our own db - don't know what else is going on
 | |
| 		}
 | |
| 
 | |
| 		if(!empty($id))
 | |
| 		{
 | |
| 			$userid = $id;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			$userid = (USER === true) ? USERID : 0;
 | |
| 		}
 | |
| 
 | |
| 		if(!empty($u_name))
 | |
| 		{
 | |
| 			$userstring = $u_name;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			$userstring = (USER === true ? USERNAME : 'LAN_ANONYMOUS');
 | |
| 		}
 | |
| 
 | |
| 		$userIP = e107::getIPHandler()->getIP(false);
 | |
| 
 | |
| 		$eventcode = 'USER_' . $event_type;
 | |
| 
 | |
| 		$title = 'LAN_AUDIT_LOG_0' . $event_type; // This creates a string which will be displayed as a constant
 | |
| 
 | |
| 		$insertQry = array(
 | |
| 			'dblog_id'        => 0,
 | |
| 			'dblog_datestamp' => intval($time_sec),
 | |
| 			'dblog_microtime' => intval($time_usec),
 | |
| 			'dblog_eventcode' => $eventcode,
 | |
| 			'dblog_user_id'   => $userid,
 | |
| 			'dblog_user_name' => $userstring,
 | |
| 			'dblog_ip'        => $userIP,
 | |
| 			'dblog_title'     => $title,
 | |
| 			'dblog_remarks'   => print_r($event_data, true),
 | |
| 		);
 | |
| 
 | |
| 		if($this->rldb->insert('audit_log', $insertQry))
 | |
| 		{
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/* Legacy function probably not needed
 | |
| 	function get_log_events($count = 15, $offset)
 | |
| 	{
 | |
| 		global $sql;
 | |
| 		$count = intval($count);
 | |
| 		return "Not implemented yet";
 | |
| 	}
 | |
| 	*/
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Removes all events older than $days, or truncates the table if $days == false
 | |
| 	 *
 | |
| 	 * @param integer|false $days
 | |
| 	 * @return void
 | |
| 	 */
 | |
| 	public function purge_log_events($days)
 | |
| 	{
 | |
| 
 | |
| 		global $sql;
 | |
| 		if($days == false)
 | |
| 		{ // $days is false, so truncate the log table
 | |
| 			$sql->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->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)
 | |
| 	{
 | |
| 
 | |
| 		// $changes = array();
 | |
| 
 | |
| 		$changes = array_diff_recursive($new, $old);
 | |
| 
 | |
| 		if(count($changes))
 | |
| 		{
 | |
| 			if($logNow)
 | |
| 			{
 | |
| 				$this->add($event, print_r($changes, true), E_LOG_INFORMATIVE, '');
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				$this->logMessage($changes, LOG_MESSAGE_NODISPLAY, E_MESSAGE_INFO);
 | |
| 			}
 | |
| 
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		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 null
 | |
| 	 * @deprecated Use e107::getLog()->addArray($arrayData)->save($event);
 | |
| 	 */
 | |
| 	public function logArrayAll($event, $target, $extra = '', $niceNames = null)
 | |
| 	{
 | |
| 
 | |
| 		trigger_error('<b>' . __METHOD__ . ' is deprecated.</b> Use e107::getLog()->addArray($arrayData)->save($event) instead.', E_USER_DEPRECATED); // no LAN
 | |
| 		if($extra == '' && $niceNames == null)
 | |
| 		{
 | |
| 			return $this->add($event, $target, E_LOG_INFORMATIVE, '');    // supports arrays
 | |
| 
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 		$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->add($event, $logString, E_LOG_INFORMATIVE, '');
 | |
| 
 | |
| 		return null;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 *    The next two routines accept and buffers messages which are destined for both admin log and message handler
 | |
| 	 */
 | |
| 
 | |
| 	/**
 | |
| 	 *    Add a message to the queue
 | |
| 	 *
 | |
| 	 * @param string|array $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
 | |
| 	 *                                        (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.
 | |
| 	 *                                        one of the values specified for $mesLevel to determine the prefix attached to the log message
 | |
| 	 * @param boolean      $session           add session message
 | |
| 	 *
 | |
| 	 * @return e_admin_log
 | |
| 	 */
 | |
| 	public function logMessage($text, $type = '', $logLevel = true, $session = false)
 | |
| 	{
 | |
| 
 | |
| 		if(is_array($text))
 | |
| 		{
 | |
| 			$text = print_r($text, true);
 | |
| 		}
 | |
| 		elseif(empty($text))
 | |
| 		{
 | |
| 			$bt = debug_backtrace(true);
 | |
| 			e107::getMessage()->addDebug('Log Message was empty: ' . print_a($bt[1], true));
 | |
| 
 | |
| 			return $this;    // changing to text will break chained methods.
 | |
| 		}
 | |
| 
 | |
| 		if(!$type)
 | |
| 		{
 | |
| 			$type = E_MESSAGE_INFO;
 | |
| 		}
 | |
| 		if($logLevel === true)
 | |
| 		{
 | |
| 			$logLevel = $type;
 | |
| 		}
 | |
| 
 | |
| 		$logArray = array('message' => $text, 'dislevel' => $type, 'loglevel' => $logLevel, 'session' => $session, 'time' => time());
 | |
| 
 | |
| 		$this->_messages[] = $logArray;
 | |
| 		$this->_allMessages[] = $logArray;
 | |
| 
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * @deprecated
 | |
| 	 * BC Alias for addSuccess();
 | |
| 	 */
 | |
| 	public function logSuccess($text, $message = true, $session = false)
 | |
| 	{
 | |
| 
 | |
| 		trigger_error('<b>' . __METHOD__ . ' is deprecated.</b> Use e107::getLog()->addSuccess($arrayData)->save($event) instead.', E_USER_DEPRECATED); // no LAN
 | |
| 
 | |
| 		return $this->addSuccess($text, $message, $session);
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * @deprecated
 | |
| 	 * BC Alias for addError();
 | |
| 	 */
 | |
| 	public function logError($text, $message = true, $session = false)
 | |
| 	{
 | |
| 
 | |
| 		trigger_error('<b>' . __METHOD__ . ' is deprecated.</b> Use e107::getLog()->addError($arrayData)->save($event) instead.', E_USER_DEPRECATED); // no LAN
 | |
| 
 | |
| 		return $this->addError($text, $message, $session);
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a success message to the log queue
 | |
| 	 *
 | |
| 	 * @param string|array $text
 | |
| 	 * @param boolean      $message if true - register with eMessage handler
 | |
| 	 * @param boolean      $session add session message
 | |
| 	 * @return e_admin_log
 | |
| 	 */
 | |
| 	public function addSuccess($text, $message = true, $session = false)
 | |
| 	{
 | |
| 
 | |
| 		return $this->logMessage($text, ($message ? E_MESSAGE_SUCCESS : LOG_MESSAGE_NODISPLAY), E_MESSAGE_SUCCESS, $session);
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Add an error message to the log queue
 | |
| 	 *
 | |
| 	 * @param string  $text
 | |
| 	 * @param boolean $message if true (default) - register with eMessage handler, set to false to hide.
 | |
| 	 * @param boolean $session add session message
 | |
| 	 * @return e_admin_log
 | |
| 	 */
 | |
| 	public function addError($text, $message = true, $session = false)
 | |
| 	{
 | |
| 
 | |
| 		return $this->logMessage($text, ($message ? E_MESSAGE_ERROR : LOG_MESSAGE_NODISPLAY), E_MESSAGE_ERROR, $session);
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Add an Debug message to the log queue
 | |
| 	 *
 | |
| 	 * @param string  $text
 | |
| 	 * @param boolean $message if true (default) - register with eMessage handler, set to false to hide .
 | |
| 	 * @param boolean $session add session message
 | |
| 	 * @return e_admin_log
 | |
| 	 */
 | |
| 	public function addDebug($text, $message = true, $session = false)
 | |
| 	{
 | |
| 
 | |
| 		return $this->logMessage($text, ($message ? E_MESSAGE_DEBUG : LOG_MESSAGE_NODISPLAY), E_MESSAGE_DEBUG, $session);
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Add an Warning message to the log queue
 | |
| 	 *
 | |
| 	 * @param string  $text
 | |
| 	 * @param boolean $message if true (default) - register with eMessage handler, set to false to hide.
 | |
| 	 * @param boolean $session add session message
 | |
| 	 * @return e_admin_log
 | |
| 	 */
 | |
| 	public function addWarning($text, $message = true, $session = false)
 | |
| 	{
 | |
| 
 | |
| 		return $this->logMessage($text, ($message ? E_MESSAGE_WARNING : LOG_MESSAGE_NODISPLAY), E_MESSAGE_WARNING, $session);
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Add an array to the log queue
 | |
| 	 *
 | |
| 	 * @param        $array
 | |
| 	 * @param null   $oldArray (optional) - when included, only the changes between the arrays is saved.
 | |
| 	 * @param string $type     (optional) default: LOG_MESSAGE_NODISPLAY. or E_MESSAGE_WARNING, E_MESSAGE_DEBUG, E_MESSAGE_SUCCESS
 | |
| 	 * @param bool   $session
 | |
| 	 * @return e_admin_log
 | |
| 	 */
 | |
| 	public function addArray($array, $oldArray = null, $type = LOG_MESSAGE_NODISPLAY, $session = false)
 | |
| 	{
 | |
| 
 | |
| 		if(is_array($oldArray))
 | |
| 		{
 | |
| 			$text = array_diff_recursive($array, $oldArray); // Located in core_functions.php
 | |
| 			if(count($text) < 1)
 | |
| 			{
 | |
| 				$text = 'No differences found';
 | |
| 			}
 | |
| 
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			$text = $array;
 | |
| 		}
 | |
| 
 | |
| 		return $this->logMessage($text, $type, $type, $session);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Return the last row added to the log table.
 | |
| 	 *
 | |
| 	 * @param int $type
 | |
| 	 * @return array|string
 | |
| 	 */
 | |
| 	public function getLastLog($type = LOG_TO_ADMIN)
 | |
| 	{
 | |
| 
 | |
| 		switch($type)
 | |
| 		{
 | |
| 			case LOG_TO_AUDIT:
 | |
| 				$table = 'audit_log';
 | |
| 				break;
 | |
| 
 | |
| 			case LOG_TO_ROLLING:
 | |
| 				$table = 'dblog';
 | |
| 				break;
 | |
| 
 | |
| 			case LOG_TO_ADMIN:
 | |
| 			default:
 | |
| 				$table = 'admin_log';
 | |
| 		}
 | |
| 
 | |
| 		$query = 'SELECT * FROM #' . $table . ' ORDER BY dblog_id DESC LIMIT 1';
 | |
| 
 | |
| 		return e107::getDb()->retrieve($query);
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Empty the messages - pass to both admin log and message handler
 | |
| 	 *
 | |
| 	 * @param string $logTitle      - title for log entry
 | |
| 	 * @param int    $logImportance - passed directly to admin log
 | |
| 	 * @param string $logEventCode  - passed directly to admin log
 | |
| 	 * @param string $mstack        [optional] message stack passed to message handler
 | |
| 	 * @param int    $target        - LOG_TO_ADMIN|LOG_TO_ROLLING|LOG_TO_AUDIT
 | |
| 	 * @return e_admin_log
 | |
| 	 */
 | |
| 	public function flushMessages($logTitle, $logImportance = E_LOG_INFORMATIVE, $logEventCode = '', $mstack = false, $target = LOG_TO_ADMIN)
 | |
| 	{
 | |
| 
 | |
| 		$mes = e107::getMessage();
 | |
| 
 | |
| 		$resultTypes = array(E_MESSAGE_SUCCESS => 'Success', E_MESSAGE_ERROR => 'Fail'); // Add LANS here. Could add other codes
 | |
| 		$separator = '';
 | |
| 		$logString = '';
 | |
| 		foreach($this->_messages as $m)
 | |
| 		{
 | |
| 			if($m['loglevel'] !== false)
 | |
| 			{
 | |
| 				$logString .= $separator;
 | |
| 				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']));
 | |
| 				if(isset($resultTypes[$m['loglevel']]))
 | |
| 				{
 | |
| 					$logString .= ' - ' . $resultTypes[$m['loglevel']];
 | |
| 				}
 | |
| 				$separator = '[!br!]';
 | |
| 			}
 | |
| 			if($m['dislevel'] != LOG_MESSAGE_NODISPLAY)
 | |
| 			{
 | |
| 				if($mstack)
 | |
| 				{
 | |
| 					$mes->addStack($m['message'], $mstack, $m['dislevel'], $m['session']);
 | |
| 					// move to main stack OUTSIDE if needed
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					$mes->add($m['message'], $m['dislevel'], $m['session']);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		$this->add($logTitle, $logString, $logImportance, $logEventCode, $target, $this->_userData);
 | |
| 		$this->_messages = array(); // Clear the memory for reuse
 | |
| 		$this->_userData = null; // Clear the user data to prevent reuse
 | |
| 
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Clear all messages in 'memory'.
 | |
| 	 */
 | |
| 	public function clear()
 | |
| 	{
 | |
| 
 | |
| 		$this->_messages = array();
 | |
| 
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Save Message stack to File.
 | |
| 	 */
 | |
| 	private function saveToFile($logTitle = '', $append = false, $opts = array())
 | |
| 	{
 | |
| 
 | |
| 		if($this->logFile == null)
 | |
| 		{
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 		if(count($this->_allMessages))
 | |
| 		{
 | |
| 			$head = '  e107 CMS Log file : ' . $logTitle . '   ' . date('Y-m-d_H-i-s') . "\n";
 | |
| 			$head .= "-------------------------------------------------------------------------------------------\n\n";
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 		$text = '';
 | |
| 
 | |
| 		foreach($this->_allMessages as $m)
 | |
| 		{
 | |
| 			$text .= date('Y-m-d H:i:s', $m['time']) . "  \t" . str_pad($m['loglevel'], 10, ' ', STR_PAD_RIGHT) . "\t" . strip_tags($m['message']) . "\n";
 | |
| 		}
 | |
| 
 | |
| 		$date = ($append == true) ? date('Y-m-d') : date('Y-m-d_H-i-s') . '_' . crc32($text);
 | |
| 
 | |
| 
 | |
| 		$dir = e_LOG;
 | |
| 
 | |
| 		if(empty($this->_current_plugin))
 | |
| 		{
 | |
| 			$this->_current_plugin = deftrue('e_CURRENT_PLUGIN');
 | |
| 		}
 | |
| 
 | |
| 		if(!empty($this->_current_plugin)) // If it's a plugin, create a subfolder.
 | |
| 		{
 | |
| 			$dir = e_LOG . $this->_current_plugin . '/';
 | |
| 
 | |
| 			if(!is_dir($dir))
 | |
| 			{
 | |
| 				if(!mkdir($dir, 0755) && !is_dir($dir))
 | |
| 				{
 | |
| 					$this->add('Directory creation Failed', sprintf('Directory "%s" was not created', $dir));
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		$fileName = $dir . $date . '_' . $this->logFile . '.log';
 | |
| 
 | |
| 		if(!empty($opts['filename']))
 | |
| 		{
 | |
| 			$fileName = $dir . basename($opts['filename']);
 | |
| 		}
 | |
| 
 | |
| 		if($append == true)
 | |
| 		{
 | |
| 			$app = FILE_APPEND;
 | |
| 			if(!file_exists($fileName))
 | |
| 			{
 | |
| 				$text = $head . $text;
 | |
| 			}
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			$app = 0;
 | |
| 			$text = $head . $text;
 | |
| 		}
 | |
| 
 | |
| 		if(file_put_contents($fileName, $text, $app))
 | |
| 		{
 | |
| 			$this->_allMessages = array();
 | |
| 			$this->_current_plugin = null;
 | |
| 
 | |
| 			return $this->logFile;
 | |
| 		}
 | |
| 
 | |
| 		if(E107_DEBUG_LEVEL > 0 && getperms('0'))
 | |
| 		{
 | |
| 			e107::getMessage()->addDebug("Couldn't Save to Log File: " . $fileName);
 | |
| 		}
 | |
| 
 | |
| 		$this->_current_plugin = null;
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Set and save accumulated log to a file.
 | |
| 	 * Use addDebug(), addError() or addSuccess() prior to executing.
 | |
| 	 *
 | |
| 	 * @param string name without the extension. (ie. date prefix and .log suffix will be added automatically)
 | |
| 	 * @param string Title for use inside the Log file
 | |
| 	 * @param boolean true = append to file, false = new file each save.
 | |
| 	 */
 | |
| 	public function toFile($name, $logTitle = '', $append = false, $opts = array())
 | |
| 	{
 | |
| 
 | |
| 		$this->logFile = $name;
 | |
| 		$file = $this->saveToFile($logTitle, $append, $opts);
 | |
| 
 | |
| 		$this->logFile = null;
 | |
| 
 | |
| 		return $file;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| }
 |