diff options
| -rw-r--r-- | phpBB/common.php | 2 | ||||
| -rw-r--r-- | phpBB/config/services.yml | 12 | ||||
| -rw-r--r-- | phpBB/config/tables.yml | 1 | ||||
| -rw-r--r-- | phpBB/download/file.php | 1 | ||||
| -rw-r--r-- | phpBB/includes/functions.php | 72 | ||||
| -rw-r--r-- | phpBB/includes/functions_admin.php | 281 | ||||
| -rw-r--r-- | phpBB/includes/functions_container.php | 1 | ||||
| -rw-r--r-- | phpBB/includes/functions_user.php | 8 | ||||
| -rw-r--r-- | phpBB/includes/log/interface.php | 106 | ||||
| -rw-r--r-- | phpBB/includes/log/log.php | 739 | ||||
| -rw-r--r-- | phpBB/install/database_update.php | 1 | ||||
| -rw-r--r-- | phpBB/install/install_install.php | 5 | ||||
| -rw-r--r-- | tests/functions_user/group_user_attributes_test.php | 3 | ||||
| -rw-r--r-- | tests/log/add_test.php | 88 | ||||
| -rw-r--r-- | tests/log/fixtures/empty_log.xml | 15 | ||||
| -rw-r--r-- | tests/log/fixtures/full_log.xml | 166 | ||||
| -rw-r--r-- | tests/log/function_add_log_test.php | 193 | ||||
| -rw-r--r-- | tests/log/function_view_log_test.php | 344 | 
18 files changed, 1725 insertions, 313 deletions
| diff --git a/phpBB/common.php b/phpBB/common.php index 5c0feb87db..c33e2cbb1f 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -111,6 +111,8 @@ $config = $phpbb_container->get('config');  set_config(null, null, null, $config);  set_config_count(null, null, null, $config); +$phpbb_log = $phpbb_container->get('log'); +  // load extensions  $phpbb_extension_manager = $phpbb_container->get('ext.manager');  $phpbb_subscriber_loader = $phpbb_container->get('event.subscriber_loader'); diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml index 24e80ddaf0..7b2a24b2b3 100644 --- a/phpBB/config/services.yml +++ b/phpBB/config/services.yml @@ -187,6 +187,18 @@ services:          tags:              - { name: kernel.event_subscriber } +    log: +        class: phpbb_log +        arguments: +            - @dbal.conn +            - @user +            - @auth +            - @dispatcher +            - %core.root_path% +            - %core.adm_relative_path% +            - %core.php_ext% +            - %tables.log% +      notification_manager:          class: phpbb_notification_manager          arguments: diff --git a/phpBB/config/tables.yml b/phpBB/config/tables.yml index 10db8fbab6..b3093abf0c 100644 --- a/phpBB/config/tables.yml +++ b/phpBB/config/tables.yml @@ -1,6 +1,7 @@  parameters:      tables.config: %core.table_prefix%config      tables.ext: %core.table_prefix%ext +    tables.log: %core.table_prefix%log      tables.notification_types: %core.table_prefix%notification_types      tables.notifications: %core.table_prefix%notifications      tables.user_notifications: %core.table_prefix%user_notifications diff --git a/phpBB/download/file.php b/phpBB/download/file.php index 6537355bb0..91c05586a5 100644 --- a/phpBB/download/file.php +++ b/phpBB/download/file.php @@ -67,6 +67,7 @@ if (isset($_GET['avatar']))  	$phpbb_dispatcher = $phpbb_container->get('dispatcher');  	$request	= $phpbb_container->get('request');  	$db			= $phpbb_container->get('dbal.conn'); +	$phpbb_log	= $phpbb_container->get('log');  	// Connect to DB  	if (!@$db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false)) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 6a1f144967..c0fd3918dc 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -3582,69 +3582,49 @@ function parse_cfg_file($filename, $lines = false)  }  /** -* Add log event +* Add log entry +* +* @param	string	$mode				The mode defines which log_type is used and from which log the entry is retrieved +* @param	int		$forum_id			Mode 'mod' ONLY: forum id of the related item, NOT INCLUDED otherwise +* @param	int		$topic_id			Mode 'mod' ONLY: topic id of the related item, NOT INCLUDED otherwise +* @param	int		$reportee_id		Mode 'user' ONLY: user id of the reportee, NOT INCLUDED otherwise +* @param	string	$log_operation		Name of the operation +* @param	array	$additional_data	More arguments can be added, depending on the log_type +* +* @return	int|bool		Returns the log_id, if the entry was added to the database, false otherwise. +* +* @deprecated	Use $phpbb_log->add() instead  */  function add_log()  { -	global $db, $user; - -	// In phpBB 3.1.x i want to have logging in a class to be able to control it -	// For now, we need a quite hakish approach to circumvent logging for some actions -	// @todo implement cleanly -	if (!empty($GLOBALS['skip_add_log'])) -	{ -		return false; -	} +	global $phpbb_log, $user;  	$args = func_get_args(); +	$mode = array_shift($args); -	$mode			= array_shift($args); -	$reportee_id	= ($mode == 'user') ? intval(array_shift($args)) : ''; -	$forum_id		= ($mode == 'mod') ? intval(array_shift($args)) : ''; -	$topic_id		= ($mode == 'mod') ? intval(array_shift($args)) : ''; -	$action			= array_shift($args); -	$data			= (!sizeof($args)) ? '' : serialize($args); - -	$sql_ary = array( -		'user_id'		=> (empty($user->data)) ? ANONYMOUS : $user->data['user_id'], -		'log_ip'		=> $user->ip, -		'log_time'		=> time(), -		'log_operation'	=> $action, -		'log_data'		=> $data, -	); - +	// This looks kind of dirty, but add_log has some additional data before the log_operation +	$additional_data = array();  	switch ($mode)  	{  		case 'admin': -			$sql_ary['log_type'] = LOG_ADMIN; +		case 'critical':  		break; -  		case 'mod': -			$sql_ary += array( -				'log_type'	=> LOG_MOD, -				'forum_id'	=> $forum_id, -				'topic_id'	=> $topic_id -			); +			$additional_data['forum_id'] = array_shift($args); +			$additional_data['topic_id'] = array_shift($args);  		break; -  		case 'user': -			$sql_ary += array( -				'log_type'		=> LOG_USERS, -				'reportee_id'	=> $reportee_id -			); -		break; - -		case 'critical': -			$sql_ary['log_type'] = LOG_CRITICAL; +			$additional_data['reportee_id'] = array_shift($args);  		break; - -		default: -			return false;  	} -	$db->sql_query('INSERT INTO ' . LOG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); +	$log_operation = array_shift($args); +	$additional_data = array_merge($additional_data, $args); + +	$user_id = (empty($user->data)) ? ANONYMOUS : $user->data['user_id']; +	$user_ip = (empty($user->ip)) ? '' : $user->ip; -	return $db->sql_nextid(); +	return $phpbb_log->add($mode, $user_id, $user_ip, $log_operation, time(), $additional_data);  }  /** diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index baf107bcda..d273b9fb3a 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -2506,273 +2506,32 @@ function cache_moderators()  /**  * View log -* If $log_count is set to false, we will skip counting all entries in the database. +* +* @param	string	$mode			The mode defines which log_type is used and from which log the entry is retrieved +* @param	array	&$log			The result array with the logs +* @param	mixed	&$log_count		If $log_count is set to false, we will skip counting all entries in the database. +*									Otherwise an integer with the number of total matching entries is returned. +* @param	int		$limit			Limit the number of entries that are returned +* @param	int		$offset			Offset when fetching the log entries, f.e. when paginating +* @param	mixed	$forum_id		Restrict the log entries to the given forum_id (can also be an array of forum_ids) +* @param	int		$topic_id		Restrict the log entries to the given topic_id +* @param	int		$user_id		Restrict the log entries to the given user_id +* @param	int		$log_time		Only get log entries newer than the given timestamp +* @param	string	$sort_by		SQL order option, e.g. 'l.log_time DESC' +* @param	string	$keywords		Will only return log entries that have the keywords in log_operation or log_data +* +* @return	int				Returns the offset of the last valid page, if the specified offset was invalid (too high)  */  function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $limit_days = 0, $sort_by = 'l.log_time DESC', $keywords = '')  { -	global $db, $user, $auth, $phpEx, $phpbb_root_path, $phpbb_admin_path; - -	$topic_id_list = $reportee_id_list = $is_auth = $is_mod = array(); - -	$profile_url = (defined('IN_ADMIN')) ? append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview') : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile'); - -	switch ($mode) -	{ -		case 'admin': -			$log_type = LOG_ADMIN; -			$sql_forum = ''; -		break; - -		case 'mod': -			$log_type = LOG_MOD; -			$sql_forum = ''; - -			if ($topic_id) -			{ -				$sql_forum = 'AND l.topic_id = ' . (int) $topic_id; -			} -			else if (is_array($forum_id)) -			{ -				$sql_forum = 'AND ' . $db->sql_in_set('l.forum_id', array_map('intval', $forum_id)); -			} -			else if ($forum_id) -			{ -				$sql_forum = 'AND l.forum_id = ' . (int) $forum_id; -			} -		break; - -		case 'user': -			$log_type = LOG_USERS; -			$sql_forum = 'AND l.reportee_id = ' . (int) $user_id; -		break; - -		case 'users': -			$log_type = LOG_USERS; -			$sql_forum = ''; -		break; - -		case 'critical': -			$log_type = LOG_CRITICAL; -			$sql_forum = ''; -		break; - -		default: -			return; -	} - -	// Use no preg_quote for $keywords because this would lead to sole backslashes being added -	// We also use an OR connection here for spaces and the | string. Currently, regex is not supported for searching (but may come later). -	$keywords = preg_split('#[\s|]+#u', utf8_strtolower($keywords), 0, PREG_SPLIT_NO_EMPTY); -	$sql_keywords = ''; - -	if (!empty($keywords)) -	{ -		$keywords_pattern = array(); - -		// Build pattern and keywords... -		for ($i = 0, $num_keywords = sizeof($keywords); $i < $num_keywords; $i++) -		{ -			$keywords_pattern[] = preg_quote($keywords[$i], '#'); -			$keywords[$i] = $db->sql_like_expression($db->any_char . $keywords[$i] . $db->any_char); -		} +	global $phpbb_log; -		$keywords_pattern = '#' . implode('|', $keywords_pattern) . '#ui'; +	$count_logs = ($log_count !== false); -		$operations = array(); -		foreach ($user->lang as $key => $value) -		{ -			if (substr($key, 0, 4) == 'LOG_' && preg_match($keywords_pattern, $value)) -			{ -				$operations[] = $key; -			} -		} - -		$sql_keywords = 'AND ('; -		if (!empty($operations)) -		{ -			$sql_keywords .= $db->sql_in_set('l.log_operation', $operations) . ' OR '; -		} -		$sql_lower = $db->sql_lower_text('l.log_data'); -		$sql_keywords .= "$sql_lower " . implode(" OR $sql_lower ", $keywords) . ')'; -	} - -	if ($log_count !== false) -	{ -		$sql = 'SELECT COUNT(l.log_id) AS total_entries -			FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . " u -			WHERE l.log_type = $log_type -				AND l.user_id = u.user_id -				AND l.log_time >= $limit_days -				$sql_keywords -				$sql_forum"; -		$result = $db->sql_query($sql); -		$log_count = (int) $db->sql_fetchfield('total_entries'); -		$db->sql_freeresult($result); -	} - -	// $log_count may be false here if false was passed in for it, -	// because in this case we did not run the COUNT() query above. -	// If we ran the COUNT() query and it returned zero rows, return; -	// otherwise query for logs below. -	if ($log_count === 0) -	{ -		// Save the queries, because there are no logs to display -		return 0; -	} - -	if ($offset >= $log_count) -	{ -		$offset = ($offset - $limit < 0) ? 0 : $offset - $limit; -	} - -	$sql = "SELECT l.*, u.username, u.username_clean, u.user_colour -		FROM " . LOG_TABLE . " l, " . USERS_TABLE . " u -		WHERE l.log_type = $log_type -			AND u.user_id = l.user_id -			" . (($limit_days) ? "AND l.log_time >= $limit_days" : '') . " -			$sql_keywords -			$sql_forum -		ORDER BY $sort_by"; -	$result = $db->sql_query_limit($sql, $limit, $offset); - -	$i = 0; -	$log = array(); -	while ($row = $db->sql_fetchrow($result)) -	{ -		if ($row['topic_id']) -		{ -			$topic_id_list[] = $row['topic_id']; -		} - -		if ($row['reportee_id']) -		{ -			$reportee_id_list[] = $row['reportee_id']; -		} +	$log = $phpbb_log->get_logs($mode, $count_logs, $limit, $offset, $forum_id, $topic_id, $user_id, $limit_days, $sort_by, $keywords); +	$log_count = $phpbb_log->get_log_count(); -		$log[$i] = array( -			'id'				=> $row['log_id'], - -			'reportee_id'			=> $row['reportee_id'], -			'reportee_username'		=> '', -			'reportee_username_full'=> '', - -			'user_id'			=> $row['user_id'], -			'username'			=> $row['username'], -			'username_full'		=> get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, $profile_url), - -			'ip'				=> $row['log_ip'], -			'time'				=> $row['log_time'], -			'forum_id'			=> $row['forum_id'], -			'topic_id'			=> $row['topic_id'], - -			'viewforum'			=> ($row['forum_id'] && $auth->acl_get('f_read', $row['forum_id'])) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : false, -			'action'			=> (isset($user->lang[$row['log_operation']])) ? $user->lang[$row['log_operation']] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}', -		); - -		if (!empty($row['log_data'])) -		{ -			$log_data_ary = @unserialize($row['log_data']); -			$log_data_ary = ($log_data_ary === false) ? array() : $log_data_ary; - -			if (isset($user->lang[$row['log_operation']])) -			{ -				// Check if there are more occurrences of % than arguments, if there are we fill out the arguments array -				// It doesn't matter if we add more arguments than placeholders -				if ((substr_count($log[$i]['action'], '%') - sizeof($log_data_ary)) > 0) -				{ -					$log_data_ary = array_merge($log_data_ary, array_fill(0, substr_count($log[$i]['action'], '%') - sizeof($log_data_ary), '')); -				} - -				$log[$i]['action'] = vsprintf($log[$i]['action'], $log_data_ary); - -				// If within the admin panel we do not censor text out -				if (defined('IN_ADMIN')) -				{ -					$log[$i]['action'] = bbcode_nl2br($log[$i]['action']); -				} -				else -				{ -					$log[$i]['action'] = bbcode_nl2br(censor_text($log[$i]['action'])); -				} -			} -			else if (!empty($log_data_ary)) -			{ -				$log[$i]['action'] .= '<br />' . implode('', $log_data_ary); -			} - -			/* Apply make_clickable... has to be seen if it is for good. :/ -			// Seems to be not for the moment, reconsider later... -			$log[$i]['action'] = make_clickable($log[$i]['action']); -			*/ -		} - -		$i++; -	} -	$db->sql_freeresult($result); - -	if (sizeof($topic_id_list)) -	{ -		$topic_id_list = array_unique($topic_id_list); - -		// This query is not really needed if move_topics() updates the forum_id field, -		// although it's also used to determine if the topic still exists in the database -		$sql = 'SELECT topic_id, forum_id -			FROM ' . TOPICS_TABLE . ' -			WHERE ' . $db->sql_in_set('topic_id', array_map('intval', $topic_id_list)); -		$result = $db->sql_query($sql); - -		$default_forum_id = 0; - -		while ($row = $db->sql_fetchrow($result)) -		{ -			if ($auth->acl_get('f_read', $row['forum_id'])) -			{ -				$is_auth[$row['topic_id']] = $row['forum_id']; -			} - -			if ($auth->acl_gets('a_', 'm_', $row['forum_id'])) -			{ -				$is_mod[$row['topic_id']] = $row['forum_id']; -			} -		} -		$db->sql_freeresult($result); - -		foreach ($log as $key => $row) -		{ -			$log[$key]['viewtopic'] = (isset($is_auth[$row['topic_id']])) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $is_auth[$row['topic_id']] . '&t=' . $row['topic_id']) : false; -			$log[$key]['viewlogs'] = (isset($is_mod[$row['topic_id']])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=logs&mode=topic_logs&t=' . $row['topic_id'], true, $user->session_id) : false; -		} -	} - -	if (sizeof($reportee_id_list)) -	{ -		$reportee_id_list = array_unique($reportee_id_list); -		$reportee_names_list = array(); - -		$sql = 'SELECT user_id, username, user_colour -			FROM ' . USERS_TABLE . ' -			WHERE ' . $db->sql_in_set('user_id', $reportee_id_list); -		$result = $db->sql_query($sql); - -		while ($row = $db->sql_fetchrow($result)) -		{ -			$reportee_names_list[$row['user_id']] = $row; -		} -		$db->sql_freeresult($result); - -		foreach ($log as $key => $row) -		{ -			if (!isset($reportee_names_list[$row['reportee_id']])) -			{ -				continue; -			} - -			$log[$key]['reportee_username'] = $reportee_names_list[$row['reportee_id']]['username']; -			$log[$key]['reportee_username_full'] = get_username_string('full', $row['reportee_id'], $reportee_names_list[$row['reportee_id']]['username'], $reportee_names_list[$row['reportee_id']]['user_colour'], false, $profile_url); -		} -	} - -	return $offset; +	return $phpbb_log->get_valid_offset();  }  /** diff --git a/phpBB/includes/functions_container.php b/phpBB/includes/functions_container.php index a3ed21c35b..106b7d75cc 100644 --- a/phpBB/includes/functions_container.php +++ b/phpBB/includes/functions_container.php @@ -57,6 +57,7 @@ function phpbb_create_install_container($phpbb_root_path, $php_ext)  	$container = phpbb_create_container(array($core), $phpbb_root_path, $php_ext);  	$container->setParameter('core.root_path', $phpbb_root_path); +	$container->setParameter('core.adm_relative_path', $phpbb_adm_relative_path);  	$container->setParameter('core.php_ext', $php_ext);  	$container->setParameter('core.table_prefix', ''); diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index f05bf76ed8..bc636acabb 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -310,8 +310,10 @@ function user_add($user_row, $cp_data = false)  		if ($add_group_id)  		{ -			// Because these actions only fill the log unneccessarily we skip the add_log() entry with a little hack. :/ -			$GLOBALS['skip_add_log'] = true; +			global $phpbb_log; + +			// Because these actions only fill the log unneccessarily we skip the add_log() entry. +			$phpbb_log->disable('admin');  			// Add user to "newly registered users" group and set to default group if admin specified so.  			if ($config['new_member_group_default']) @@ -324,7 +326,7 @@ function user_add($user_row, $cp_data = false)  				group_user_add($add_group_id, $user_id);  			} -			unset($GLOBALS['skip_add_log']); +			$phpbb_log->enable('admin');  		}  	} diff --git a/phpBB/includes/log/interface.php b/phpBB/includes/log/interface.php new file mode 100644 index 0000000000..3b459c9bdf --- /dev/null +++ b/phpBB/includes/log/interface.php @@ -0,0 +1,106 @@ +<?php +/** +* +* @package phpbb_log +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* The interface for the log-system. +* +* @package phpbb_log +*/ +interface phpbb_log_interface +{ +	/** +	* This function returns the state of the log system. +	* +	* @param	string	$type	The log type we want to check. Empty to get +	*							global log status. +	* +	* @return	bool	True if log for the type is enabled +	*/ +	public function is_enabled($type = ''); + +	/** +	* Disable log +	* +	* This function allows disabling the log system or parts of it, for this +	* page call. When add_log is called and the type is disabled, +	* the log will not be added to the database. +	* +	* @param	mixed	$type	The log type we want to disable. Empty to +	*						disable all logs. Can also be an array of types. +	* +	* @return	null +	*/ +	public function disable($type = ''); + +	/** +	* Enable log +	* +	* This function allows re-enabling the log system. +	* +	* @param	mixed	$type	The log type we want to enable. Empty to +	*						enable all logs. Can also be an array of types. +	* +	* @return	null +	*/ +	public function enable($type = ''); + +	/** +	* Adds a log entry to the database +	* +	* @param	string	$mode				The mode defines which log_type is used and from which log the entry is retrieved +	* @param	int		$user_id			User ID of the user +	* @param	string	$log_ip				IP address of the user +	* @param	string	$log_operation		Name of the operation +	* @param	int		$log_time			Timestamp when the log entry was added, if empty time() will be used +	* @param	array	$additional_data	More arguments can be added, depending on the log_type +	* +	* @return	int|bool		Returns the log_id, if the entry was added to the database, false otherwise. +	*/ +	public function add($mode, $user_id, $log_ip, $log_operation, $log_time = false, $additional_data = array()); + +	/** +	* Grab the logs from the database +	* +	* @param	string	$mode			The mode defines which log_type is used and ifrom which log the entry is retrieved +	* @param	bool	$count_logs		Shall we count all matching log entries? +	* @param	int		$limit			Limit the number of entries that are returned +	* @param	int		$offset			Offset when fetching the log entries, f.e. when paginating +	* @param	mixed	$forum_id		Restrict the log entries to the given forum_id (can also be an array of forum_ids) +	* @param	int		$topic_id		Restrict the log entries to the given topic_id +	* @param	int		$user_id		Restrict the log entries to the given user_id +	* @param	int		$log_time		Only get log entries newer than the given timestamp +	* @param	string	$sort_by		SQL order option, e.g. 'l.log_time DESC' +	* @param	string	$keywords		Will only return log entries that have the keywords in log_operation or log_data +	* +	* @return	array			The result array with the logs +	*/ +	public function get_logs($mode, $count_logs = true, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $log_time = 0, $sort_by = 'l.log_time DESC', $keywords = ''); + +	/** +	* Get total log count +	* +	* @return	int			Returns the number of matching logs from the last call to get_logs() +	*/ +	public function get_log_count(); + +	/** +	* Get offset of the last valid page +	* +	* @return	int			Returns the offset of the last valid page from the last call to get_logs() +	*/ +	public function get_valid_offset(); +} diff --git a/phpBB/includes/log/log.php b/phpBB/includes/log/log.php new file mode 100644 index 0000000000..7a26858348 --- /dev/null +++ b/phpBB/includes/log/log.php @@ -0,0 +1,739 @@ +<?php +/** +* +* @package phpbb_log +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* This class is used to add entries into the log table. +* +* @package phpbb_log +*/ +class phpbb_log implements phpbb_log_interface +{ +	/** +	* If set, administrative user profile links will be returned and messages +	* will not be censored. +	* @var bool +	*/ +	protected $is_in_admin; + +	/** +	* An array with the disabled log types. Logs of such types will not be +	* added when add_log() is called. +	* @var array +	*/ +	protected $disabled_types; + +	/** +	* Keeps the total log count of the last call to get_logs() +	* @var int +	*/ +	protected $entry_count; + +	/** +	* Keeps the offset of the last valid page of the last call to get_logs() +	* @var int +	*/ +	protected $last_page_offset; + +	/** +	* The table we use to store our logs. +	* @var string +	*/ +	protected $log_table; + +	/** +	* Database object +	* @var phpbb_db_driver +	*/ +	protected $db; + +	/** +	* User object +	* @var phpbb_user +	*/ +	protected $user; + +	/** +	* Auth object +	* @var phpbb_auth +	*/ +	protected $auth; + +	/** +	* Event dispatcher object +	* @var phpbb_dispatcher +	*/ +	protected $dispatcher; + +	/** +	* phpBB root path +	* @var string +	*/ +	protected $phpbb_root_path; + +	/** +	* Admin root path +	* @var string +	*/ +	protected $phpbb_admin_path; + +	/** +	* PHP Extension +	* @var string +	*/ +	protected $php_ext; + +	/** +	* Constructor +	* +	* @param	phpbb_db_driver	$db		Database object +	* @param	phpbb_user		$user	User object +	* @param	phpbb_auth		$auth	Auth object +	* @param	phpbb_dispatcher	$phpbb_dispatcher	Event dispatcher +	* @param	string		$phpbb_root_path		Root path +	* @param	string		$relative_admin_path	Relative admin root path +	* @param	string		$php_ext			PHP Extension +	* @param	string		$log_table		Name of the table we use to store our logs +	* @return	null +	*/ +	public function __construct($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, $relative_admin_path, $php_ext, $log_table) +	{ +		$this->db = $db; +		$this->user = $user; +		$this->auth = $auth; +		$this->dispatcher = $phpbb_dispatcher; +		$this->phpbb_root_path = $phpbb_root_path; +		$this->phpbb_admin_path = $this->phpbb_root_path . $relative_admin_path; +		$this->php_ext = $php_ext; +		$this->log_table = $log_table; + +		/* +		* IN_ADMIN is set after the session is created, +		* so we need to take ADMIN_START into account as well, otherwise +		* it will not work for the phpbb_log object we create in common.php +		*/ +		$this->set_is_admin((defined('ADMIN_START') && ADMIN_START) || (defined('IN_ADMIN') && IN_ADMIN)); +		$this->enable(); +	} + +	/** +	* Set is_in_admin in order to return administrative user profile links +	* in get_logs() +	* +	* @param	bool	$is_in_admin		Are we called from within the acp? +	* @return	null +	*/ +	public function set_is_admin($is_in_admin) +	{ +		$this->is_in_admin = (bool) $is_in_admin; +	} + +	/** +	* Returns the is_in_admin option +	* +	* @return	bool +	*/ +	public function get_is_admin() +	{ +		return $this->is_in_admin; +	} + +	/** +	* Set table name +	* +	* @param	string	$log_table		Can overwrite the table to use for the logs +	* @return	null +	*/ +	public function set_log_table($log_table) +	{ +		$this->log_table = $log_table; +	} + +	/** +	* This function returns the state of the log system. +	* +	* {@inheritDoc} +	*/ +	public function is_enabled($type = '') +	{ +		if ($type == '' || $type == 'all') +		{ +			return !isset($this->disabled_types['all']); +		} +		return !isset($this->disabled_types[$type]) && !isset($this->disabled_types['all']); +	} + +	/** +	* Disable log +	* +	* This function allows disabling the log system or parts of it, for this +	* page call. When add_log is called and the type is disabled, +	* the log will not be added to the database. +	* +	* {@inheritDoc} +	*/ +	public function disable($type = '') +	{ +		if (is_array($type)) +		{ +			foreach ($type as $disable_type) +			{ +				$this->disable($disable_type); +			} +			return; +		} + +		// Empty string is an equivalent for all types. +		if ($type == '') +		{ +			$type = 'all'; +		} +		$this->disabled_types[$type] = true; +	} + +	/** +	* Enable log +	* +	* This function allows re-enabling the log system. +	* +	* {@inheritDoc} +	*/ +	public function enable($type = '') +	{ +		if (is_array($type)) +		{ +			foreach ($type as $enable_type) +			{ +				$this->enable($enable_type); +			} +			return; +		} + +		if ($type == '' || $type == 'all') +		{ +			$this->disabled_types = array(); +			return; +		} +		unset($this->disabled_types[$type]); +	} + +	/** +	* Adds a log to the database +	* +	* {@inheritDoc} +	*/ +	public function add($mode, $user_id, $log_ip, $log_operation, $log_time = false, $additional_data = array()) +	{ +		if (!$this->is_enabled($mode)) +		{ +			return false; +		} + +		if ($log_time == false) +		{ +			$log_time = time(); +		} + +		$sql_ary = array( +			'user_id'		=> $user_id, +			'log_ip'		=> $log_ip, +			'log_time'		=> $log_time, +			'log_operation'	=> $log_operation, +		); + +		switch ($mode) +		{ +			case 'admin': +				$sql_ary += array( +					'log_type'		=> LOG_ADMIN, +					'log_data'		=> (!empty($additional_data)) ? serialize($additional_data) : '', +				); +			break; + +			case 'mod': +				$forum_id = (int) $additional_data['forum_id']; +				unset($additional_data['forum_id']); +				$topic_id = (int) $additional_data['topic_id']; +				unset($additional_data['topic_id']); +				$sql_ary += array( +					'log_type'		=> LOG_MOD, +					'forum_id'		=> $forum_id, +					'topic_id'		=> $topic_id, +					'log_data'		=> (!empty($additional_data)) ? serialize($additional_data) : '', +				); +			break; + +			case 'user': +				$reportee_id = (int) $additional_data['reportee_id']; +				unset($additional_data['reportee_id']); + +				$sql_ary += array( +					'log_type'		=> LOG_USERS, +					'reportee_id'	=> $reportee_id, +					'log_data'		=> (!empty($additional_data)) ? serialize($additional_data) : '', +				); +			break; + +			case 'critical': +				$sql_ary += array( +					'log_type'		=> LOG_CRITICAL, +					'log_data'		=> (!empty($additional_data)) ? serialize($additional_data) : '', +				); +			break; +		} + +		/** +		* Allows to modify log data before we add it to the database +		* +		* NOTE: if sql_ary does not contain a log_type value, the entry will +		* not be stored in the database. So ensure to set it, if needed. +		* +		* @event core.add_log +		* @var	string	mode			Mode of the entry we log +		* @var	int		user_id			ID of the user who triggered the log +		* @var	string	log_ip			IP of the user who triggered the log +		* @var	string	log_operation	Language key of the log operation +		* @var	int		log_time		Timestamp, when the log was added +		* @var	array	additional_data	Array with additional log data +		* @var	array	sql_ary			Array with log data we insert into the +		*							database. If sql_ary[log_type] is not set, +		*							we won't add the entry to the database. +		* @since 3.1-A1 +		*/ +		$vars = array('mode', 'user_id', 'log_ip', 'log_operation', 'log_time', 'additional_data', 'sql_ary'); +		extract($this->dispatcher->trigger_event('core.add_log', $vars)); + +		// We didn't find a log_type, so we don't save it in the database. +		if (!isset($sql_ary['log_type'])) +		{ +			return false; +		} + +		$this->db->sql_query('INSERT INTO ' . $this->log_table . ' ' . $this->db->sql_build_array('INSERT', $sql_ary)); + +		return $this->db->sql_nextid(); +	} + +	/** +	* Grab the logs from the database +	* +	* {@inheritDoc} +	*/ +	public function get_logs($mode, $count_logs = true, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $log_time = 0, $sort_by = 'l.log_time DESC', $keywords = '') +	{ +		$this->entry_count = 0; +		$this->last_page_offset = $offset; + +		$topic_id_list = $reportee_id_list = array(); + +		$profile_url = ($this->get_is_admin() && $this->phpbb_admin_path) ? append_sid("{$this->phpbb_admin_path}index.{$this->php_ext}", 'i=users&mode=overview') : append_sid("{$this->phpbb_root_path}memberlist.{$this->php_ext}", 'mode=viewprofile'); + +		switch ($mode) +		{ +			case 'admin': +				$log_type = LOG_ADMIN; +				$sql_additional = ''; +			break; + +			case 'mod': +				$log_type = LOG_MOD; +				$sql_additional = ''; + +				if ($topic_id) +				{ +					$sql_additional = 'AND l.topic_id = ' . (int) $topic_id; +				} +				else if (is_array($forum_id)) +				{ +					$sql_additional = 'AND ' . $this->db->sql_in_set('l.forum_id', array_map('intval', $forum_id)); +				} +				else if ($forum_id) +				{ +					$sql_additional = 'AND l.forum_id = ' . (int) $forum_id; +				} +			break; + +			case 'user': +				$log_type = LOG_USERS; +				$sql_additional = 'AND l.reportee_id = ' . (int) $user_id; +			break; + +			case 'users': +				$log_type = LOG_USERS; +				$sql_additional = ''; +			break; + +			case 'critical': +				$log_type = LOG_CRITICAL; +				$sql_additional = ''; +			break; + +			default: +				$log_type = false; +				$sql_additional = ''; +		} + +		/** +		* Overwrite log type and limitations before we count and get the logs +		* +		* NOTE: if log_type is false, no entries will be returned. +		* +		* @event core.get_logs_modify_type +		* @var	string	mode		Mode of the entries we display +		* @var	bool	count_logs	Do we count all matching entries? +		* @var	int		limit		Limit the number of entries +		* @var	int		offset		Offset when fetching the entries +		* @var	mixed	forum_id	Limit entries to the forum_id, +		*							can also be an array of forum_ids +		* @var	int		topic_id	Limit entries to the topic_id +		* @var	int		user_id		Limit entries to the user_id +		* @var	int		log_time	Limit maximum age of log entries +		* @var	string	sort_by		SQL order option +		* @var	string	keywords	Will only return entries that have the +		*							keywords in log_operation or log_data +		* @var	string	profile_url	URL to the users profile +		* @var	int		log_type	Limit logs to a certain type. If log_type +		*							is false, no entries will be returned. +		* @var	string	sql_additional	Additional conditions for the entries, +		*								e.g.: 'AND l.forum_id = 1' +		* @since 3.1-A1 +		*/ +		$vars = array('mode', 'count_logs', 'limit', 'offset', 'forum_id', 'topic_id', 'user_id', 'log_time', 'sort_by', 'keywords', 'profile_url', 'log_type', 'sql_additional'); +		extract($this->dispatcher->trigger_event('core.get_logs_modify_type', $vars)); + +		if ($log_type === false) +		{ +			$this->last_page_offset = 0; +			return array(); +		} + +		$sql_keywords = ''; +		if (!empty($keywords)) +		{ +			// Get the SQL condition for our keywords +			$sql_keywords = $this->generate_sql_keyword($keywords); +		} + +		if ($count_logs) +		{ +			$sql = 'SELECT COUNT(l.log_id) AS total_entries +				FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . ' u +				WHERE l.log_type = ' . (int) $log_type . ' +					AND l.user_id = u.user_id +					AND l.log_time >= ' . (int) $log_time . " +					$sql_keywords +					$sql_additional"; +			$result = $this->db->sql_query($sql); +			$this->entry_count = (int) $this->db->sql_fetchfield('total_entries'); +			$this->db->sql_freeresult($result); + +			if ($this->entry_count == 0) +			{ +				// Save the queries, because there are no logs to display +				$this->last_page_offset = 0; +				return array(); +			} + +			// Return the user to the last page that is valid +			while ($this->last_page_offset >= $this->entry_count) +			{ +				$this->last_page_offset = max(0, $this->last_page_offset - $limit); +			} +		} + +		$sql = 'SELECT l.*, u.username, u.username_clean, u.user_colour +			FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . ' u +			WHERE l.log_type = ' . (int) $log_type . ' +				AND u.user_id = l.user_id +				' . (($log_time) ? 'AND l.log_time >= ' . (int) $log_time : '') . " +				$sql_keywords +				$sql_additional +			ORDER BY $sort_by"; +		$result = $this->db->sql_query_limit($sql, $limit, $this->last_page_offset); + +		$i = 0; +		$log = array(); +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$row['forum_id'] = (int) $row['forum_id']; +			if ($row['topic_id']) +			{ +				$topic_id_list[] = (int) $row['topic_id']; +			} + +			if ($row['reportee_id']) +			{ +				$reportee_id_list[] = (int) $row['reportee_id']; +			} + +			$log_entry_data = array( +				'id'				=> (int) $row['log_id'], + +				'reportee_id'			=> (int) $row['reportee_id'], +				'reportee_username'		=> '', +				'reportee_username_full'=> '', + +				'user_id'			=> (int) $row['user_id'], +				'username'			=> $row['username'], +				'username_full'		=> get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, $profile_url), + +				'ip'				=> $row['log_ip'], +				'time'				=> (int) $row['log_time'], +				'forum_id'			=> (int) $row['forum_id'], +				'topic_id'			=> (int) $row['topic_id'], + +				'viewforum'			=> ($row['forum_id'] && $this->auth->acl_get('f_read', $row['forum_id'])) ? append_sid("{$this->phpbb_root_path}viewforum.{$this->php_ext}", 'f=' . $row['forum_id']) : false, +				'action'			=> (isset($this->user->lang[$row['log_operation']])) ? $this->user->lang[$row['log_operation']] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}', +			); + +			/** +			* Modify the entry's data before it is returned +			* +			* @event core.get_logs_modify_entry_data +			* @var	array	row			Entry data from the database +			* @var	array	log_entry_data	Entry's data which is returned +			* @since 3.1-A1 +			*/ +			$vars = array('row', 'log_entry_data'); +			extract($this->dispatcher->trigger_event('core.get_logs_modify_entry_data', $vars)); + +			$log[$i] = $log_entry_data; + +			if (!empty($row['log_data'])) +			{ +				$log_data_ary = unserialize($row['log_data']); +				$log_data_ary = ($log_data_ary !== false) ? $log_data_ary : array(); + +				if (isset($this->user->lang[$row['log_operation']])) +				{ +					// Check if there are more occurrences of % than +					// arguments, if there are we fill out the arguments +					// array. It doesn't matter if we add more arguments than +					// placeholders. +					if ((substr_count($log[$i]['action'], '%') - sizeof($log_data_ary)) > 0) +					{ +						$log_data_ary = array_merge($log_data_ary, array_fill(0, substr_count($log[$i]['action'], '%') - sizeof($log_data_ary), '')); +					} + +					$log[$i]['action'] = vsprintf($log[$i]['action'], $log_data_ary); + +					// If within the admin panel we do not censor text out +					if ($this->get_is_admin()) +					{ +						$log[$i]['action'] = bbcode_nl2br($log[$i]['action']); +					} +					else +					{ +						$log[$i]['action'] = bbcode_nl2br(censor_text($log[$i]['action'])); +					} +				} +				else if (!empty($log_data_ary)) +				{ +					$log[$i]['action'] .= '<br />' . implode('', $log_data_ary); +				} + +				/* Apply make_clickable... has to be seen if it is for good. :/ +				// Seems to be not for the moment, reconsider later... +				$log[$i]['action'] = make_clickable($log[$i]['action']); +				*/ +			} + +			$i++; +		} +		$this->db->sql_freeresult($result); + +		/** +		* Get some additional data after we got all log entries +		* +		* @event core.get_logs_get_additional_data +		* @var	array	log			Array with all our log entries +		* @var	array	topic_id_list		Array of topic ids, for which we +		*									get the permission data +		* @var	array	reportee_id_list	Array of additional user IDs we +		*									get the username strings for +		* @since 3.1-A1 +		*/ +		$vars = array('log', 'topic_id_list', 'reportee_id_list'); +		extract($this->dispatcher->trigger_event('core.get_logs_get_additional_data', $vars)); + +		if (sizeof($topic_id_list)) +		{ +			$topic_auth = $this->get_topic_auth($topic_id_list); + +			foreach ($log as $key => $row) +			{ +				$log[$key]['viewtopic'] = (isset($topic_auth['f_read'][$row['topic_id']])) ? append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", 'f=' . $topic_auth['f_read'][$row['topic_id']] . '&t=' . $row['topic_id']) : false; +				$log[$key]['viewlogs'] = (isset($topic_auth['m_'][$row['topic_id']])) ? append_sid("{$this->phpbb_root_path}mcp.{$this->php_ext}", 'i=logs&mode=topic_logs&t=' . $row['topic_id'], true, $this->user->session_id) : false; +			} +		} + +		if (sizeof($reportee_id_list)) +		{ +			$reportee_data_list = $this->get_reportee_data($reportee_id_list); + +			foreach ($log as $key => $row) +			{ +				if (!isset($reportee_data_list[$row['reportee_id']])) +				{ +					continue; +				} + +				$log[$key]['reportee_username'] = $reportee_data_list[$row['reportee_id']]['username']; +				$log[$key]['reportee_username_full'] = get_username_string('full', $row['reportee_id'], $reportee_data_list[$row['reportee_id']]['username'], $reportee_data_list[$row['reportee_id']]['user_colour'], false, $profile_url); +			} +		} + +		return $log; +	} + +	/** +	* Generates a sql condition for the specified keywords +	* +	* @param	string	$keywords	The keywords the user specified to search for +	* +	* @return	string		Returns the SQL condition searching for the keywords +	*/ +	protected function generate_sql_keyword($keywords) +	{ +		// Use no preg_quote for $keywords because this would lead to sole +		// backslashes being added. We also use an OR connection here for +		// spaces and the | string. Currently, regex is not supported for +		// searching (but may come later). +		$keywords = preg_split('#[\s|]+#u', utf8_strtolower($keywords), 0, PREG_SPLIT_NO_EMPTY); +		$sql_keywords = ''; + +		if (!empty($keywords)) +		{ +			$keywords_pattern = array(); + +			// Build pattern and keywords... +			for ($i = 0, $num_keywords = sizeof($keywords); $i < $num_keywords; $i++) +			{ +				$keywords_pattern[] = preg_quote($keywords[$i], '#'); +				$keywords[$i] = $this->db->sql_like_expression($this->db->any_char . $keywords[$i] . $this->db->any_char); +			} + +			$keywords_pattern = '#' . implode('|', $keywords_pattern) . '#ui'; + +			$operations = array(); +			foreach ($this->user->lang as $key => $value) +			{ +				if (substr($key, 0, 4) == 'LOG_' && preg_match($keywords_pattern, $value)) +				{ +					$operations[] = $key; +				} +			} + +			$sql_keywords = 'AND ('; +			if (!empty($operations)) +			{ +				$sql_keywords .= $this->db->sql_in_set('l.log_operation', $operations) . ' OR '; +			} +			$sql_lower = $this->db->sql_lower_text('l.log_data'); +			$sql_keywords .= " $sql_lower " . implode(" OR $sql_lower ", $keywords) . ')'; +		} + +		return $sql_keywords; +	} + +	/** +	* Determine whether the user is allowed to read and/or moderate the forum of the topic +	* +	* @param	array	$topic_ids	Array with the topic ids +	* +	* @return	array		Returns an array with two keys 'm_' and 'read_f' which are also an array of topic_id => forum_id sets when the permissions are given. Sample: +	*						array( +	*							'permission' => array( +	*								topic_id => forum_id +	*							), +	*						), +	*/ +	protected function get_topic_auth(array $topic_ids) +	{ +		$forum_auth = array('f_read' => array(), 'm_' => array()); +		$topic_ids = array_unique($topic_ids); + +		$sql = 'SELECT topic_id, forum_id +			FROM ' . TOPICS_TABLE . ' +			WHERE ' . $this->db->sql_in_set('topic_id', array_map('intval', $topic_ids)); +		$result = $this->db->sql_query($sql); + +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$row['topic_id'] = (int) $row['topic_id']; +			$row['forum_id'] = (int) $row['forum_id']; + +			if ($this->auth->acl_get('f_read', $row['forum_id'])) +			{ +				$forum_auth['f_read'][$row['topic_id']] = $row['forum_id']; +			} + +			if ($this->auth->acl_gets('a_', 'm_', $row['forum_id'])) +			{ +				$forum_auth['m_'][$row['topic_id']] = $row['forum_id']; +			} +		} +		$this->db->sql_freeresult($result); + +		return $forum_auth; +	} + +	/** +	* Get the data for all reportee from the database +	* +	* @param	array	$reportee_ids	Array with the user ids of the reportees +	* +	* @return	array		Returns an array with the reportee data +	*/ +	protected function get_reportee_data(array $reportee_ids) +	{ +		$reportee_ids = array_unique($reportee_ids); +		$reportee_data_list = array(); + +		$sql = 'SELECT user_id, username, user_colour +			FROM ' . USERS_TABLE . ' +			WHERE ' . $this->db->sql_in_set('user_id', $reportee_ids); +		$result = $this->db->sql_query($sql); + +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			$reportee_data_list[$row['user_id']] = $row; +		} +		$this->db->sql_freeresult($result); + +		return $reportee_data_list; +	} + +	/** +	* Get total log count +	* +	* {@inheritDoc} +	*/ +	public function get_log_count() +	{ +		return ($this->entry_count) ? $this->entry_count : 0; +	} + +	/** +	* Get offset of the last valid log page +	* +	* {@inheritDoc} +	*/ +	public function get_valid_offset() +	{ +		return ($this->last_page_offset) ? $this->last_page_offset : 0; +	} +} diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 3382e57e76..2ecddf49d4 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -123,6 +123,7 @@ $request	= $phpbb_container->get('request');  $user		= $phpbb_container->get('user');  $auth		= $phpbb_container->get('auth');  $db			= $phpbb_container->get('dbal.conn'); +$phpbb_log	= $phpbb_container->get('log');  // make sure request_var uses this request instance  request_var('', 0, false, false, $request); // "dependency injection" for a function diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index 4cc154509c..67e368e34d 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -53,7 +53,7 @@ class install_install extends module  	function main($mode, $sub)  	{  		global $lang, $template, $language, $phpbb_root_path, $phpEx; -		global $phpbb_container, $cache; +		global $phpbb_container, $cache, $phpbb_log;  		switch ($sub)  		{ @@ -105,8 +105,9 @@ class install_install extends module  				// Create a normal container now  				$phpbb_container = phpbb_create_default_container($phpbb_root_path, $phpEx); -				// Sets the global $cache variable +				// Sets the global variables  				$cache = $phpbb_container->get('cache'); +				$phpbb_log = $phpbb_container->get('log');  				$this->build_search_index($mode, $sub);  				$this->add_modules($mode, $sub); diff --git a/tests/functions_user/group_user_attributes_test.php b/tests/functions_user/group_user_attributes_test.php index f13156c2cc..4336fd894e 100644 --- a/tests/functions_user/group_user_attributes_test.php +++ b/tests/functions_user/group_user_attributes_test.php @@ -125,7 +125,7 @@ class phpbb_functions_user_group_user_attributes_test extends phpbb_database_tes  	*/  	public function test_group_user_attributes($description, $user_id, $group_id, $group_row, $expected)  	{ -		global $auth, $cache, $db, $phpbb_dispatcher, $user, $phpbb_container; +		global $auth, $cache, $db, $phpbb_dispatcher, $user, $phpbb_container, $phpbb_log, $phpbb_root_path, $phpEx;  		$user->ip = '';  		$cache = new phpbb_mock_cache; @@ -141,6 +141,7 @@ class phpbb_functions_user_group_user_attributes_test extends phpbb_database_tes  			->method('get')  			->with('cache.driver')  			->will($this->returnValue($cache_driver)); +		$phpbb_log = new phpbb_log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE);  		group_user_attributes('default', $group_id, array($user_id), false, 'group_name', $group_row); diff --git a/tests/log/add_test.php b/tests/log/add_test.php new file mode 100644 index 0000000000..a5f93232f2 --- /dev/null +++ b/tests/log/add_test.php @@ -0,0 +1,88 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + +class phpbb_log_add_test extends phpbb_database_test_case +{ +	public function getDataSet() +	{ +		return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/empty_log.xml'); +	} + +	public function test_log_enabled() +	{ +		global $phpbb_root_path, $phpEx, $db, $phpbb_dispatcher; + +		$db = $this->new_dbal(); +		$cache = new phpbb_mock_cache; +		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); +		$user = $this->getMock('phpbb_user'); +		$auth = $this->getMock('phpbb_auth'); + +		$log = new phpbb_log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); + +		$this->assertTrue($log->is_enabled(), 'Initialise failed'); + +		$log->disable(); +		$this->assertFalse($log->is_enabled(), 'Disable all failed'); + +		$log->enable(); +		$this->assertTrue($log->is_enabled(), 'Enable all failed'); + +		$log->disable('admin'); +		$this->assertFalse($log->is_enabled('admin'), 'Disable admin failed'); +		$this->assertTrue($log->is_enabled('user'), 'User should be enabled, is disabled'); +		$this->assertTrue($log->is_enabled(), 'Disable admin disabled all'); + +		$log->enable('admin'); +		$this->assertTrue($log->is_enabled('admin'), 'Enable admin failed'); +	} + +	public function test_log_add() +	{ +		global $phpbb_root_path, $phpEx, $db, $phpbb_dispatcher; + +		$db = $this->new_dbal(); +		$cache = new phpbb_mock_cache; +		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); +		$user = $this->getMock('phpbb_user'); +		$auth = $this->getMock('phpbb_auth'); + +		$log = new phpbb_log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); + +		$mode = 'critical'; +		$user_id = ANONYMOUS; +		$log_ip = 'user_ip'; +		$log_time = time(); +		$log_operation = 'LOG_OPERATION'; +		$additional_data = array(); + +		// Add an entry successful +		$this->assertEquals(1, $log->add($mode, $user_id, $log_ip, $log_operation, $log_time)); + +		// Disable logging for all types +		$log->disable(); +		$this->assertFalse($log->add($mode, $user_id, $log_ip, $log_operation, $log_time), 'Disable for all types failed'); +		$log->enable(); + +		// Disable logging for same type +		$log->disable('critical'); +		$this->assertFalse($log->add($mode, $user_id, $log_ip, $log_operation, $log_time), 'Disable for same type failed'); +		$log->enable(); + +		// Disable logging for different type +		$log->disable('admin'); +		$this->assertEquals(2, $log->add($mode, $user_id, $log_ip, $log_operation, $log_time), 'Disable for different types failed'); +		$log->enable(); + +		// Invalid mode specified +		$this->assertFalse($log->add('mode_does_not_exist', $user_id, $log_ip, $log_operation, $log_time)); +	} +} diff --git a/tests/log/fixtures/empty_log.xml b/tests/log/fixtures/empty_log.xml new file mode 100644 index 0000000000..261b6a622a --- /dev/null +++ b/tests/log/fixtures/empty_log.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_log"> +		<column>log_id</column> +		<column>log_type</column> +		<column>user_id</column> +		<column>forum_id</column> +		<column>topic_id</column> +		<column>reportee_id</column> +		<column>log_ip</column> +		<column>log_time</column> +		<column>log_operation</column> +		<column>log_data</column> +	</table> +</dataset> diff --git a/tests/log/fixtures/full_log.xml b/tests/log/fixtures/full_log.xml new file mode 100644 index 0000000000..2ce2643d26 --- /dev/null +++ b/tests/log/fixtures/full_log.xml @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<dataset> +	<table name="phpbb_log"> +		<column>log_id</column> +		<column>log_type</column> +		<column>user_id</column> +		<column>forum_id</column> +		<column>topic_id</column> +		<column>reportee_id</column> +		<column>log_ip</column> +		<column>log_time</column> +		<column>log_operation</column> +		<column>log_data</column> +		<row> +			<value>1</value> +			<value>0</value> +			<value>1</value> +			<value>0</value> +			<value>0</value> +			<value>0</value> +			<value>127.0.0.1</value> +			<value>1</value> +			<value>LOG_INSTALL_INSTALLED</value> +			<value>a:1:{i:0;s:9:"3.1.0-dev";}</value> +		</row> +		<row> +			<value>2</value> +			<value>0</value> +			<value>1</value> +			<value>0</value> +			<value>0</value> +			<value>0</value> +			<value>127.0.0.1</value> +			<value>1</value> +			<value>LOG_KEY_NOT_EXISTS</value> +			<value>a:1:{i:0;s:15:"additional_data";}</value> +		</row> +		<row> +			<value>3</value> +			<value>2</value> +			<value>1</value> +			<value>0</value> +			<value>0</value> +			<value>0</value> +			<value>127.0.0.1</value> +			<value>1</value> +			<value>LOG_CRITICAL</value> +			<value>a:1:{i:0;s:13:"critical data";}</value> +		</row> +		<row> +			<value>4</value> +			<value>1</value> +			<value>1</value> +			<value>12</value> +			<value>34</value> +			<value>0</value> +			<value>127.0.0.1</value> +			<value>1</value> +			<value>LOG_MOD</value> +			<value></value> +		</row> +		<row> +			<value>5</value> +			<value>1</value> +			<value>1</value> +			<value>12</value> +			<value>45</value> +			<value>0</value> +			<value>127.0.0.1</value> +			<value>1</value> +			<value>LOG_MOD</value> +			<value></value> +		</row> +		<row> +			<value>6</value> +			<value>1</value> +			<value>1</value> +			<value>23</value> +			<value>56</value> +			<value>0</value> +			<value>127.0.0.1</value> +			<value>1</value> +			<value>LOG_MOD</value> +			<value></value> +		</row> +		<row> +			<value>7</value> +			<value>1</value> +			<value>1</value> +			<value>12</value> +			<value>45</value> +			<value>0</value> +			<value>127.0.0.1</value> +			<value>1</value> +			<value>LOG_MOD2</value> +			<value></value> +		</row> +		<row> +			<value>8</value> +			<value>3</value> +			<value>1</value> +			<value>0</value> +			<value>0</value> +			<value>2</value> +			<value>127.0.0.1</value> +			<value>1</value> +			<value>LOG_USER</value> +			<value>a:1:{i:0;s:5:"admin";}</value> +		</row> +		<row> +			<value>9</value> +			<value>3</value> +			<value>1</value> +			<value>0</value> +			<value>0</value> +			<value>1</value> +			<value>127.0.0.1</value> +			<value>1</value> +			<value>LOG_USER</value> +			<value>a:1:{i:0;s:5:"guest";}</value> +		</row> +	</table> +	<table name="phpbb_users"> +		<column>user_id</column> +		<column>username</column> +		<column>username_clean</column> +		<column>user_permissions</column> +		<column>user_sig</column> +		<column>user_occ</column> +		<column>user_interests</column> +		<row> +			<value>1</value> +			<value>Anonymous</value> +			<value>Anonymous</value> +			<value></value> +			<value></value> +			<value></value> +			<value></value> +		</row> +		<row> +			<value>2</value> +			<value>admin</value> +			<value>admin</value> +			<value></value> +			<value></value> +			<value></value> +			<value></value> +		</row> +	</table> +	<table name="phpbb_topics"> +		<column>topic_id</column> +		<column>forum_id</column> +		<row> +			<value>34</value> +			<value>12</value> +		</row> +		<row> +			<value>45</value> +			<value>12</value> +		</row> +		<row> +			<value>56</value> +			<value>23</value> +		</row> +	</table> +</dataset> diff --git a/tests/log/function_add_log_test.php b/tests/log/function_add_log_test.php new file mode 100644 index 0000000000..864b364862 --- /dev/null +++ b/tests/log/function_add_log_test.php @@ -0,0 +1,193 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + +class phpbb_log_function_add_log_test extends phpbb_database_test_case +{ +	public function getDataSet() +	{ +		return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/empty_log.xml'); +	} + +	public static function test_add_log_function_data() +	{ +		return array( +			/** +			* Case documentation +			array( +				// Row that is in the database afterwards +				array( +					'user_id'		=> ANONYMOUS, +					'log_type'		=> LOG_MOD, +					'log_operation'	=> 'LOG_MOD_ADDITIONAL', +					// log_data will be serialized +					'log_data'		=> array( +						'argument3', +					), +					'reportee_id'	=> 0, +					'forum_id'		=> 56, +					'topic_id'		=> 78, +				), +				// user_id		Can also be false, then ANONYMOUS is used +				false, +				// log_mode		Used to determine the log_type +				'mod', +				// Followed by some additional arguments +				// forum_id, topic_id and reportee_id are specified before log_operation +				// The rest is specified afterwards. +				56, +				78, +				'LOG_MOD_ADDITIONAL', // log_operation +				'argument3', +			), +			*/ +			array( +				array( +					'user_id'		=> 2, +					'log_type'		=> LOG_CRITICAL, +					'log_operation'	=> 'LOG_NO_ADDITIONAL', +					'log_data'		=> '', +					'reportee_id'	=> 0, +					'forum_id'		=> 0, +					'topic_id'		=> 0, +				), +				2, 'critical', 'LOG_NO_ADDITIONAL', +			), +			array( +				array( +					'user_id'		=> 2, +					'log_type'		=> LOG_CRITICAL, +					'log_operation'	=> 'LOG_ONE_ADDITIONAL', +					'log_data'		=> array( +						'argument1', +					), +					'reportee_id'	=> 0, +					'forum_id'		=> 0, +					'topic_id'		=> 0, +				), +				2, 'critical', 'LOG_ONE_ADDITIONAL', 'argument1', +			), +			array( +				array( +					'user_id'		=> ANONYMOUS, +					'log_type'		=> LOG_ADMIN, +					'log_operation'	=> 'LOG_TWO_ADDITIONAL', +					'log_data'		=> array( +						'argument1', +						'argument2', +					), +					'reportee_id'	=> 0, +					'forum_id'		=> 0, +					'topic_id'		=> 0, +				), +				false, 'admin', 'LOG_TWO_ADDITIONAL', 'argument1', 'argument2', +			), +			array( +				array( +					'user_id'		=> ANONYMOUS, +					'log_type'		=> LOG_USERS, +					'log_operation'	=> 'LOG_USERS_ADDITIONAL', +					'log_data'		=> array( +						'argument2', +					), +					'reportee_id'	=> 2, +					'forum_id'		=> 0, +					'topic_id'		=> 0, +				), +				false, 'user', 2, 'LOG_USERS_ADDITIONAL', 'argument2', +			), +			array( +				array( +					'user_id'		=> ANONYMOUS, +					'log_type'		=> LOG_MOD, +					'log_operation'	=> 'LOG_MOD_TOPIC_AND_FORUM', +					'log_data'		=> '', +					'reportee_id'	=> 0, +					'forum_id'		=> 12, +					'topic_id'		=> 34, +				), +				false, 'mod', 12, 34, 'LOG_MOD_TOPIC_AND_FORUM', +			), +			array( +				array( +					'user_id'		=> ANONYMOUS, +					'log_type'		=> LOG_MOD, +					'log_operation'	=> 'LOG_MOD_ADDITIONAL', +					'log_data'		=> array( +						'argument3', +					), +					'reportee_id'	=> 0, +					'forum_id'		=> 56, +					'topic_id'		=> 78, +				), +				false, 'mod', 56, 78, 'LOG_MOD_ADDITIONAL', 'argument3', +			), +			array( +				array( +				), +				false, 'mode_does_not_exist', 'LOG_MOD_ADDITIONAL', 'argument1', +			), +		); +	} + +	/** +	* @dataProvider test_add_log_function_data +	*/ +	public function test_add_log_function($expected, $user_id, $mode, $required1, $additional1 = null, $additional2 = null, $additional3 = null) +	{ +		global $db, $cache, $user, $phpbb_log, $phpbb_dispatcher, $phpbb_root_path, $phpEx; + +		if ($expected) +		{ +			// Serialize the log data if we have some +			if (is_array($expected['log_data'])) +			{ +				$expected['log_data'] = serialize($expected['log_data']); +			} +			$expected = array($expected); +		} + +		$db = $this->new_dbal(); +		$cache = new phpbb_mock_cache; +		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); +		$user = $this->getMock('phpbb_user'); +		$auth = $this->getMock('phpbb_auth'); + +		$phpbb_log = new phpbb_log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); + +		$user->ip = 'user_ip'; +		if ($user_id) +		{ +			$user->data['user_id'] = $user_id; +		} + +		if ($additional3 != null) +		{ +			add_log($mode, $required1, $additional1, $additional2, $additional3); +		} +		else if ($additional2 != null) +		{ +			add_log($mode, $required1, $additional1, $additional2); +		} +		else if ($additional1 != null) +		{ +			add_log($mode, $required1, $additional1); +		} +		else +		{ +			add_log($mode, $required1); +		} + +		$result = $db->sql_query('SELECT user_id, log_type, log_operation, log_data, reportee_id, forum_id, topic_id +			FROM ' . LOG_TABLE); + +		$this->assertEquals($expected, $db->sql_fetchrowset($result)); +	} +} diff --git a/tests/log/function_view_log_test.php b/tests/log/function_view_log_test.php new file mode 100644 index 0000000000..2ecf77aeb8 --- /dev/null +++ b/tests/log/function_view_log_test.php @@ -0,0 +1,344 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2012 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/session.php'; +require_once dirname(__FILE__) . '/../mock/user.php'; +require_once dirname(__FILE__) . '/../mock/cache.php'; + +class phpbb_log_function_view_log_test extends phpbb_database_test_case +{ +	public function getDataSet() +	{ +		return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/full_log.xml'); +	} + +	public static function test_view_log_function_data() +	{ +		global $phpEx, $phpbb_dispatcher; +		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); + +		$expected_data_sets = array( +			1 => array( +				'id'				=> 1, + +				'reportee_id'			=> 0, +				'reportee_username'		=> '', +				'reportee_username_full'=> '', + +				'user_id'			=> 1, +				'username'			=> 'Anonymous', +				'username_full'		=> 'Anonymous', + +				'ip'				=> '127.0.0.1', +				'time'				=> 1, +				'forum_id'			=> 0, +				'topic_id'			=> 0, + +				'viewforum'			=> '', +				'action'			=> 'installed: 3.1.0-dev', +			), +			2 => array( +				'id'				=> 2, + +				'reportee_id'			=> 0, +				'reportee_username'		=> '', +				'reportee_username_full'=> '', + +				'user_id'			=> 1, +				'username'			=> 'Anonymous', +				'username_full'		=> 'Anonymous', + +				'ip'				=> '127.0.0.1', +				'time'				=> 1, +				'forum_id'			=> 0, +				'topic_id'			=> 0, + +				'viewforum'			=> '', +				'action'			=> '{LOG KEY NOT EXISTS}<br />additional_data', +			), +			3 => array( +				'id'				=> 3, + +				'reportee_id'			=> 0, +				'reportee_username'		=> '', +				'reportee_username_full'=> '', + +				'user_id'			=> 1, +				'username'			=> 'Anonymous', +				'username_full'		=> 'Anonymous', + +				'ip'				=> '127.0.0.1', +				'time'				=> 1, +				'forum_id'			=> 0, +				'topic_id'			=> 0, + +				'viewforum'			=> '', +				'action'			=> '{LOG CRITICAL}<br />critical data', +			), +			4 => array( +				'id'				=> 4, + +				'reportee_id'			=> 0, +				'reportee_username'		=> '', +				'reportee_username_full'=> '', + +				'user_id'			=> 1, +				'username'			=> 'Anonymous', +				'username_full'		=> 'Anonymous', + +				'ip'				=> '127.0.0.1', +				'time'				=> 1, +				'forum_id'			=> 12, +				'topic_id'			=> 34, + +				'viewforum'			=> '', +				'action'			=> '{LOG MOD}', +				'viewtopic'			=> '', +				'viewlogs'			=> '', +			), +			5 => array( +				'id'				=> 5, + +				'reportee_id'			=> 0, +				'reportee_username'		=> '', +				'reportee_username_full'=> '', + +				'user_id'			=> 1, +				'username'			=> 'Anonymous', +				'username_full'		=> 'Anonymous', + +				'ip'				=> '127.0.0.1', +				'time'				=> 1, +				'forum_id'			=> 12, +				'topic_id'			=> 45, + +				'viewforum'			=> '', +				'action'			=> '{LOG MOD}', +				'viewtopic'			=> '', +				'viewlogs'			=> '', +			), +			6 => array( +				'id'				=> 6, + +				'reportee_id'			=> 0, +				'reportee_username'		=> '', +				'reportee_username_full'=> '', + +				'user_id'			=> 1, +				'username'			=> 'Anonymous', +				'username_full'		=> 'Anonymous', + +				'ip'				=> '127.0.0.1', +				'time'				=> 1, +				'forum_id'			=> 23, +				'topic_id'			=> 56, + +				'viewforum'			=> append_sid("phpBB/viewforum.$phpEx", 'f=23'), +				'action'			=> '{LOG MOD}', +				'viewtopic'			=> append_sid("phpBB/viewtopic.$phpEx", 'f=23&t=56'), +				'viewlogs'			=> append_sid("phpBB/mcp.$phpEx", 'i=logs&mode=topic_logs&t=56'), +			), +			7 => array( +				'id'				=> 7, + +				'reportee_id'			=> 0, +				'reportee_username'		=> '', +				'reportee_username_full'=> '', + +				'user_id'			=> 1, +				'username'			=> 'Anonymous', +				'username_full'		=> 'Anonymous', + +				'ip'				=> '127.0.0.1', +				'time'				=> 1, +				'forum_id'			=> 12, +				'topic_id'			=> 45, + +				'viewforum'			=> '', +				'action'			=> '{LOG MOD2}', +				'viewtopic'			=> '', +				'viewlogs'			=> '', +			), +			8 => array( +				'id'				=> 8, + +				'reportee_id'			=> 2, +				'reportee_username'		=> 'admin', +				'reportee_username_full'=> 'admin', + +				'user_id'			=> 1, +				'username'			=> 'Anonymous', +				'username_full'		=> 'Anonymous', + +				'ip'				=> '127.0.0.1', +				'time'				=> 1, +				'forum_id'			=> 0, +				'topic_id'			=> 0, + +				'viewforum'			=> '', +				'action'			=> '{LOG USER}<br />admin', +			), +			9 => array( +				'id'				=> 9, + +				'reportee_id'			=> 1, +				'reportee_username'		=> 'Anonymous', +				'reportee_username_full'=> 'Anonymous', + +				'user_id'			=> 1, +				'username'			=> 'Anonymous', +				'username_full'		=> 'Anonymous', + +				'ip'				=> '127.0.0.1', +				'time'				=> 1, +				'forum_id'			=> 0, +				'topic_id'			=> 0, + +				'viewforum'			=> '', +				'action'			=> '{LOG USER}<br />guest', +			), +		); + +		$test_cases = array( +			/** +			* Case documentation +			array( +				// Array of datasets that should be in $log after running the function +				'expected'			=> array(5, 7), +				// Offset that will be returned from the function +				'expected_returned'	=> 0, +				// view_log parameters (see includes/functions_admin.php for docblock) +				// $log is ommited! +				'mod', 5, 0, 12, 45, +			), +			*/ +			array( +				'expected'			=> array(1, 2), +				'expected_returned'	=> 0, +				'admin', false, +			), +			array( +				'expected'			=> array(1), +				'expected_returned'	=> 0, +				'admin', false, 1, +			), +			array( +				'expected'			=> array(2), +				'expected_returned'	=> 1, +				'admin', false, 1, 1, +			), +			array( +				'expected'			=> array(2), +				'expected_returned'	=> 1, +				'admin', 0, 1, 1, +			), +			array( +				'expected'			=> array(2), +				'expected_returned'	=> 1, +				'admin', 0, 1, 5, +			), +			array( +				'expected'			=> array(3), +				'expected_returned'	=> 0, +				'critical', false, +			), +			array( +				'expected'			=> array(), +				'expected_returned'	=> null, +				'mode_does_not_exist', false, +			), +			array( +				'expected'			=> array(4, 5, 7), +				'expected_returned'	=> 0, +				'mod', 0, 5, 0, 12, +			), +			array( +				'expected'			=> array(5, 7), +				'expected_returned'	=> 0, +				'mod', 0, 5, 0, 12, 45, +			), +			array( +				'expected'			=> array(6), +				'expected_returned'	=> 0, +				'mod', 0, 5, 0, 23, +			), +			array( +				'expected'			=> array(8), +				'expected_returned'	=> 0, +				'user', 0, 5, 0, 0, 0, 2, +			), +			array( +				'expected'			=> array(8, 9), +				'expected_returned'	=> 0, +				'users', 0, +			), +		); + +		foreach ($test_cases as $case => $case_data) +		{ +			foreach ($case_data['expected'] as $data_set => $expected) +			{ +				$test_cases[$case]['expected'][$data_set] = $expected_data_sets[$expected]; +			} +		} + +		return $test_cases; +	} + +	/** +	* @dataProvider test_view_log_function_data +	*/ +	public function test_view_log_function($expected, $expected_returned, $mode, $log_count, $limit = 5, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $limit_days = 0, $sort_by = 'l.log_id ASC', $keywords = '') +	{ +		global $cache, $db, $user, $auth, $phpbb_log, $phpbb_dispatcher, $phpbb_root_path, $phpEx; + +		$db = $this->new_dbal(); +		$cache = new phpbb_mock_cache; +		$phpbb_dispatcher = new phpbb_mock_event_dispatcher(); + +		// Create auth mock +		$auth = $this->getMock('phpbb_auth'); +		$acl_get_map = array( +			array('f_read', 23, true), +			array('m_', 23, true), +		); +		$acl_gets_map = array( +			array('a_', 'm_', 23, true), +		); + +		$auth->expects($this->any()) +			->method('acl_get') +			->with($this->stringContains('_'), +				$this->anything()) +			->will($this->returnValueMap($acl_get_map)); +		$auth->expects($this->any()) +			->method('acl_gets') +			->with($this->stringContains('_'), +				$this->anything()) +			->will($this->returnValueMap($acl_gets_map)); + +		$user = new phpbb_mock_user; +		$user->optionset('viewcensors', false); +		// Test sprintf() of the data into the action +		$user->lang = array( +			'LOG_INSTALL_INSTALLED'		=> 'installed: %s', +		); + +		$phpbb_log = new phpbb_log($db, $user, $auth, $phpbb_dispatcher, $phpbb_root_path, 'adm/', $phpEx, LOG_TABLE); + +		$log = array(); +		$this->assertEquals($expected_returned, view_log($mode, $log, $log_count, $limit, $offset, $forum_id, $topic_id, $user_id, $limit_days, $sort_by, $keywords)); + +		$this->assertEquals($expected, $log); +	} +} | 
