diff options
Diffstat (limited to 'phpBB/includes/acp')
67 files changed, 4896 insertions, 7228 deletions
diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index fc5f44e14f..2372c1f73c 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,19 +19,39 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_attachments  { -	var $u_action; -	var $new_config; +	/** @var \phpbb\db\driver\driver_interface */ +	protected $db; + +	/** @var \phpbb\config\config */ +	protected $config; + +	/** @var ContainerBuilder */ +	protected $phpbb_container; + +	/** @var \phpbb\template\template */ +	protected $template; + +	/** @var \phpbb\user */ +	protected $user; + +	public $id; +	public $u_action; +	protected $new_config;  	function main($id, $mode)  	{ -		global $db, $user, $auth, $template, $cache; +		global $db, $user, $auth, $template, $cache, $phpbb_container;  		global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx; +		$this->id = $id; +		$this->db = $db; +		$this->config = $config; +		$this->template = $template; +		$this->user = $user; +		$this->phpbb_container = $phpbb_container; +  		$user->add_lang(array('posting', 'viewtopic', 'acp/attachments'));  		$error = $notify = array(); @@ -61,6 +84,10 @@ class acp_attachments  				$l_title = 'ACP_ORPHAN_ATTACHMENTS';  			break; +			case 'manage': +				$l_title = 'ACP_MANAGE_ATTACHMENTS'; +			break; +  			default:  				trigger_error('NO_MODE', E_USER_ERROR);  			break; @@ -95,7 +122,7 @@ class acp_attachments  				}  				$db->sql_freeresult($result); -				$l_legend_cat_images = $user->lang['SETTINGS_CAT_IMAGES'] . ' [' . $user->lang['ASSIGNED_GROUP'] . ': ' . ((!empty($s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE])) ? implode(', ', $s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE]) : $user->lang['NO_EXT_GROUP']) . ']'; +				$l_legend_cat_images = $user->lang['SETTINGS_CAT_IMAGES'] . ' [' . $user->lang['ASSIGNED_GROUP'] . ': ' . ((!empty($s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE])) ? implode($user->lang['COMMA_SEPARATOR'], $s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE]) : $user->lang['NO_EXT_GROUP']) . ']';  				$display_vars = array(  					'title'	=> 'ACP_ATTACHMENT_SETTINGS', @@ -114,22 +141,21 @@ class acp_attachments  						'attachment_quota'		=> array('lang' => 'ATTACH_QUOTA',			'validate' => 'string',	'type' => 'custom', 'method' => 'max_filesize', 'explain' => true),  						'max_filesize'			=> array('lang' => 'ATTACH_MAX_FILESIZE',	'validate' => 'string',	'type' => 'custom', 'method' => 'max_filesize', 'explain' => true),  						'max_filesize_pm'		=> array('lang' => 'ATTACH_MAX_PM_FILESIZE','validate' => 'string',	'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), -						'max_attachments'		=> array('lang' => 'MAX_ATTACHMENTS',		'validate' => 'int',	'type' => 'text:3:3', 'explain' => false), -						'max_attachments_pm'	=> array('lang' => 'MAX_ATTACHMENTS_PM',	'validate' => 'int',	'type' => 'text:3:3', 'explain' => false), +						'max_attachments'		=> array('lang' => 'MAX_ATTACHMENTS',		'validate' => 'int:0:999',	'type' => 'number:0:999', 'explain' => false), +						'max_attachments_pm'	=> array('lang' => 'MAX_ATTACHMENTS_PM',	'validate' => 'int:0:999',	'type' => 'number:0:999', 'explain' => false),  						'secure_downloads'		=> array('lang' => 'SECURE_DOWNLOADS',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'secure_allow_deny'		=> array('lang' => 'SECURE_ALLOW_DENY',		'validate' => 'int',	'type' => 'custom', 'method' => 'select_allow_deny', 'explain' => true),  						'secure_allow_empty_referer'	=> array('lang' => 'SECURE_EMPTY_REFERRER', 'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'check_attachment_content' 		=> array('lang' => 'CHECK_CONTENT', 'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), -  						'legend2'					=> $l_legend_cat_images,  						'img_display_inlined'		=> array('lang' => 'DISPLAY_INLINED',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'img_create_thumbnail'		=> array('lang' => 'CREATE_THUMBNAIL',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), -						'img_max_thumb_width'		=> array('lang' => 'MAX_THUMB_WIDTH',		'validate' => 'int',	'type' => 'text:7:15', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), -						'img_min_thumb_filesize'	=> array('lang' => 'MIN_THUMB_FILESIZE',	'validate' => 'int',	'type' => 'text:7:15', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']), +						'img_max_thumb_width'		=> array('lang' => 'MAX_THUMB_WIDTH',		'validate' => 'int:0:999999999999999',	'type' => 'number:0:999999999999999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), +						'img_min_thumb_filesize'	=> array('lang' => 'MIN_THUMB_FILESIZE',	'validate' => 'int:0:999999999999999',	'type' => 'number:0:999999999999999', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']),  						'img_imagick'				=> array('lang' => 'IMAGICK_PATH',			'validate' => 'string',	'type' => 'text:20:200', 'explain' => true, 'append' => '  <span>[ <a href="' . $this->u_action . '&action=imgmagick">' . $user->lang['SEARCH_IMAGICK'] . '</a> ]</span>'), -						'img_max'					=> array('lang' => 'MAX_IMAGE_SIZE',		'validate' => 'int',	'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), -						'img_link'					=> array('lang' => 'IMAGE_LINK_SIZE',		'validate' => 'int',	'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), +						'img_max'					=> array('lang' => 'MAX_IMAGE_SIZE',		'validate' => 'int:0:9999',	'type' => 'dimension:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), +						'img_link'					=> array('lang' => 'IMAGE_LINK_SIZE',		'validate' => 'int:0:9999',	'type' => 'dimension:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),  					)  				); @@ -745,7 +771,6 @@ class acp_attachments  						}  						$template->assign_vars(array( -							'PHPBB_ROOT_PATH'		=> $phpbb_root_path,  							'IMG_PATH'				=> $img_path,  							'ACTION'				=> $action,  							'GROUP_ID'				=> $group_id, @@ -914,7 +939,7 @@ class acp_attachments  						$db->sql_query($sql);  						add_log('admin', 'LOG_ATTACH_ORPHAN_DEL', implode(', ', $delete_files)); -						$notify[] = sprintf($user->lang['LOG_ATTACH_ORPHAN_DEL'], implode(', ', $delete_files)); +						$notify[] = sprintf($user->lang['LOG_ATTACH_ORPHAN_DEL'], implode($user->lang['COMMA_SEPARATOR'], $delete_files));  					}  					$upload_list = array(); @@ -1043,6 +1068,181 @@ class acp_attachments  				$db->sql_freeresult($result);  			break; + +			case 'manage': + +				if ($submit) +				{ +					$delete_files = (isset($_POST['delete'])) ? array_keys(request_var('delete', array('' => 0))) : array(); + +					if (sizeof($delete_files)) +					{ +						// Select those attachments we want to delete... +						$sql = 'SELECT real_filename +							FROM ' . ATTACHMENTS_TABLE . ' +							WHERE ' . $db->sql_in_set('attach_id', $delete_files) . ' +								AND is_orphan = 0'; +						$result = $db->sql_query($sql); +						while ($row = $db->sql_fetchrow($result)) +						{ +							$deleted_filenames[] = $row['real_filename']; +						} +						$db->sql_freeresult($result); + +						if ($num_deleted = delete_attachments('attach', $delete_files)) +						{ +							if (sizeof($delete_files) != $num_deleted) +							{ +								$error[] = $user->lang['FILES_GONE']; +							} +							add_log('admin', 'LOG_ATTACHMENTS_DELETED', implode(', ', $deleted_filenames)); +							$notify[] = sprintf($user->lang['LOG_ATTACHMENTS_DELETED'], implode($user->lang['COMMA_SEPARATOR'], $deleted_filenames)); +						} +						else +						{ +							$error[] = $user->lang['NO_FILES_TO_DELETE']; +						} +					} +				} + +				if ($action == 'stats') +				{ +					$this->handle_stats_resync(); +				} + +				$stats_error = $this->check_stats_accuracy(); + +				if ($stats_error) +				{ +					$error[] = $stats_error; +				} + +				$template->assign_vars(array( +					'S_MANAGE'		=> true, +				)); + +				$start		= request_var('start', 0); + +				// Sort keys +				$sort_days	= request_var('st', 0); +				$sort_key	= request_var('sk', 't'); +				$sort_dir	= request_var('sd', 'd'); + +				// Sorting +				$limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); +				$sort_by_text = array('f' => $user->lang['FILENAME'], 't' => $user->lang['FILEDATE'], 's' => $user->lang['FILESIZE'], 'x' => $user->lang['EXTENSION'], 'd' => $user->lang['DOWNLOADS'],'p' => $user->lang['ATTACH_POST_TYPE'], 'u' => $user->lang['AUTHOR']); +				$sort_by_sql = array('f' => 'a.real_filename', 't' => 'a.filetime', 's' => 'a.filesize', 'x' => 'a.extension', 'd' => 'a.download_count', 'p' => 'a.in_message', 'u' => 'u.username'); + +				$s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; +				gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); + +				$min_filetime = ($sort_days) ? (time() - ($sort_days * 86400)) : ''; +				$limit_filetime = ($min_filetime) ? " AND a.filetime >= $min_filetime " : ''; +				$start = ($sort_days && isset($_POST['sort'])) ? 0 : $start; + +				$attachments_per_page = (int) $config['topics_per_page']; + +				$stats = $this->get_attachment_stats($limit_filetime); +				$num_files = $stats['num_files']; +				$total_size = $stats['upload_dir_size']; + +				// Make sure $start is set to the last page if it exceeds the amount +				$pagination = $phpbb_container->get('pagination'); +				$start = $pagination->validate_start($start, $attachments_per_page, $num_files); + +				// If the user is trying to reach the second half of the attachments list, fetch it starting from the end +				$store_reverse = false; +				$sql_limit = $attachments_per_page; + +				if ($start > $num_files / 2) +				{ +					$store_reverse = true; + +					// Select the sort order. Add time sort anchor for non-time sorting cases +					$sql_sort_anchor = ($sort_key != 't') ? ', a.filetime ' . (($sort_dir == 'd') ? 'ASC' : 'DESC') : ''; +					$sql_sort_order = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'ASC' : 'DESC') . $sql_sort_anchor; +					$sql_limit = $pagination->reverse_limit($start, $sql_limit, $num_files); +					$sql_start = $pagination->reverse_start($start, $sql_limit, $num_files); +				} +				else +				{ +					// Select the sort order. Add time sort anchor for non-time sorting cases +					$sql_sort_anchor = ($sort_key != 't') ? ', a.filetime ' . (($sort_dir == 'd') ? 'DESC' : 'ASC') : ''; +					$sql_sort_order = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC') . $sql_sort_anchor; +					$sql_start = $start; +				} + +				$attachments_list = array(); + +				// Just get the files +				$sql = 'SELECT a.*, u.username, u.user_colour, t.topic_title +					FROM ' . ATTACHMENTS_TABLE . ' a +					LEFT JOIN ' . USERS_TABLE . ' u ON (u.user_id = a.poster_id) +					LEFT JOIN ' . TOPICS_TABLE . " t ON (a.topic_id = t.topic_id) +					WHERE a.is_orphan = 0 +						$limit_filetime +					ORDER BY $sql_sort_order"; +				$result = $db->sql_query_limit($sql, $sql_limit, $sql_start); + +				$i = ($store_reverse) ? $sql_limit - 1 : 0; + +				// Store increment value in a variable to save some conditional calls +				$i_increment = ($store_reverse) ? -1 : 1; +				while ($attachment_row = $db->sql_fetchrow($result)) +				{ +					$attachments_list[$i] = $attachment_row; +					$i = $i + $i_increment; +				} +				$db->sql_freeresult($result); + +				$base_url = $this->u_action . "&$u_sort_param"; +				$pagination->generate_template_pagination($base_url, 'pagination', 'start', $num_files, $attachments_per_page, $start); + +				$template->assign_vars(array( +					'TOTAL_FILES'		=> $num_files, +					'TOTAL_SIZE'		=> get_formatted_filesize($total_size), + +					'S_LIMIT_DAYS'		=> $s_limit_days, +					'S_SORT_KEY'		=> $s_sort_key, +					'S_SORT_DIR'		=> $s_sort_dir) +				); + +				// Grab extensions +				$extensions = $cache->obtain_attach_extensions(true); + +				for ($i = 0, $end = sizeof($attachments_list); $i < $end; ++$i) +				{ +					$row = $attachments_list[$i]; + +					$row['extension'] = strtolower(trim((string) $row['extension'])); +					$comment = ($row['attach_comment'] && !$row['in_message']) ? str_replace(array("\n", "\r"), array('<br />', "\n"), $row['attach_comment']) : ''; +					$display_cat = $extensions[$row['extension']]['display_cat']; +					$l_downloaded_viewed = ($display_cat == ATTACHMENT_CATEGORY_NONE) ? 'DOWNLOAD_COUNTS' : 'VIEWED_COUNTS'; + +					$template->assign_block_vars('attachments', array( +						'ATTACHMENT_POSTER'	=> get_username_string('full', (int) $row['poster_id'], (string) $row['username'], (string) $row['user_colour'], (string) $row['username']), +						'FILESIZE'			=> get_formatted_filesize((int) $row['filesize']), +						'FILETIME'			=> $user->format_date((int) $row['filetime']), +						'REAL_FILENAME'		=> (!$row['in_message']) ? utf8_basename((string) $row['real_filename']) : '', +						'PHYSICAL_FILENAME'	=> utf8_basename((string) $row['physical_filename']), +						'EXT_GROUP_NAME'	=> (!empty($extensions[$row['extension']]['group_name'])) ? $user->lang['EXT_GROUP_' . $extensions[$row['extension']]['group_name']] : '', +						'COMMENT'			=> $comment, +						'TOPIC_TITLE'		=> (!$row['in_message']) ? (string) $row['topic_title'] : '', +						'ATTACH_ID'			=> (int) $row['attach_id'], +						'POST_ID'			=> (int) $row['post_msg_id'], +						'TOPIC_ID'			=> (int) $row['topic_id'], +						'POST_IDS'			=> (!empty($post_ids[$row['attach_id']])) ? (int) $post_ids[$row['attach_id']] : '', + +						'L_DOWNLOAD_COUNT'	=> $user->lang($l_downloaded_viewed, (int) $row['download_count']), + +						'S_IN_MESSAGE'		=> (bool) $row['in_message'], + +						'U_VIEW_TOPIC'		=> append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row['topic_id']}&p={$row['post_msg_id']}") . "#p{$row['post_msg_id']}", +						'U_FILE'			=> append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'mode=view&id=' . $row['attach_id'])) +					); +				} + +			break;  		}  		if (sizeof($error)) @@ -1063,6 +1263,96 @@ class acp_attachments  	}  	/** +	* Get attachment file count and size of upload directory +	* +	* @param $limit string	Additional limit for WHERE clause to filter stats by. +	* @return array Returns array with stats: num_files and upload_dir_size +	*/ +	public function get_attachment_stats($limit = '') +	{ +		$sql = 'SELECT COUNT(a.attach_id) AS num_files, SUM(a.filesize) AS upload_dir_size +			FROM ' . ATTACHMENTS_TABLE . " a +			WHERE a.is_orphan = 0 +				$limit"; +		$result = $this->db->sql_query($sql); +		$row = $this->db->sql_fetchrow($result); +		$this->db->sql_freeresult($result); + +		return array( +			'num_files'			=> (int) $row['num_files'], +			'upload_dir_size'	=> (float) $row['upload_dir_size'], +		); +	} + +	/** +	* Set config attachment stat values +	* +	* @param $stats array	Array of config key => value pairs to set. +	* @return null +	*/ +	public function set_attachment_stats($stats) +	{ +		foreach ($stats as $key => $value) +		{ +			$this->config->set($key, $value, true); +		} +	} + +	/** +	* Check accuracy of attachment statistics. +	* +	* @return bool|string	Returns false if stats are correct or error message +	*	otherwise. +	*/ +	public function check_stats_accuracy() +	{ +		// Get fresh stats. +		$stats = $this->get_attachment_stats(); + +		// Get current files stats +		$num_files = (int) $this->config['num_files']; +		$total_size = (float) $this->config['upload_dir_size']; + +		if (($num_files != $stats['num_files']) || ($total_size != $stats['upload_dir_size'])) +		{ +			$u_resync = $this->u_action . '&action=stats'; + +			return $this->user->lang( +				'FILES_STATS_WRONG', +				(int) $stats['num_files'], +				get_formatted_filesize($stats['upload_dir_size']), +				'<a href="' . $u_resync . '">', +				'</a>' +			); +		} +		return false; +	} + +	/** +	* Handle stats resync. +	* +	* @return null +	*/ +	public function handle_stats_resync() +	{ +		if (!confirm_box(true)) +		{ +			confirm_box(false, $this->user->lang['RESYNC_FILES_STATS_CONFIRM'], build_hidden_fields(array( +				'i'			=> $this->id, +				'mode'		=> 'manage', +				'action'	=> 'stats', +			))); +		} +		else +		{ +			$this->set_attachment_stats($this->get_attachment_stats()); +			$log = $this->phpbb_container->get('log'); +			$log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_RESYNC_FILES_STATS'); +		} + +	} + +	/**  	* Build Select for category items  	*/  	function category_select($select_name, $group_id = false, $key = '') @@ -1235,6 +1525,7 @@ class acp_attachments  	function perform_site_list()  	{  		global $db, $user; +		global $request;  		if (isset($_REQUEST['securesubmit']))  		{ @@ -1243,7 +1534,7 @@ class acp_attachments  			$ip_list = array_unique(explode("\n", $ips));  			$ip_list_log = implode(', ', $ip_list); -			$ip_exclude = (!empty($_POST['ipexclude'])) ? 1 : 0; +			$ip_exclude = (int) $request->variable('ipexclude', false, false, \phpbb\request\request_interface::POST);  			$iplist = array();  			$hostlist = array(); @@ -1441,7 +1732,8 @@ class acp_attachments  		$size_var = $filesize['si_identifier'];  		$value = $filesize['value']; -		return '<input type="text" id="' . $key . '" size="8" maxlength="15" name="config[' . $key . ']" value="' . $value . '" /> <select name="' . $key . '">' . size_select_options($size_var) . '</select>'; +		// size="8" and maxlength="15" attributes as a fallback for browsers that do not support type="number" yet. +		return '<input type="number" id="' . $key . '" size="8" maxlength="15" min="0" name="config[' . $key . ']" value="' . $value . '" /> <select name="' . $key . '">' . size_select_options($size_var) . '</select>';  	}  	/** @@ -1455,5 +1747,3 @@ class acp_attachments  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php index f8af1b86e1..b555f46a94 100644 --- a/phpBB/includes/acp/acp_ban.php +++ b/phpBB/includes/acp/acp_ban.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,23 +19,19 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_ban  {  	var $u_action;  	function main($id, $mode)  	{ -		global $config, $db, $user, $auth, $template, $cache; -		global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; +		global $user, $template, $request, $phpbb_dispatcher; +		global $phpbb_root_path, $phpEx;  		include($phpbb_root_path . 'includes/functions_user.' . $phpEx); -		$bansubmit	= (isset($_POST['bansubmit'])) ? true : false; -		$unbansubmit = (isset($_POST['unbansubmit'])) ? true : false; -		$current_time = time(); +		$bansubmit	= $request->is_set_post('bansubmit'); +		$unbansubmit = $request->is_set_post('unbansubmit');  		$user->add_lang(array('acp/ban', 'acp/users'));  		$this->tpl_name = 'acp_ban'; @@ -48,23 +47,79 @@ class acp_ban  		if ($bansubmit)  		{  			// Grab the list of entries -			$ban				= utf8_normalize_nfc(request_var('ban', '', true)); -			$ban_len			= request_var('banlength', 0); -			$ban_len_other		= request_var('banlengthother', ''); -			$ban_exclude		= request_var('banexclude', 0); -			$ban_reason			= utf8_normalize_nfc(request_var('banreason', '', true)); -			$ban_give_reason	= utf8_normalize_nfc(request_var('bangivereason', '', true)); +			$ban				= $request->variable('ban', '', true); +			$ban_length			= $request->variable('banlength', 0); +			$ban_length_other	= $request->variable('banlengthother', ''); +			$ban_exclude		= $request->variable('banexclude', 0); +			$ban_reason			= $request->variable('banreason', '', true); +			$ban_give_reason	= $request->variable('bangivereason', '', true);  			if ($ban)  			{ -				user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason); +				$abort_ban = false; +				/** +				* Use this event to modify the ban details before the ban is performed +				* +				* @event core.acp_ban_before +				* @var	string	mode				One of the following: user, ip, email +				* @var	string	ban					Either string or array with usernames, ips or email addresses +				* @var	int		ban_length			Ban length in minutes +				* @var	string	ban_length_other	Ban length as a date (YYYY-MM-DD) +				* @var	bool	ban_exclude			Are we banning or excluding from another ban +				* @var	string	ban_reason			Ban reason displayed to moderators +				* @var	string	ban_give_reason		Ban reason displayed to the banned user +				* @var	mixed	abort_ban			Either false, or an error message that is displayed to the user. +				*									If a string is given the bans are not issued. +				* @since 3.1.0-RC5 +				*/ +				$vars = array( +					'mode', +					'ban', +					'ban_length', +					'ban_length_other', +					'ban_exclude', +					'ban_reason', +					'ban_give_reason', +					'abort_ban', +				); +				extract($phpbb_dispatcher->trigger_event('core.acp_ban_before', compact($vars))); + +				if ($abort_ban) +				{ +					trigger_error($abort_ban . adm_back_link($this->u_action)); +				} +				user_ban($mode, $ban, $ban_length, $ban_length_other, $ban_exclude, $ban_reason, $ban_give_reason); + +				/** +				* Use this event to perform actions after the ban has been performed +				* +				* @event core.acp_ban_after +				* @var	string	mode				One of the following: user, ip, email +				* @var	string	ban					Either string or array with usernames, ips or email addresses +				* @var	int		ban_length			Ban length in minutes +				* @var	string	ban_length_other	Ban length as a date (YYYY-MM-DD) +				* @var	bool	ban_exclude			Are we banning or excluding from another ban +				* @var	string	ban_reason			Ban reason displayed to moderators +				* @var	string	ban_give_reason		Ban reason displayed to the banned user +				* @since 3.1.0-RC5 +				*/ +				$vars = array( +					'mode', +					'ban', +					'ban_length', +					'ban_length_other', +					'ban_exclude', +					'ban_reason', +					'ban_give_reason', +				); +				extract($phpbb_dispatcher->trigger_event('core.acp_ban_after', compact($vars)));  				trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . adm_back_link($this->u_action));  			}  		}  		else if ($unbansubmit)  		{ -			$ban = request_var('unban', array('')); +			$ban = $request->variable('unban', array(''));  			if ($ban)  			{ @@ -98,7 +153,7 @@ class acp_ban  			break;  		} -		$this->display_ban_options($mode); +		self::display_ban_options($mode);  		$template->assign_vars(array(  			'L_TITLE'				=> $this->page_title, @@ -110,7 +165,7 @@ class acp_ban  			'L_NO_BAN_CELL'			=> $l_no_ban_cell,  			'S_USERNAME_BAN'	=> ($mode == 'user') ? true : false, -			 +  			'U_ACTION'			=> $this->u_action,  			'U_FIND_USERNAME'	=> append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=acp_ban&field=ban'),  		)); @@ -119,7 +174,7 @@ class acp_ban  	/**  	* Display ban options  	*/ -	function display_ban_options($mode) +	static public function display_ban_options($mode)  	{  		global $user, $db, $template; @@ -176,8 +231,6 @@ class acp_ban  		$result = $db->sql_query($sql);  		$banned_options = $excluded_options = array(); -		$ban_length = $ban_reasons = $ban_give_reasons = array(); -  		while ($row = $db->sql_fetchrow($result))  		{  			$option = '<option value="' . $row['ban_id'] . '">' . $row[$field] . '</option>'; @@ -196,60 +249,31 @@ class acp_ban  			if ($time_length == 0)  			{  				// Banned permanently -				$ban_length[$row['ban_id']] = $user->lang['PERMANENT']; +				$ban_length = $user->lang['PERMANENT'];  			}  			else if (isset($ban_end_text[$time_length]))  			{  				// Banned for a given duration -				$ban_length[$row['ban_id']] = sprintf($user->lang['BANNED_UNTIL_DURATION'], $ban_end_text[$time_length], $user->format_date($row['ban_end'], false, true)); +				$ban_length = $user->lang('BANNED_UNTIL_DURATION', $ban_end_text[$time_length], $user->format_date($row['ban_end'], false, true));  			}  			else  			{  				// Banned until given date -				$ban_length[$row['ban_id']] = sprintf($user->lang['BANNED_UNTIL_DATE'], $user->format_date($row['ban_end'], false, true)); +				$ban_length = $user->lang('BANNED_UNTIL_DATE', $user->format_date($row['ban_end'], false, true));  			} -			$ban_reasons[$row['ban_id']] = $row['ban_reason']; -			$ban_give_reasons[$row['ban_id']] = $row['ban_give_reason']; +			$template->assign_block_vars('bans', array( +				'BAN_ID'		=> (int) $row['ban_id'], +				'LENGTH'		=> $ban_length, +				'A_LENGTH'		=> addslashes($ban_length), +				'REASON'		=> $row['ban_reason'], +				'A_REASON'		=> addslashes($row['ban_reason']), +				'GIVE_REASON'	=> $row['ban_give_reason'], +				'A_GIVE_REASON'	=> addslashes($row['ban_give_reason']), +			));  		}  		$db->sql_freeresult($result); -		if (sizeof($ban_length)) -		{ -			foreach ($ban_length as $ban_id => $length) -			{ -				$template->assign_block_vars('ban_length', array( -					'BAN_ID'	=> (int) $ban_id, -					'LENGTH'	=> $length, -					'A_LENGTH'	=> addslashes($length), -				)); -			} -		} - -		if (sizeof($ban_reasons)) -		{ -			foreach ($ban_reasons as $ban_id => $reason) -			{ -				$template->assign_block_vars('ban_reason', array( -					'BAN_ID'	=> $ban_id, -					'REASON'	=> $reason, -					'A_REASON'	=> addslashes($reason), -				)); -			} -		} - -		if (sizeof($ban_give_reasons)) -		{ -			foreach ($ban_give_reasons as $ban_id => $reason) -			{ -				$template->assign_block_vars('ban_give_reason', array( -					'BAN_ID'	=> $ban_id, -					'REASON'	=> $reason, -					'A_REASON'	=> addslashes($reason), -				)); -			} -		} -  		$options = '';  		if ($excluded_options)  		{ @@ -272,5 +296,3 @@ class acp_ban  		));  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index 31166a56dc..130a3ef542 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,16 +19,13 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_bbcodes  {  	var $u_action;  	function main($id, $mode)  	{ -		global $db, $user, $auth, $template, $cache; +		global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher;  		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;  		$user->add_lang('acp/posting'); @@ -97,7 +97,7 @@ class acp_bbcodes  			case 'edit':  			case 'add': -				$template->assign_vars(array( +				$tpl_ary = array(  					'S_EDIT_BBCODE'		=> true,  					'U_BACK'			=> $this->u_action,  					'U_ACTION'			=> $this->u_action . '&action=' . (($action == 'add') ? 'create' : 'modify') . (($bbcode_id) ? "&bbcode=$bbcode_id" : ''), @@ -106,14 +106,32 @@ class acp_bbcodes  					'BBCODE_MATCH'			=> $bbcode_match,  					'BBCODE_TPL'			=> $bbcode_tpl,  					'BBCODE_HELPLINE'		=> $bbcode_helpline, -					'DISPLAY_ON_POSTING'	=> $display_on_posting) +					'DISPLAY_ON_POSTING'	=> $display_on_posting,  				); -				foreach ($user->lang['tokens'] as $token => $token_explain) +				$bbcode_tokens = array('TEXT', 'SIMPLETEXT', 'INTTEXT', 'IDENTIFIER', 'NUMBER', 'EMAIL', 'URL', 'LOCAL_URL', 'RELATIVE_URL', 'COLOR'); + +				/** +				* Modify custom bbcode template data before we display the add/edit form +				* +				* @event core.acp_bbcodes_edit_add +				* @var	string	action			Type of the action: add|edit +				* @var	array	tpl_ary			Array with custom bbcode add/edit data +				* @var	int		bbcode_id		When editing: the bbcode id, +				*								when creating: 0 +				* @var	array	bbcode_tokens	Array of bbcode tokens +				* @since 3.1.0-a3 +				*/ +				$vars = array('action', 'tpl_ary', 'bbcode_id', 'bbcode_tokens'); +				extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_edit_add', compact($vars))); + +				$template->assign_vars($tpl_ary); + +				foreach ($bbcode_tokens as $token)  				{  					$template->assign_block_vars('token', array(  						'TOKEN'		=> '{' . $token . '}', -						'EXPLAIN'	=> ($token === 'LOCAL_URL') ? sprintf($token_explain, generate_board_url() . '/') : $token_explain, +						'EXPLAIN'	=> ($token === 'LOCAL_URL') ? $user->lang(array('tokens', $token), generate_board_url() . '/') : $user->lang(array('tokens', $token)),  					));  				} @@ -124,6 +142,36 @@ class acp_bbcodes  			case 'modify':  			case 'create': +				$sql_ary = $hidden_fields = array(); + +				/** +				* Modify custom bbcode data before the modify/create action +				* +				* @event core.acp_bbcodes_modify_create +				* @var	string	action				Type of the action: modify|create +				* @var	array	sql_ary				Array with new bbcode data +				* @var	int		bbcode_id			When editing: the bbcode id, +				*									when creating: 0 +				* @var	bool	display_on_posting	Display bbcode on posting form +				* @var	string	bbcode_match		The bbcode usage string to match +				* @var	string	bbcode_tpl			The bbcode HTML replacement string +				* @var	string	bbcode_helpline		The bbcode help line string +				* @var	array	hidden_fields		Array of hidden fields for use when +				*									submitting form when $warn_text is true +				* @since 3.1.0-a3 +				*/ +				$vars = array( +					'action', +					'sql_ary', +					'bbcode_id', +					'display_on_posting', +					'bbcode_match', +					'bbcode_tpl', +					'bbcode_helpline', +					'hidden_fields', +				); +				extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_modify_create', compact($vars))); +  				$warn_text = preg_match('%<[^>]*\{text[\d]*\}[^>]*>%i', $bbcode_tpl);  				if (!$warn_text || confirm_box(true))  				{ @@ -172,13 +220,12 @@ class acp_bbcodes  						trigger_error($user->lang['BBCODE_TAG_DEF_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING);  					} -  					if (strlen($bbcode_helpline) > 255)  					{  						trigger_error($user->lang['BBCODE_HELPLINE_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING);  					} -					$sql_ary = array( +					$sql_ary = array_merge($sql_ary, array(  						'bbcode_tag'				=> $data['bbcode_tag'],  						'bbcode_match'				=> $bbcode_match,  						'bbcode_tpl'				=> $bbcode_tpl, @@ -188,7 +235,7 @@ class acp_bbcodes  						'first_pass_replace'		=> $data['first_pass_replace'],  						'second_pass_match'			=> $data['second_pass_match'],  						'second_pass_replace'		=> $data['second_pass_replace'] -					); +					));  					if ($action == 'create')  					{ @@ -244,14 +291,14 @@ class acp_bbcodes  				}  				else  				{ -					confirm_box(false, $user->lang['BBCODE_DANGER'], build_hidden_fields(array( +					confirm_box(false, $user->lang['BBCODE_DANGER'], build_hidden_fields(array_merge($hidden_fields, array(  						'action'				=> $action,  						'bbcode'				=> $bbcode_id,  						'bbcode_match'			=> $bbcode_match,  						'bbcode_tpl'			=> htmlspecialchars($bbcode_tpl),  						'bbcode_helpline'		=> $bbcode_helpline,  						'display_on_posting'	=> $display_on_posting, -						)) +						)))  					, 'confirm_bbcode.html');  				} @@ -273,6 +320,18 @@ class acp_bbcodes  						$db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id");  						$cache->destroy('sql', BBCODES_TABLE);  						add_log('admin', 'LOG_BBCODE_DELETE', $row['bbcode_tag']); + +						if ($request->is_ajax()) +						{ +							$json_response = new \phpbb\json_response; +							$json_response->send(array( +								'MESSAGE_TITLE'	=> $user->lang['INFORMATION'], +								'MESSAGE_TEXT'	=> $user->lang['BBCODE_DELETED'], +								'REFRESH_DATA'	=> array( +									'time'	=> 3 +								) +							)); +						}  					}  					else  					{ @@ -288,22 +347,57 @@ class acp_bbcodes  			break;  		} -		$template->assign_vars(array( -			'U_ACTION'		=> $this->u_action . '&action=add') +		$u_action = $this->u_action; + +		$template_data = array( +			'U_ACTION'		=> $this->u_action . '&action=add',  		); -		$sql = 'SELECT * -			FROM ' . BBCODES_TABLE . ' -			ORDER BY bbcode_tag'; -		$result = $db->sql_query($sql); +		$sql_ary = array( +			'SELECT'	=> 'b.*', +			'FROM'		=> array(BBCODES_TABLE => 'b'), +			'ORDER_BY'	=> 'b.bbcode_tag', +		); + +		/** +		*  Modify custom bbcode template data before we display the form +		* +		* @event core.acp_bbcodes_display_form +		* @var	string	action			Type of the action: modify|create +		* @var	string	sql_ary			The SQL array to get custom bbcode data +		* @var	array	template_data	Array with form template data +		* @var	string	u_action		The u_action link +		* @since 3.1.0-a3 +		*/ +		$vars = array('action', 'sql_ary', 'template_data', 'u_action'); +		extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_display_form', compact($vars))); + +		$result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary)); + +		$template->assign_vars($template_data);  		while ($row = $db->sql_fetchrow($result))  		{ -			$template->assign_block_vars('bbcodes', array( +			$bbcodes_array = array(  				'BBCODE_TAG'		=> $row['bbcode_tag'], -				'U_EDIT'			=> $this->u_action . '&action=edit&bbcode=' . $row['bbcode_id'], -				'U_DELETE'			=> $this->u_action . '&action=delete&bbcode=' . $row['bbcode_id']) +				'U_EDIT'			=> $u_action . '&action=edit&bbcode=' . $row['bbcode_id'], +				'U_DELETE'			=> $u_action . '&action=delete&bbcode=' . $row['bbcode_id'],  			); + +			/** +			*  Modify display of custom bbcodes in the form +			* +			* @event core.acp_bbcodes_display_bbcodes +			* @var	array	row				Array with current bbcode data +			* @var	array	bbcodes_array	Array of bbcodes template data +			* @var	string	u_action		The u_action link +			* @since 3.1.0-a3 +			*/ +			$vars = array('bbcodes_array', 'row', 'u_action'); +			extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_display_bbcodes', compact($vars))); + +			$template->assign_block_vars('bbcodes', $bbcodes_array); +  		}  		$db->sql_freeresult($result);  	} @@ -317,16 +411,7 @@ class acp_bbcodes  		$bbcode_tpl = trim($bbcode_tpl);  		$utf8 = strpos($bbcode_match, 'INTTEXT') !== false; -		// make sure we have utf8 support -		$utf8_pcre_properties = false; -		if (version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) -		{ -			// While this is the proper range of PHP versions, PHP may not be linked with the bundled PCRE lib and instead with an older version -			if (@preg_match('/\p{L}/u', 'a') !== false) -			{ -				$utf8_pcre_properties = true; -			} -		} +		$utf8_pcre_properties = phpbb_pcre_utf8_support();  		$fp_match = preg_quote($bbcode_match, '!');  		$fp_replace = preg_replace('#^\[(.*?)\]#', '[$1:$uid]', $bbcode_match); @@ -480,5 +565,3 @@ class acp_bbcodes  		);  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 526d8e05da..63e2647f02 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -1,11 +1,17 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package.  * +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/**  * @todo add cron intervals to server settings? (database_gc, queue_interval, session_gc, search_gc, cache_gc, warnings_gc)  */ @@ -17,9 +23,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_board  {  	var $u_action; @@ -29,7 +32,7 @@ class acp_board  	{  		global $db, $user, $auth, $template;  		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; -		global $cache; +		global $cache, $phpbb_container, $phpbb_dispatcher;  		$user->add_lang('acp/board'); @@ -54,19 +57,24 @@ class acp_board  						'legend1'				=> 'ACP_BOARD_SETTINGS',  						'sitename'				=> array('lang' => 'SITE_NAME',				'validate' => 'string',	'type' => 'text:40:255', 'explain' => false),  						'site_desc'				=> array('lang' => 'SITE_DESC',				'validate' => 'string',	'type' => 'text:40:255', 'explain' => false), +						'site_home_url'			=> array('lang' => 'SITE_HOME_URL',			'validate' => 'string',	'type' => 'url:40:255', 'explain' => true), +						'site_home_text'		=> array('lang' => 'SITE_HOME_TEXT',		'validate' => 'string',	'type' => 'text:40:255', 'explain' => true), +						'board_index_text'		=> array('lang' => 'BOARD_INDEX_TEXT',		'validate' => 'string',	'type' => 'text:40:255', 'explain' => true),  						'board_disable'			=> array('lang' => 'DISABLE_BOARD',			'validate' => 'bool',	'type' => 'custom', 'method' => 'board_disable', 'explain' => true),  						'board_disable_msg'		=> false,  						'default_lang'			=> array('lang' => 'DEFAULT_LANGUAGE',		'validate' => 'lang',	'type' => 'select', 'function' => 'language_select', 'params' => array('{CONFIG_VALUE}'), 'explain' => false),  						'default_dateformat'	=> array('lang' => 'DEFAULT_DATE_FORMAT',	'validate' => 'string',	'type' => 'custom', 'method' => 'dateformat_select', 'explain' => true), -						'board_timezone'		=> array('lang' => 'SYSTEM_TIMEZONE',		'validate' => 'string',	'type' => 'select', 'function' => 'tz_select', 'params' => array('{CONFIG_VALUE}', 1), 'explain' => true), -						'board_dst'				=> array('lang' => 'SYSTEM_DST',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false), -						'default_style'			=> array('lang' => 'DEFAULT_STYLE',			'validate' => 'int',	'type' => 'select', 'function' => 'style_select', 'params' => array('{CONFIG_VALUE}', false), 'explain' => false), +						'board_timezone'		=> array('lang' => 'SYSTEM_TIMEZONE',		'validate' => 'timezone',	'type' => 'custom', 'method' => 'timezone_select', 'explain' => true), + +						'legend2'				=> 'BOARD_STYLE', +						'default_style'			=> array('lang' => 'DEFAULT_STYLE',			'validate' => 'int',	'type' => 'select', 'function' => 'style_select', 'params' => array('{CONFIG_VALUE}', false), 'explain' => true), +						'guest_style'			=> array('lang' => 'GUEST_STYLE',			'validate' => 'int',	'type' => 'select', 'function' => 'style_select', 'params' => array($this->guest_style_get(), false), 'explain' => true),  						'override_user_style'	=> array('lang' => 'OVERRIDE_STYLE',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), -						'legend2'				=> 'WARNINGS', -						'warnings_expire_days'	=> array('lang' => 'WARNINGS_EXPIRE',		'validate' => 'int',	'type' => 'text:3:4', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), +						'legend3'				=> 'WARNINGS', +						'warnings_expire_days'	=> array('lang' => 'WARNINGS_EXPIRE',		'validate' => 'int:0:9999',	'type' => 'number:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), -						'legend3'					=> 'ACP_SUBMIT_CHANGES', +						'legend4'					=> 'ACP_SUBMIT_CHANGES',  					)  				);  			break; @@ -89,6 +97,7 @@ class acp_board  						'allow_nocensors'		=> array('lang' => 'ALLOW_NO_CENSORS',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'allow_bookmarks'		=> array('lang' => 'ALLOW_BOOKMARKS',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'allow_birthdays'		=> array('lang' => 'ALLOW_BIRTHDAYS',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), +						'display_last_subject'	=> array('lang' => 'DISPLAY_LAST_SUBJECT',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'allow_quick_reply'		=> array('lang' => 'ALLOW_QUICK_REPLY',		'validate' => 'bool',	'type' => 'custom', 'method' => 'quick_reply', 'explain' => true),  						'legend2'				=> 'ACP_LOAD_SETTINGS', @@ -96,6 +105,7 @@ class acp_board  						'load_moderators'		=> array('lang' => 'YES_MODERATORS',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false),  						'load_jumpbox'			=> array('lang' => 'YES_JUMPBOX',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false),  						'load_cpf_memberlist'	=> array('lang' => 'LOAD_CPF_MEMBERLIST',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false), +						'load_cpf_pm'			=> array('lang' => 'LOAD_CPF_PM',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain'	=> false),  						'load_cpf_viewprofile'	=> array('lang' => 'LOAD_CPF_VIEWPROFILE',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false),  						'load_cpf_viewtopic'	=> array('lang' => 'LOAD_CPF_VIEWTOPIC',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false), @@ -105,28 +115,43 @@ class acp_board  			break;  			case 'avatar': +				$phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); +				$avatar_drivers = $phpbb_avatar_manager->get_all_drivers(); + +				$avatar_vars = array(); +				foreach ($avatar_drivers as $current_driver) +				{ +					$driver = $phpbb_avatar_manager->get_driver($current_driver, false); + +					/* +					* First grab the settings for enabling/disabling the avatar +					* driver and afterwards grab additional settings the driver +					* might have. +					*/ +					$avatar_vars += $phpbb_avatar_manager->get_avatar_settings($driver); +					$avatar_vars += $driver->prepare_form_acp($user); +				} +  				$display_vars = array(  					'title'	=> 'ACP_AVATAR_SETTINGS',  					'vars'	=> array(  						'legend1'				=> 'ACP_AVATAR_SETTINGS', -						'avatar_min_width'		=> array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,), -						'avatar_min_height'		=> array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,), -						'avatar_max_width'		=> array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,), -						'avatar_max_height'		=> array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,), +						'avatar_min_width'		=> array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false), +						'avatar_min_height'		=> array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false), +						'avatar_max_width'		=> array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false), +						'avatar_max_height'		=> array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false),  						'allow_avatar'			=> array('lang' => 'ALLOW_AVATARS',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), -						'allow_avatar_local'	=> array('lang' => 'ALLOW_LOCAL',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false), -						'allow_avatar_remote'	=> array('lang' => 'ALLOW_REMOTE',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), -						'allow_avatar_upload'	=> array('lang' => 'ALLOW_UPLOAD',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false), -						'allow_avatar_remote_upload'=> array('lang' => 'ALLOW_REMOTE_UPLOAD', 'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), -						'avatar_filesize'		=> array('lang' => 'MAX_FILESIZE',			'validate' => 'int:0',	'type' => 'text:4:10', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']), -						'avatar_min'			=> array('lang' => 'MIN_AVATAR_SIZE',		'validate' => 'int:0',	'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), -						'avatar_max'			=> array('lang' => 'MAX_AVATAR_SIZE',		'validate' => 'int:0',	'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), -						'avatar_path'			=> array('lang' => 'AVATAR_STORAGE_PATH',	'validate' => 'rpath',	'type' => 'text:20:255', 'explain' => true), -						'avatar_gallery_path'	=> array('lang' => 'AVATAR_GALLERY_PATH',	'validate' => 'rpath',	'type' => 'text:20:255', 'explain' => true) +						'avatar_min'			=> array('lang' => 'MIN_AVATAR_SIZE',		'validate' => 'int:0',	'type' => 'dimension:0', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), +						'avatar_max'			=> array('lang' => 'MAX_AVATAR_SIZE',		'validate' => 'int:0',	'type' => 'dimension:0', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),  					)  				); + +				if (!empty($avatar_vars)) +				{ +					$display_vars['vars'] += $avatar_vars; +				}  			break;  			case 'message': @@ -136,11 +161,11 @@ class acp_board  					'vars'	=> array(  						'legend1'				=> 'GENERAL_SETTINGS',  						'allow_privmsg'			=> array('lang' => 'BOARD_PM',				'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), -						'pm_max_boxes'			=> array('lang' => 'BOXES_MAX',				'validate' => 'int:0',	'type' => 'text:4:4', 'explain' => true), -						'pm_max_msgs'			=> array('lang' => 'BOXES_LIMIT',			'validate' => 'int:0',	'type' => 'text:4:4', 'explain' => true), +						'pm_max_boxes'			=> array('lang' => 'BOXES_MAX',				'validate' => 'int:0:9999',	'type' => 'number:0:9999', 'explain' => true), +						'pm_max_msgs'			=> array('lang' => 'BOXES_LIMIT',			'validate' => 'int:0:9999',	'type' => 'number:0:9999', 'explain' => true),  						'full_folder_action'	=> array('lang' => 'FULL_FOLDER_ACTION',	'validate' => 'int',	'type' => 'select', 'method' => 'full_folder_select', 'explain' => true), -						'pm_edit_time'			=> array('lang' => 'PM_EDIT_TIME',			'validate' => 'int:0',	'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), -						'pm_max_recipients'		=> array('lang' => 'PM_MAX_RECIPIENTS',		'validate' => 'int:0',	'type' => 'text:5:5', 'explain' => true), +						'pm_edit_time'			=> array('lang' => 'PM_EDIT_TIME',			'validate' => 'int:0:99999',	'type' => 'number:0:99999', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), +						'pm_max_recipients'		=> array('lang' => 'PM_MAX_RECIPIENTS',		'validate' => 'int:0:99999',	'type' => 'number:0:99999', 'explain' => true),  						'legend2'				=> 'GENERAL_OPTIONS',  						'allow_mass_pm'			=> array('lang' => 'ALLOW_MASS_PM',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false), @@ -177,24 +202,24 @@ class acp_board  						'legend2'				=> 'POSTING',  						'bump_type'				=> false, -						'edit_time'				=> array('lang' => 'EDIT_TIME',				'validate' => 'int:0',		'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), -						'delete_time'			=> array('lang' => 'DELETE_TIME',			'validate' => 'int:0',		'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), +						'edit_time'				=> array('lang' => 'EDIT_TIME',				'validate' => 'int:0:99999',		'type' => 'number:0:99999', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), +						'delete_time'			=> array('lang' => 'DELETE_TIME',			'validate' => 'int:0:99999',		'type' => 'number:0:99999', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']),  						'display_last_edited'	=> array('lang' => 'DISPLAY_LAST_EDITED',	'validate' => 'bool',		'type' => 'radio:yes_no', 'explain' => true), -						'flood_interval'		=> array('lang' => 'FLOOD_INTERVAL',		'validate' => 'int:0',		'type' => 'text:3:10', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), +						'flood_interval'		=> array('lang' => 'FLOOD_INTERVAL',		'validate' => 'int:0:9999999999',		'type' => 'number:0:9999999999', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),  						'bump_interval'			=> array('lang' => 'BUMP_INTERVAL',			'validate' => 'int:0',		'type' => 'custom', 'method' => 'bump_interval', 'explain' => true), -						'topics_per_page'		=> array('lang' => 'TOPICS_PER_PAGE',		'validate' => 'int:1',		'type' => 'text:3:4', 'explain' => false), -						'posts_per_page'		=> array('lang' => 'POSTS_PER_PAGE',		'validate' => 'int:1',		'type' => 'text:3:4', 'explain' => false), -						'smilies_per_page'		=> array('lang' => 'SMILIES_PER_PAGE',		'validate' => 'int:1',		'type' => 'text:3:4', 'explain' => false), -						'hot_threshold'			=> array('lang' => 'HOT_THRESHOLD',			'validate' => 'int:0',		'type' => 'text:3:4', 'explain' => true), -						'max_poll_options'		=> array('lang' => 'MAX_POLL_OPTIONS',		'validate' => 'int:2:127',	'type' => 'text:4:4', 'explain' => false), -						'max_post_chars'		=> array('lang' => 'CHAR_LIMIT',			'validate' => 'int:0',		'type' => 'text:4:6', 'explain' => true), -						'min_post_chars'		=> array('lang' => 'MIN_CHAR_LIMIT',		'validate' => 'int:1',		'type' => 'text:4:6', 'explain' => true), -						'max_post_smilies'		=> array('lang' => 'SMILIES_LIMIT',			'validate' => 'int:0',		'type' => 'text:4:4', 'explain' => true), -						'max_post_urls'			=> array('lang' => 'MAX_POST_URLS',			'validate' => 'int:0',		'type' => 'text:5:4', 'explain' => true), -						'max_post_font_size'	=> array('lang' => 'MAX_POST_FONT_SIZE',	'validate' => 'int:0',		'type' => 'text:5:4', 'explain' => true, 'append' => ' %'), -						'max_quote_depth'		=> array('lang' => 'QUOTE_DEPTH_LIMIT',		'validate' => 'int:0',		'type' => 'text:4:4', 'explain' => true), -						'max_post_img_width'	=> array('lang' => 'MAX_POST_IMG_WIDTH',	'validate' => 'int:0',		'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), -						'max_post_img_height'	=> array('lang' => 'MAX_POST_IMG_HEIGHT',	'validate' => 'int:0',		'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), +						'topics_per_page'		=> array('lang' => 'TOPICS_PER_PAGE',		'validate' => 'int:1:9999',		'type' => 'number:1:9999', 'explain' => false), +						'posts_per_page'		=> array('lang' => 'POSTS_PER_PAGE',		'validate' => 'int:1:9999',		'type' => 'number:1:9999', 'explain' => false), +						'smilies_per_page'		=> array('lang' => 'SMILIES_PER_PAGE',		'validate' => 'int:1:9999',		'type' => 'number:1:9999', 'explain' => false), +						'hot_threshold'			=> array('lang' => 'HOT_THRESHOLD',			'validate' => 'int:0:9999',		'type' => 'number:0:9999', 'explain' => true), +						'max_poll_options'		=> array('lang' => 'MAX_POLL_OPTIONS',		'validate' => 'int:2:127',	'type' => 'number:2:127', 'explain' => false), +						'max_post_chars'		=> array('lang' => 'CHAR_LIMIT',			'validate' => 'int:0:999999',		'type' => 'number:0:999999', 'explain' => true), +						'min_post_chars'		=> array('lang' => 'MIN_CHAR_LIMIT',		'validate' => 'int:1:999999',		'type' => 'number:1:999999', 'explain' => true), +						'max_post_smilies'		=> array('lang' => 'SMILIES_LIMIT',			'validate' => 'int:0:9999',		'type' => 'number:0:9999', 'explain' => true), +						'max_post_urls'			=> array('lang' => 'MAX_POST_URLS',			'validate' => 'int:0:9999',		'type' => 'number:0:9999', 'explain' => true), +						'max_post_font_size'	=> array('lang' => 'MAX_POST_FONT_SIZE',	'validate' => 'int:0:9999',		'type' => 'number:0:9999', 'explain' => true, 'append' => ' %'), +						'max_quote_depth'		=> array('lang' => 'QUOTE_DEPTH_LIMIT',		'validate' => 'int:0:9999',		'type' => 'number:0:9999', 'explain' => true), +						'max_post_img_width'	=> array('lang' => 'MAX_POST_IMG_WIDTH',	'validate' => 'int:0:9999',		'type' => 'number:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), +						'max_post_img_height'	=> array('lang' => 'MAX_POST_IMG_HEIGHT',	'validate' => 'int:0:9999',		'type' => 'number:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),  						'legend3'					=> 'ACP_SUBMIT_CHANGES',  					) @@ -214,12 +239,12 @@ class acp_board  						'allow_sig_links'		=> array('lang' => 'ALLOW_SIG_LINKS',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'legend2'				=> 'GENERAL_SETTINGS', -						'max_sig_chars'			=> array('lang' => 'MAX_SIG_LENGTH',		'validate' => 'int:0',	'type' => 'text:5:4', 'explain' => true), -						'max_sig_urls'			=> array('lang' => 'MAX_SIG_URLS',			'validate' => 'int:0',	'type' => 'text:5:4', 'explain' => true), -						'max_sig_font_size'		=> array('lang' => 'MAX_SIG_FONT_SIZE',		'validate' => 'int:0',	'type' => 'text:5:4', 'explain' => true, 'append' => ' %'), -						'max_sig_smilies'		=> array('lang' => 'MAX_SIG_SMILIES',		'validate' => 'int:0',	'type' => 'text:5:4', 'explain' => true), -						'max_sig_img_width'		=> array('lang' => 'MAX_SIG_IMG_WIDTH',		'validate' => 'int:0',	'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), -						'max_sig_img_height'	=> array('lang' => 'MAX_SIG_IMG_HEIGHT',	'validate' => 'int:0',	'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), +						'max_sig_chars'			=> array('lang' => 'MAX_SIG_LENGTH',		'validate' => 'int:0:9999',	'type' => 'number:0:9999', 'explain' => true), +						'max_sig_urls'			=> array('lang' => 'MAX_SIG_URLS',			'validate' => 'int:0:9999',	'type' => 'number:0:9999', 'explain' => true), +						'max_sig_font_size'		=> array('lang' => 'MAX_SIG_FONT_SIZE',		'validate' => 'int:0:9999',	'type' => 'number:0:9999', 'explain' => true, 'append' => ' %'), +						'max_sig_smilies'		=> array('lang' => 'MAX_SIG_SMILIES',		'validate' => 'int:0:9999',	'type' => 'number:0:9999', 'explain' => true), +						'max_sig_img_width'		=> array('lang' => 'MAX_SIG_IMG_WIDTH',		'validate' => 'int:0:9999',	'type' => 'number:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), +						'max_sig_img_height'	=> array('lang' => 'MAX_SIG_IMG_HEIGHT',	'validate' => 'int:0:9999',	'type' => 'number:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']),  						'legend3'					=> 'ACP_SUBMIT_CHANGES',  					) @@ -235,20 +260,20 @@ class acp_board  						'max_pass_chars'		=> array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:8:255', 'type' => false, 'method' => false, 'explain' => false,),  						'require_activation'	=> array('lang' => 'ACC_ACTIVATION',	'validate' => 'int',	'type' => 'select', 'method' => 'select_acc_activation', 'explain' => true), -						'new_member_post_limit'	=> array('lang' => 'NEW_MEMBER_POST_LIMIT', 'validate' => 'int:0:255', 'type' => 'text:4:4', 'explain' => true, 'append' => ' ' . $user->lang['POSTS']), +						'new_member_post_limit'	=> array('lang' => 'NEW_MEMBER_POST_LIMIT', 'validate' => 'int:0:255', 'type' => 'number:0:255', 'explain' => true, 'append' => ' ' . $user->lang['POSTS']),  						'new_member_group_default'=> array('lang' => 'NEW_MEMBER_GROUP_DEFAULT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),  						'min_name_chars'		=> array('lang' => 'USERNAME_LENGTH',	'validate' => 'int:1',	'type' => 'custom:5:180', 'method' => 'username_length', 'explain' => true),  						'min_pass_chars'		=> array('lang' => 'PASSWORD_LENGTH',	'validate' => 'int:1',	'type' => 'custom', 'method' => 'password_length', 'explain' => true),  						'allow_name_chars'		=> array('lang' => 'USERNAME_CHARS',	'validate' => 'string',	'type' => 'select', 'method' => 'select_username_chars', 'explain' => true),  						'pass_complex'			=> array('lang' => 'PASSWORD_TYPE',		'validate' => 'string',	'type' => 'select', 'method' => 'select_password_chars', 'explain' => true), -						'chg_passforce'			=> array('lang' => 'FORCE_PASS_CHANGE',	'validate' => 'int:0',	'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), +						'chg_passforce'			=> array('lang' => 'FORCE_PASS_CHANGE',	'validate' => 'int:0:999',	'type' => 'number:0:999', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),  						'legend2'				=> 'GENERAL_OPTIONS',  						'allow_namechange'		=> array('lang' => 'ALLOW_NAME_CHANGE',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false),  						'allow_emailreuse'		=> array('lang' => 'ALLOW_EMAIL_REUSE',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'enable_confirm'		=> array('lang' => 'VISUAL_CONFIRM_REG',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), -						'max_login_attempts'	=> array('lang' => 'MAX_LOGIN_ATTEMPTS',	'validate' => 'int:0',	'type' => 'text:3:3', 'explain' => true), -						'max_reg_attempts'		=> array('lang' => 'REG_LIMIT',				'validate' => 'int:0',	'type' => 'text:4:4', 'explain' => true), +						'max_login_attempts'	=> array('lang' => 'MAX_LOGIN_ATTEMPTS',	'validate' => 'int:0:999',	'type' => 'number:0:999', 'explain' => true), +						'max_reg_attempts'		=> array('lang' => 'REG_LIMIT',				'validate' => 'int:0:9999',	'type' => 'number:0:9999', 'explain' => true),  						'legend3'			=> 'COPPA',  						'coppa_enable'		=> array('lang' => 'ENABLE_COPPA',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), @@ -270,13 +295,13 @@ class acp_board  						'feed_http_auth'			=> array('lang' => 'ACP_FEED_HTTP_AUTH',			'validate' => 'bool',	'type' => 'radio:enabled_disabled',	'explain' => true),  						'legend2'					=> 'ACP_FEED_POST_BASED', -						'feed_limit_post'			=> array('lang' => 'ACP_FEED_LIMIT',				'validate' => 'int:5',	'type' => 'text:3:4',				'explain' => true), +						'feed_limit_post'			=> array('lang' => 'ACP_FEED_LIMIT',				'validate' => 'int:5:9999',	'type' => 'number:5:9999',				'explain' => true),  						'feed_overall'				=> array('lang' => 'ACP_FEED_OVERALL',				'validate' => 'bool',	'type' => 'radio:enabled_disabled',	'explain' => true ),  						'feed_forum'				=> array('lang' => 'ACP_FEED_FORUM',				'validate' => 'bool',	'type' => 'radio:enabled_disabled',	'explain' => true ),  						'feed_topic'				=> array('lang' => 'ACP_FEED_TOPIC',				'validate' => 'bool',	'type' => 'radio:enabled_disabled',	'explain' => true ),  						'legend3'					=> 'ACP_FEED_TOPIC_BASED', -						'feed_limit_topic'			=> array('lang' => 'ACP_FEED_LIMIT',				'validate' => 'int:5',	'type' => 'text:3:4',				'explain' => true), +						'feed_limit_topic'			=> array('lang' => 'ACP_FEED_LIMIT',				'validate' => 'int:5:9999',	'type' => 'number:5:9999',				'explain' => true),  						'feed_topics_new'			=> array('lang' => 'ACP_FEED_TOPICS_NEW',			'validate' => 'bool',	'type' => 'radio:enabled_disabled',	'explain' => true ),  						'feed_topics_active'		=> array('lang' => 'ACP_FEED_TOPICS_ACTIVE',		'validate' => 'bool',	'type' => 'radio:enabled_disabled',	'explain' => true ),  						'feed_news_id'				=> array('lang' => 'ACP_FEED_NEWS',					'validate' => 'string',	'type' => 'custom', 'method' => 'select_news_forums', 'explain' => true), @@ -296,7 +321,7 @@ class acp_board  						'cookie_domain'	=> array('lang' => 'COOKIE_DOMAIN',	'validate' => 'string',	'type' => 'text::255', 'explain' => false),  						'cookie_name'	=> array('lang' => 'COOKIE_NAME',	'validate' => 'string',	'type' => 'text::16', 'explain' => false),  						'cookie_path'	=> array('lang'	=> 'COOKIE_PATH',	'validate' => 'string',	'type' => 'text::255', 'explain' => false), -						'cookie_secure'	=> array('lang' => 'COOKIE_SECURE',	'validate' => 'bool',	'type' => 'radio:disabled_enabled', 'explain' => true) +						'cookie_secure'	=> array('lang' => 'COOKIE_SECURE',	'validate' => 'bool',	'type' => 'radio:disabled_enabled', 'explain' => true),  					)  				);  			break; @@ -306,12 +331,14 @@ class acp_board  					'title'	=> 'ACP_LOAD_SETTINGS',  					'vars'	=> array(  						'legend1'			=> 'GENERAL_SETTINGS', -						'limit_load'		=> array('lang' => 'LIMIT_LOAD',		'validate' => 'string',	'type' => 'text:4:4', 'explain' => true), -						'session_length'	=> array('lang' => 'SESSION_LENGTH',	'validate' => 'int:60',	'type' => 'text:5:10', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), -						'active_sessions'	=> array('lang' => 'LIMIT_SESSIONS',	'validate' => 'int:0',	'type' => 'text:4:4', 'explain' => true), -						'load_online_time'	=> array('lang' => 'ONLINE_LENGTH',		'validate' => 'int:0',	'type' => 'text:4:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), +						'limit_load'		=> array('lang' => 'LIMIT_LOAD',		'validate' => 'int:0:9999',	'type' => 'number:0:9999', 'explain' => true), +						'session_length'	=> array('lang' => 'SESSION_LENGTH',	'validate' => 'int:60:9999999999',	'type' => 'number:60:9999999999', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), +						'active_sessions'	=> array('lang' => 'LIMIT_SESSIONS',	'validate' => 'int:0:9999',	'type' => 'number:0:9999', 'explain' => true), +						'load_online_time'	=> array('lang' => 'ONLINE_LENGTH',		'validate' => 'int:0:999',	'type' => 'number:0:999', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), +						'read_notification_expire_days'	=> array('lang' => 'READ_NOTIFICATION_EXPIRE_DAYS',	'validate' => 'int:0',	'type' => 'number:0', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']),  						'legend2'				=> 'GENERAL_OPTIONS', +						'load_notifications'	=> array('lang' => 'LOAD_NOTIFICATIONS',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'load_db_track'			=> array('lang' => 'YES_POST_MARKING',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'load_db_lastread'		=> array('lang' => 'YES_READ_MARKING',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'load_anon_lastread'	=> array('lang' => 'YES_ANON_READ_MARKING',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), @@ -323,10 +350,13 @@ class acp_board  						'load_moderators'		=> array('lang' => 'YES_MODERATORS',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false),  						'load_jumpbox'			=> array('lang' => 'YES_JUMPBOX',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false),  						'load_user_activity'	=> array('lang' => 'LOAD_USER_ACTIVITY',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), -						'load_tplcompile'		=> array('lang' => 'RECOMPILE_STYLES',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), +						'load_tplcompile'		=> array('lang' => 'RECOMPILE_STYLES',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), +						'allow_cdn'				=> array('lang' => 'ALLOW_CDN',				'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), +						'allow_live_searches'	=> array('lang' => 'ALLOW_LIVE_SEARCHES',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'legend3'				=> 'CUSTOM_PROFILE_FIELDS',  						'load_cpf_memberlist'	=> array('lang' => 'LOAD_CPF_MEMBERLIST',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false), +						'load_cpf_pm'			=> array('lang' => 'LOAD_CPF_PM',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain'	=> false),  						'load_cpf_viewprofile'	=> array('lang' => 'LOAD_CPF_VIEWPROFILE',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false),  						'load_cpf_viewtopic'	=> array('lang' => 'LOAD_CPF_VIEWTOPIC',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => false), @@ -340,7 +370,7 @@ class acp_board  					'title'	=> 'ACP_AUTH_SETTINGS',  					'vars'	=> array(  						'legend1'		=> 'ACP_AUTH_SETTINGS', -						'auth_method'	=> array('lang' => 'AUTH_METHOD',	'validate' => 'string',	'type' => 'select', 'method' => 'select_auth_method', 'explain' => false) +						'auth_method'	=> array('lang' => 'AUTH_METHOD',	'validate' => 'string',	'type' => 'select:1:toggable', 'method' => 'select_auth_method', 'explain' => false),  					)  				);  			break; @@ -351,8 +381,10 @@ class acp_board  					'vars'	=> array(  						'legend1'				=> 'ACP_SERVER_SETTINGS',  						'gzip_compress'			=> array('lang' => 'ENABLE_GZIP',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), +						'use_system_cron'		=> array('lang' => 'USE_SYSTEM_CRON',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'legend2'				=> 'PATH_SETTINGS', +						'enable_mod_rewrite'	=> array('lang' => 'MOD_REWRITE_ENABLE',	'validate' => 'bool',	'type' => 'custom', 'method' => 'enable_mod_rewrite', 'explain' => true),  						'smilies_path'			=> array('lang' => 'SMILIES_PATH',		'validate' => 'rpath',	'type' => 'text:20:255', 'explain' => true),  						'icons_path'			=> array('lang' => 'ICONS_PATH',		'validate' => 'rpath',	'type' => 'text:20:255', 'explain' => true),  						'upload_icons_path'		=> array('lang' => 'UPLOAD_ICONS_PATH',	'validate' => 'rpath',	'type' => 'text:20:255', 'explain' => true), @@ -362,7 +394,7 @@ class acp_board  						'force_server_vars'		=> array('lang' => 'FORCE_SERVER_VARS',	'validate' => 'bool',			'type' => 'radio:yes_no', 'explain' => true),  						'server_protocol'		=> array('lang' => 'SERVER_PROTOCOL',	'validate' => 'string',			'type' => 'text:10:10', 'explain' => true),  						'server_name'			=> array('lang' => 'SERVER_NAME',		'validate' => 'string',			'type' => 'text:40:255', 'explain' => true), -						'server_port'			=> array('lang' => 'SERVER_PORT',		'validate' => 'int:0',			'type' => 'text:5:5', 'explain' => true), +						'server_port'			=> array('lang' => 'SERVER_PORT',		'validate' => 'int:0:99999',			'type' => 'number:0:99999', 'explain' => true),  						'script_path'			=> array('lang' => 'SCRIPT_PATH',		'validate' => 'script_path',	'type' => 'text::255', 'explain' => true),  						'legend4'					=> 'ACP_SUBMIT_CHANGES', @@ -376,23 +408,24 @@ class acp_board  					'vars'	=> array(  						'legend1'				=> 'ACP_SECURITY_SETTINGS',  						'allow_autologin'		=> array('lang' => 'ALLOW_AUTOLOGIN',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), -						'max_autologin_time'	=> array('lang' => 'AUTOLOGIN_LENGTH',		'validate' => 'int:0',	'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), +						'allow_password_reset'	=> array('lang' => 'ALLOW_PASSWORD_RESET',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), +						'max_autologin_time'	=> array('lang' => 'AUTOLOGIN_LENGTH',		'validate' => 'int:0:99999',	'type' => 'number:0:99999',	'explain' => true,	'append' => ' ' . $user->lang['DAYS']),  						'ip_check'				=> array('lang' => 'IP_VALID',				'validate' => 'int',	'type' => 'custom', 'method' => 'select_ip_check', 'explain' => true),  						'browser_check'			=> array('lang' => 'BROWSER_VALID',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'forwarded_for_check'	=> array('lang' => 'FORWARDED_FOR_VALID',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), -						'referer_validation'	=> array('lang' => 'REFERER_VALID',		'validate' => 'int:0:3','type' => 'custom', 'method' => 'select_ref_check', 'explain' => true), +						'referer_validation'	=> array('lang' => 'REFERRER_VALID',		'validate' => 'int:0:3','type' => 'custom', 'method' => 'select_ref_check', 'explain' => true),  						'check_dnsbl'			=> array('lang' => 'CHECK_DNSBL',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'email_check_mx'		=> array('lang' => 'EMAIL_CHECK_MX',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'max_pass_chars'		=> array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:8:255', 'type' => false, 'method' => false, 'explain' => false,),  						'min_pass_chars'		=> array('lang' => 'PASSWORD_LENGTH',	'validate' => 'int:1',	'type' => 'custom', 'method' => 'password_length', 'explain' => true),  						'pass_complex'			=> array('lang' => 'PASSWORD_TYPE',			'validate' => 'string',	'type' => 'select', 'method' => 'select_password_chars', 'explain' => true), -						'chg_passforce'			=> array('lang' => 'FORCE_PASS_CHANGE',		'validate' => 'int:0',	'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), -						'max_login_attempts'	=> array('lang' => 'MAX_LOGIN_ATTEMPTS',	'validate' => 'int:0',	'type' => 'text:3:3', 'explain' => true), -						'ip_login_limit_max'	=> array('lang' => 'IP_LOGIN_LIMIT_MAX',	'validate' => 'int:0',	'type' => 'text:3:3', 'explain' => true), -						'ip_login_limit_time'	=> array('lang' => 'IP_LOGIN_LIMIT_TIME',	'validate' => 'int:0',	'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), +						'chg_passforce'			=> array('lang' => 'FORCE_PASS_CHANGE',		'validate' => 'int:0:999',	'type' => 'number:0:999', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), +						'max_login_attempts'	=> array('lang' => 'MAX_LOGIN_ATTEMPTS',	'validate' => 'int:0:999',	'type' => 'number:0:999', 'explain' => true), +						'ip_login_limit_max'	=> array('lang' => 'IP_LOGIN_LIMIT_MAX',	'validate' => 'int:0:999',	'type' => 'number:0:999', 'explain' => true), +						'ip_login_limit_time'	=> array('lang' => 'IP_LOGIN_LIMIT_TIME',	'validate' => 'int:0:99999',	'type' => 'number:0:99999', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),  						'ip_login_limit_use_forwarded'	=> array('lang' => 'IP_LOGIN_LIMIT_USE_FORWARDED',	'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'tpl_allow_php'			=> array('lang' => 'TPL_ALLOW_PHP',			'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true), -						'form_token_lifetime'	=> array('lang' => 'FORM_TIME_MAX',			'validate' => 'int:-1',	'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), +						'form_token_lifetime'	=> array('lang' => 'FORM_TIME_MAX',			'validate' => 'int:-1:99999',	'type' => 'number:-1:99999', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']),  						'form_token_sid_guests'	=> array('lang' => 'FORM_SID_GUESTS',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  					) @@ -407,16 +440,17 @@ class acp_board  						'email_enable'			=> array('lang' => 'ENABLE_EMAIL',			'validate' => 'bool',	'type' => 'radio:enabled_disabled', 'explain' => true),  						'board_email_form'		=> array('lang' => 'BOARD_EMAIL_FORM',		'validate' => 'bool',	'type' => 'radio:enabled_disabled', 'explain' => true),  						'email_function_name'	=> array('lang' => 'EMAIL_FUNCTION_NAME',	'validate' => 'string',	'type' => 'text:20:50', 'explain' => true), -						'email_package_size'	=> array('lang' => 'EMAIL_PACKAGE_SIZE',	'validate' => 'int:0',	'type' => 'text:5:5', 'explain' => true), -						'board_contact'			=> array('lang' => 'CONTACT_EMAIL',			'validate' => 'email',	'type' => 'text:25:100', 'explain' => true), -						'board_email'			=> array('lang' => 'ADMIN_EMAIL',			'validate' => 'email',	'type' => 'text:25:100', 'explain' => true), +						'email_package_size'	=> array('lang' => 'EMAIL_PACKAGE_SIZE',	'validate' => 'int:0',	'type' => 'number:0:99999', 'explain' => true), +						'board_contact'			=> array('lang' => 'CONTACT_EMAIL',			'validate' => 'email',	'type' => 'email:25:100', 'explain' => true), +						'board_contact_name'	=> array('lang' => 'CONTACT_EMAIL_NAME',	'validate' => 'string',	'type' => 'text:25:50', 'explain' => true), +						'board_email'			=> array('lang' => 'ADMIN_EMAIL',			'validate' => 'email',	'type' => 'email:25:100', 'explain' => true),  						'board_email_sig'		=> array('lang' => 'EMAIL_SIG',				'validate' => 'string',	'type' => 'textarea:5:30', 'explain' => true),  						'board_hide_emails'		=> array('lang' => 'BOARD_HIDE_EMAILS',		'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'legend2'				=> 'SMTP_SETTINGS',  						'smtp_delivery'			=> array('lang' => 'USE_SMTP',				'validate' => 'bool',	'type' => 'radio:yes_no', 'explain' => true),  						'smtp_host'				=> array('lang' => 'SMTP_SERVER',			'validate' => 'string',	'type' => 'text:25:50', 'explain' => false), -						'smtp_port'				=> array('lang' => 'SMTP_PORT',				'validate' => 'int:0',	'type' => 'text:4:5', 'explain' => true), +						'smtp_port'				=> array('lang' => 'SMTP_PORT',				'validate' => 'int:0:99999',	'type' => 'number:0:99999', 'explain' => true),  						'smtp_auth_method'		=> array('lang' => 'SMTP_AUTH_METHOD',		'validate' => 'string',	'type' => 'select', 'method' => 'mail_auth_select', 'explain' => true),  						'smtp_username'			=> array('lang' => 'SMTP_USERNAME',			'validate' => 'string',	'type' => 'text:25:255', 'explain' => true),  						'smtp_password'			=> array('lang' => 'SMTP_PASSWORD',			'validate' => 'string',	'type' => 'password:25:255', 'explain' => true), @@ -431,6 +465,18 @@ class acp_board  			break;  		} +		/** +		* Event to add and/or modify acp_board configurations +		* +		* @event core.acp_board_config_edit_add +		* @var	array	display_vars	Array of config values to display and process +		* @var	string	mode			Mode of the config page we are displaying +		* @var	boolean	submit			Do we display the form or process the submission +		* @since 3.1.0-a4 +		*/ +		$vars = array('display_vars', 'mode', 'submit'); +		extract($phpbb_dispatcher->trigger_event('core.acp_board_config_edit_add', compact($vars))); +  		if (isset($display_vars['lang']))  		{  			$user->add_lang($display_vars['lang']); @@ -440,7 +486,7 @@ class acp_board  		$cfg_array = (isset($_REQUEST['config'])) ? utf8_normalize_nfc(request_var('config', array('' => ''), true)) : $this->new_config;  		$error = array(); -		// We validate the complete config if whished +		// We validate the complete config if wished  		validate_config_vars($display_vars['vars'], $cfg_array, $error);  		if ($submit && !check_form_key($form_key)) @@ -466,6 +512,14 @@ class acp_board  				continue;  			} +			if ($config_name == 'guest_style') +			{ +				if (isset($cfg_array[$config_name])) { +					$this->guest_style_set($cfg_array[$config_name]); +				} +				continue; +			} +  			$this->new_config[$config_name] = $config_value = $cfg_array[$config_name];  			if ($config_name == 'email_function_name') @@ -499,84 +553,54 @@ class acp_board  		if ($mode == 'auth')  		{  			// Retrieve a list of auth plugins and check their config values -			$auth_plugins = array(); - -			$dp = @opendir($phpbb_root_path . 'includes/auth'); +			$auth_providers = $phpbb_container->get('auth.provider_collection'); -			if ($dp) +			$updated_auth_settings = false; +			$old_auth_config = array(); +			foreach ($auth_providers as $provider)  			{ -				while (($file = readdir($dp)) !== false) +				if ($fields = $provider->acp())  				{ -					if (preg_match('#^auth_(.*?)\.' . $phpEx . '$#', $file)) +					// Check if we need to create config fields for this plugin and save config when submit was pressed +					foreach ($fields as $field)  					{ -						$auth_plugins[] = basename(preg_replace('#^auth_(.*?)\.' . $phpEx . '$#', '\1', $file)); -					} -				} -				closedir($dp); +						if (!isset($config[$field])) +						{ +							set_config($field, ''); +						} -				sort($auth_plugins); -			} +						if (!isset($cfg_array[$field]) || strpos($field, 'legend') !== false) +						{ +							continue; +						} -			$updated_auth_settings = false; -			$old_auth_config = array(); -			foreach ($auth_plugins as $method) -			{ -				if ($method && file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx)) -				{ -					include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); +						$old_auth_config[$field] = $this->new_config[$field]; +						$config_value = $cfg_array[$field]; +						$this->new_config[$field] = $config_value; -					$method = 'acp_' . $method; -					if (function_exists($method)) -					{ -						if ($fields = $method($this->new_config)) +						if ($submit)  						{ -							// Check if we need to create config fields for this plugin and save config when submit was pressed -							foreach ($fields['config'] as $field) -							{ -								if (!isset($config[$field])) -								{ -									set_config($field, ''); -								} - -								if (!isset($cfg_array[$field]) || strpos($field, 'legend') !== false) -								{ -									continue; -								} - -								$old_auth_config[$field] = $this->new_config[$field]; -								$config_value = $cfg_array[$field]; -								$this->new_config[$field] = $config_value; - -								if ($submit) -								{ -									$updated_auth_settings = true; -									set_config($field, $config_value); -								} -							} +							$updated_auth_settings = true; +							set_config($field, $config_value);  						} -						unset($fields);  					}  				} +				unset($fields);  			}  			if ($submit && (($cfg_array['auth_method'] != $this->new_config['auth_method']) || $updated_auth_settings))  			{  				$method = basename($cfg_array['auth_method']); -				if ($method && in_array($method, $auth_plugins)) +				if (array_key_exists('auth.provider.' . $method, $auth_providers))  				{ -					include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); - -					$method = 'init_' . $method; -					if (function_exists($method)) +					$provider = $auth_providers['auth.provider.' . $method]; +					if ($error = $provider->init())  					{ -						if ($error = $method()) +						foreach ($old_auth_config as $config_name => $config_value)  						{ -							foreach ($old_auth_config as $config_name => $config_value) -							{ -								set_config($config_name, $config_value); -							} -							trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); +							set_config($config_name, $config_value);  						} +						trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING);  					}  					set_config('auth_method', basename($cfg_array['auth_method']));  				} @@ -591,7 +615,15 @@ class acp_board  		{  			add_log('admin', 'LOG_CONFIG_' . strtoupper($mode)); -			trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); +			$message = $user->lang('CONFIG_UPDATED'); +			$message_type = E_USER_NOTICE; +			if (!$config['email_enable'] && in_array($mode, array('email', 'registration')) && +				in_array($config['require_activation'], array(USER_ACTIVATION_SELF, USER_ACTIVATION_ADMIN))) +			{ +				$message .= '<br /><br />' . $user->lang('ACC_ACTIVATION_WARNING'); +				$message_type = E_USER_WARNING; +			} +			trigger_error($message . adm_back_link($this->u_action), $message_type);  		}  		$this->tpl_name = 'acp_board'; @@ -660,23 +692,22 @@ class acp_board  		{  			$template->assign_var('S_AUTH', true); -			foreach ($auth_plugins as $method) +			foreach ($auth_providers as $provider)  			{ -				if ($method && file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx)) +				$auth_tpl = $provider->get_acp_template($this->new_config); +				if ($auth_tpl)  				{ -					$method = 'acp_' . $method; -					if (function_exists($method)) +					if (array_key_exists('BLOCK_VAR_NAME', $auth_tpl))  					{ -						$fields = $method($this->new_config); - -						if ($fields['tpl']) +						foreach ($auth_tpl['BLOCK_VARS'] as $block_vars)  						{ -							$template->assign_block_vars('auth_tpl', array( -								'TPL'	=> $fields['tpl']) -							); +							$template->assign_block_vars($auth_tpl['BLOCK_VAR_NAME'], $block_vars);  						} -						unset($fields);  					} +					$template->assign_vars($auth_tpl['TEMPLATE_VARS']); +					$template->assign_block_vars('auth_tpl', array( +						'TEMPLATE_FILE'	=> $auth_tpl['TEMPLATE_FILE'], +					));  				}  			}  		} @@ -687,25 +718,19 @@ class acp_board  	*/  	function select_auth_method($selected_method, $key = '')  	{ -		global $phpbb_root_path, $phpEx; +		global $phpbb_root_path, $phpEx, $phpbb_container;  		$auth_plugins = array(); +		$auth_providers = $phpbb_container->get('auth.provider_collection'); -		$dp = @opendir($phpbb_root_path . 'includes/auth'); - -		if (!$dp) +		foreach ($auth_providers as $key => $value)  		{ -			return ''; -		} - -		while (($file = readdir($dp)) !== false) -		{ -			if (preg_match('#^auth_(.*?)\.' . $phpEx . '$#', $file)) +			if (!($value instanceof \phpbb\auth\provider\provider_interface))  			{ -				$auth_plugins[] = preg_replace('#^auth_(.*?)\.' . $phpEx . '$#', '\1', $file); +				continue;  			} +			$auth_plugins[] = str_replace('auth.provider.', '', $key);  		} -		closedir($dp);  		sort($auth_plugins); @@ -713,7 +738,7 @@ class acp_board  		foreach ($auth_plugins as $method)  		{  			$selected = ($selected_method == $method) ? ' selected="selected"' : ''; -			$auth_select .= '<option value="' . $method . '"' . $selected . '>' . ucfirst($method) . '</option>'; +			$auth_select .= "<option value=\"$method\"$selected data-toggle-setting=\"#auth_{$method}_settings\">" . ucfirst($method) . '</option>';  		}  		return $auth_select; @@ -775,20 +800,19 @@ class acp_board  		global $user, $config;  		$act_ary = array( -		  'ACC_DISABLE' => USER_ACTIVATION_DISABLE, -		  'ACC_NONE' => USER_ACTIVATION_NONE, +			'ACC_DISABLE'	=> array(true, USER_ACTIVATION_DISABLE), +			'ACC_NONE'		=> array(true, USER_ACTIVATION_NONE), +			'ACC_USER'		=> array($config['email_enable'], USER_ACTIVATION_SELF), +			'ACC_ADMIN'		=> array($config['email_enable'], USER_ACTIVATION_ADMIN),  		); -		if ($config['email_enable']) -		{ -			$act_ary['ACC_USER'] = USER_ACTIVATION_SELF; -			$act_ary['ACC_ADMIN'] = USER_ACTIVATION_ADMIN; -		}		 -		$act_options = ''; -		foreach ($act_ary as $key => $value) +		$act_options = ''; +		foreach ($act_ary as $key => $data)  		{ +			list($available, $value) = $data;  			$selected = ($selected_value == $value) ? ' selected="selected"' : ''; -			$act_options .= '<option value="' . $value . '"' . $selected . '>' . $user->lang[$key] . '</option>'; +			$class = (!$available) ? ' class="disabled-option"' : ''; +			$act_options .= '<option value="' . $value . '"' . $selected . $class . '>' . $user->lang($key) . '</option>';  		}  		return $act_options; @@ -801,7 +825,7 @@ class acp_board  	{  		global $user; -		return '<input id="' . $key . '" type="text" size="3" maxlength="3" name="config[min_name_chars]" value="' . $value . '" /> ' . $user->lang['MIN_CHARS'] . '  <input type="text" size="3" maxlength="3" name="config[max_name_chars]" value="' . $this->new_config['max_name_chars'] . '" /> ' . $user->lang['MAX_CHARS']; +		return '<input id="' . $key . '" type="number" size="3" maxlength="3" min="1" max="999" name="config[min_name_chars]" value="' . $value . '" /> ' . $user->lang['MIN_CHARS'] . '  <input type="number" size="3" maxlength="3" min="8" max="180" name="config[max_name_chars]" value="' . $this->new_config['max_name_chars'] . '" /> ' . $user->lang['MAX_CHARS'];  	}  	/** @@ -829,7 +853,7 @@ class acp_board  	{  		global $user; -		return '<input id="' . $key . '" type="text" size="3" maxlength="3" name="config[min_pass_chars]" value="' . $value . '" /> ' . $user->lang['MIN_CHARS'] . '  <input type="text" size="3" maxlength="3" name="config[max_pass_chars]" value="' . $this->new_config['max_pass_chars'] . '" /> ' . $user->lang['MAX_CHARS']; +		return '<input id="' . $key . '" type="number" size="3" maxlength="3" min="1" max="999" name="config[min_pass_chars]" value="' . $value . '" /> ' . $user->lang['MIN_CHARS'] . '  <input type="number" size="3" maxlength="3" min="8" max="255" name="config[max_pass_chars]" value="' . $this->new_config['max_pass_chars'] . '" /> ' . $user->lang['MAX_CHARS'];  	}  	/** @@ -893,6 +917,50 @@ class acp_board  			'<br /><br /><input class="button2" type="submit" id="' . $key . '_enable" name="' . $key . '_enable" value="' . $user->lang['ALLOW_QUICK_REPLY_BUTTON'] . '" />';  	} +	/** +	* Select guest timezone +	*/ +	function timezone_select($value, $key) +	{ +		global $template, $user; + +		$timezone_select = phpbb_timezone_select($template, $user, $value, true); + +		return '<select name="config[' . $key . ']" id="' . $key . '">' . $timezone_select . '</select>'; +	} + +	/** +	* Get guest style +	*/ +	public function guest_style_get() +	{ +		global $db; + +		$sql = 'SELECT user_style +			FROM ' . USERS_TABLE . ' +			WHERE user_id = ' . ANONYMOUS; +		$result = $db->sql_query($sql); + +		$style = (int) $db->sql_fetchfield('user_style'); +		$db->sql_freeresult($result); + +		return $style; +	} + +	/** +	* Set guest style +	* +	* @param	int		$style_id	The style ID +	*/ +	public function guest_style_set($style_id) +	{ +		global $db; + +		$sql = 'UPDATE ' . USERS_TABLE . ' +			SET user_style = ' . (int) $style_id . ' +			WHERE user_id = ' . ANONYMOUS; +		$db->sql_query($sql); +	}  	/**  	* Select default dateformat @@ -903,10 +971,14 @@ class acp_board  		// Let the format_date function operate with the acp values  		$old_tz = $user->timezone; -		$old_dst = $user->dst; - -		$user->timezone = $config['board_timezone'] * 3600; -		$user->dst = $config['board_dst'] * 3600; +		try +		{ +			$user->timezone = new DateTimeZone($config['board_timezone']); +		} +		catch (\Exception $e) +		{ +			// If the board timezone is invalid, we just use the users timezone. +		}  		$dateformat_options = ''; @@ -926,7 +998,6 @@ class acp_board  		// Reset users date options  		$user->timezone = $old_tz; -		$user->dst = $old_dst;  		return "<select name=\"dateoptions\" id=\"dateoptions\" onchange=\"if (this.value == 'custom') { document.getElementById('" . addslashes($key) . "').value = '" . addslashes($value) . "'; } else { document.getElementById('" . addslashes($key) . "').value = this.value; }\">$dateformat_options</select>  		<input type=\"text\" name=\"config[$key]\" id=\"$key\" value=\"$value\" maxlength=\"30\" />"; @@ -1000,6 +1071,51 @@ class acp_board  		$cache->destroy('sql', FORUMS_TABLE);  	} -} +	/** +	* Option to enable/disable removal of 'app.php' from URLs +	* +	* Note that if mod_rewrite is on, URLs without app.php will still work, +	* but any paths generated by the controller helper url() method will not +	* contain app.php. +	* +	* @param int $value The current config value +	* @param string $key The config key +	* @return string The HTML for the form field +	*/ +	function enable_mod_rewrite($value, $key) +	{ +		global $user, $config; -?>
\ No newline at end of file +		// Determine whether mod_rewrite is enabled on the server +		// NOTE: This only works on Apache servers on which PHP is NOT +		// installed as CGI. In that case, there is no way for PHP to +		// determine whether or not the Apache module is enabled. +		// +		// To be clear on the value of $mod_rewite: +		// null = Cannot determine whether or not the server has mod_rewrite +		//        enabled +		// false = Can determine that the server does NOT have mod_rewrite +		//         enabled +		// true = Can determine that the server DOES have mod_rewrite_enabled +		$mod_rewrite = null; +		if (function_exists('apache_get_modules')) +		{ +			$mod_rewrite = (bool) in_array('mod_rewrite', apache_get_modules()); +		} + +		// If $message is false, mod_rewrite is enabled. +		// Otherwise, it is not and we need to: +		// 1) disable the form field +		// 2) make sure the config value is set to 0 +		// 3) append the message to the return +		$value = ($mod_rewrite === false) ? 0 : $value; +		$message = $mod_rewrite === null ? 'MOD_REWRITE_INFORMATION_UNAVAILABLE' : ($mod_rewrite === false ? 'MOD_REWRITE_DISABLED' : false); + +		// Let's do some friendly HTML injection if we want to disable the +		// form field because h_radio() has no pretty way of doing so +		$field_name = 'config[enable_mod_rewrite]' . ($message === 'MOD_REWRITE_DISABLED' ? '" disabled="disabled' : ''); + +		return h_radio($field_name, array(1 => 'YES', 0 => 'NO'), $value) . +			($message !== false ? '<br /><span>' . $user->lang($message) . '</span>' : ''); +	} +} diff --git a/phpBB/includes/acp/acp_bots.php b/phpBB/includes/acp/acp_bots.php index d08cabb062..1ea320e674 100644 --- a/phpBB/includes/acp/acp_bots.php +++ b/phpBB/includes/acp/acp_bots.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,16 +19,13 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_bots  {  	var $u_action;  	function main($id, $mode)  	{ -		global $config, $db, $user, $auth, $template, $cache; +		global $config, $db, $user, $auth, $template, $cache, $request;  		global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix;  		$action = request_var('action', ''); @@ -158,7 +158,7 @@ class acp_bots  					{  						$error[] = $user->lang['ERR_BOT_NO_MATCHES'];  					} -			 +  					if ($bot_row['bot_ip'] && !preg_match('#^[\d\.,:]+$#', $bot_row['bot_ip']))  					{  						if (!$ip_list = gethostbynamel($bot_row['bot_ip'])) @@ -177,7 +177,7 @@ class acp_bots  					{  						$error[] = $user->lang['ERR_BOT_AGENT_MATCHES_UA'];  					} -					 +  					$bot_name = false;  					if ($bot_id)  					{ @@ -202,7 +202,7 @@ class acp_bots  					{  						$error[] = $user->lang['BOT_NAME_TAKEN'];  					} -					 +  					if (!sizeof($error))  					{  						// New bot? Create a new user and group entry @@ -220,7 +220,6 @@ class acp_bots  							{  								trigger_error($user->lang['NO_BOT_GROUP'] . adm_back_link($this->u_action . "&id=$bot_id&action=$action"), E_USER_WARNING);  							} -						  							$user_id = user_add(array(  								'user_type'				=> (int) USER_IGNORE, @@ -234,7 +233,7 @@ class acp_bots  								'user_style'			=> (int) $bot_row['bot_style'],  								'user_allow_massemail'	=> 0,  							)); -	 +  							$sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array(  								'user_id'		=> (int) $user_id,  								'bot_name'		=> (string) $bot_row['bot_name'], @@ -243,7 +242,7 @@ class acp_bots  								'bot_ip'		=> (string) $bot_row['bot_ip'])  							);  							$db->sql_query($sql); -	 +  							$log = 'ADDED';  						}  						else if ($bot_id) @@ -290,12 +289,12 @@ class acp_bots  							$log = 'UPDATED';  						} -						 +  						$cache->destroy('_bots'); -						 +  						add_log('admin', 'LOG_BOT_' . $log, $bot_row['bot_name']);  						trigger_error($user->lang['BOT_' . $log] . adm_back_link($this->u_action)); -					 +  					}  				}  				else if ($bot_id) @@ -336,11 +335,11 @@ class acp_bots  					'U_ACTION'		=> $this->u_action . "&id=$bot_id&action=$action",  					'U_BACK'		=> $this->u_action,  					'ERROR_MSG'		=> (sizeof($error)) ? implode('<br />', $error) : '', -					 +  					'BOT_NAME'		=> $bot_row['bot_name'],  					'BOT_IP'		=> $bot_row['bot_ip'],  					'BOT_AGENT'		=> $bot_row['bot_agent'], -					 +  					'S_EDIT_BOT'		=> true,  					'S_ACTIVE_OPTIONS'	=> $s_active_options,  					'S_STYLE_OPTIONS'	=> $style_select, @@ -354,6 +353,14 @@ class acp_bots  			break;  		} +		if ($request->is_ajax() && ($action == 'activate' || $action == 'deactivate')) +		{ +			$json_response = new \phpbb\json_response; +			$json_response->send(array( +				'text'	=> $user->lang['BOT_' . (($action == 'activate') ? 'DE' : '') . 'ACTIVATE'], +			)); +		} +  		$s_options = '';  		$_options = array('activate' => 'BOT_ACTIVATE', 'deactivate' => 'BOT_DEACTIVATE', 'delete' => 'DELETE');  		foreach ($_options as $value => $lang) @@ -390,7 +397,7 @@ class acp_bots  		}  		$db->sql_freeresult($result);  	} -	 +  	/**  	* Validate bot name against username table  	*/ @@ -410,9 +417,7 @@ class acp_bots  		$result = $db->sql_query($sql);  		$row = $db->sql_fetchrow($result);  		$db->sql_freeresult($result); -		 +  		return ($row) ? false : true;  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php index bfec7c27d8..fa8d8fb6a9 100644 --- a/phpBB/includes/acp/acp_captcha.php +++ b/phpBB/includes/acp/acp_captcha.php @@ -1,10 +1,14 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +*  */  /** @@ -15,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_captcha  {  	var $u_action; @@ -25,18 +26,17 @@ class acp_captcha  	function main($id, $mode)  	{  		global $db, $user, $auth, $template; -		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; +		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container;  		$user->add_lang('acp/board'); -		include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); -		$captchas = phpbb_captcha_factory::get_captcha_types(); +		$factory = $phpbb_container->get('captcha.factory'); +		$captchas = $factory->get_captcha_types();  		$selected = request_var('select_captcha', $config['captcha_plugin']);  		$selected = (isset($captchas['available'][$selected]) || isset($captchas['unavailable'][$selected])) ? $selected : $config['captcha_plugin'];  		$configure = request_var('configure', false); -  		// Oh, they are just here for the view  		if (isset($_GET['captcha_demo']))  		{ @@ -46,7 +46,7 @@ class acp_captcha  		// Delegate  		if ($configure)  		{ -			$config_captcha =& phpbb_captcha_factory::get_instance($selected); +			$config_captcha = $factory->get_instance($selected);  			$config_captcha->acp_page($id, $this);  		}  		else @@ -78,11 +78,11 @@ class acp_captcha  					// sanity check  					if (isset($captchas['available'][$selected]))  					{ -						$old_captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']); +						$old_captcha = $factory->get_instance($config['captcha_plugin']);  						$old_captcha->uninstall();  						set_config('captcha_plugin', $selected); -						$new_captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']); +						$new_captcha = $factory->get_instance($config['captcha_plugin']);  						$new_captcha->install();  						add_log('admin', 'LOG_CONFIG_VISUAL'); @@ -104,16 +104,16 @@ class acp_captcha  				foreach ($captchas['available'] as $value => $title)  				{  					$current = ($selected !== false && $value == $selected) ? ' selected="selected"' : ''; -					$captcha_select .= '<option value="' . $value . '"' . $current . '>' . $user->lang[$title] . '</option>'; +					$captcha_select .= '<option value="' . $value . '"' . $current . '>' . $user->lang($title) . '</option>';  				}  				foreach ($captchas['unavailable'] as $value => $title)  				{  					$current = ($selected !== false && $value == $selected) ? ' selected="selected"' : ''; -					$captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option">' . $user->lang[$title] . '</option>'; +					$captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option">' . $user->lang($title) . '</option>';  				} -				$demo_captcha =& phpbb_captcha_factory::get_instance($selected); +				$demo_captcha = $factory->get_instance($selected);  				foreach ($config_vars as $config_var => $options)  				{ @@ -136,9 +136,9 @@ class acp_captcha  	*/  	function deliver_demo($selected)  	{ -		global $db, $user, $config; +		global $db, $user, $config, $phpbb_container; -		$captcha =& phpbb_captcha_factory::get_instance($selected); +		$captcha = $phpbb_container->get('captcha.factory')->get_instance($selected);  		$captcha->init(CONFIRM_REG);  		$captcha->execute_demo(); @@ -146,5 +146,3 @@ class acp_captcha  		exit_handler();  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_contact.php b/phpBB/includes/acp/acp_contact.php new file mode 100644 index 0000000000..4e46df21e0 --- /dev/null +++ b/phpBB/includes/acp/acp_contact.php @@ -0,0 +1,134 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* @package acp +*/ +class acp_contact +{ +	public $u_action; + +	public function main($id, $mode) +	{ +		global $user, $request, $template; +		global $config, $phpbb_root_path, $phpEx, $phpbb_container; + +		$user->add_lang(array('acp/board', 'posting')); + +		$this->tpl_name = 'acp_contact'; +		$this->page_title = 'ACP_CONTACT_SETTINGS'; +		$form_name = 'acp_contact'; +		add_form_key($form_name); +		$error = ''; + +		if (!function_exists('display_custom_bbcodes')) +		{ +			include($phpbb_root_path . 'includes/functions_display.' . $phpEx); +		} +		if (!class_exists('parse_message')) +		{ +			include($phpbb_root_path . 'includes/message_parser.' . $phpEx); +		} + +		$config_text = $phpbb_container->get('config_text'); + +		$contact_admin_data			= $config_text->get_array(array( +			'contact_admin_info', +			'contact_admin_info_uid', +			'contact_admin_info_bitfield', +			'contact_admin_info_flags', +		)); + +		$contact_admin_info			= $contact_admin_data['contact_admin_info']; +		$contact_admin_info_uid		= $contact_admin_data['contact_admin_info_uid']; +		$contact_admin_info_bitfield= $contact_admin_data['contact_admin_info_bitfield']; +		$contact_admin_info_flags	= $contact_admin_data['contact_admin_info_flags']; + +		if ($request->is_set_post('submit') || $request->is_set_post('preview')) +		{ +			if (!check_form_key($form_name)) +			{ +				$error = $user->lang('FORM_INVALID'); +			} + +			$contact_admin_info = $request->variable('contact_admin_info', '', true); + +			generate_text_for_storage( +				$contact_admin_info, +				$contact_admin_info_uid, +				$contact_admin_info_bitfield, +				$contact_admin_info_flags, +				!$request->variable('disable_bbcode', false), +				!$request->variable('disable_magic_url', false), +				!$request->variable('disable_smilies', false) +			); + +			if (empty($error) && $request->is_set_post('submit')) +			{ +				$config->set('contact_admin_form_enable', $request->variable('contact_admin_form_enable', false)); + +				$config_text->set_array(array( +					'contact_admin_info'			=> $contact_admin_info, +					'contact_admin_info_uid'		=> $contact_admin_info_uid, +					'contact_admin_info_bitfield'	=> $contact_admin_info_bitfield, +					'contact_admin_info_flags'		=> $contact_admin_info_flags, +				)); + +				trigger_error($user->lang['CONTACT_US_INFO_UPDATED'] . adm_back_link($this->u_action)); +			} +		} + +		$contact_admin_info_preview = ''; +		if ($request->is_set_post('preview')) +		{ +			$contact_admin_info_preview = generate_text_for_display($contact_admin_info, $contact_admin_info_uid, $contact_admin_info_bitfield, $contact_admin_info_flags); +		} + +		$contact_admin_edit = generate_text_for_edit($contact_admin_info, $contact_admin_info_uid, $contact_admin_info_flags); + +		$template->assign_vars(array( +			'ERRORS'			=> $error, +			'CONTACT_ENABLED'	=> $config['contact_admin_form_enable'], + +			'CONTACT_US_INFO'			=> $contact_admin_edit['text'], +			'CONTACT_US_INFO_PREVIEW'	=> $contact_admin_info_preview, + +			'S_BBCODE_DISABLE_CHECKED'		=> !$contact_admin_edit['allow_bbcode'], +			'S_SMILIES_DISABLE_CHECKED'		=> !$contact_admin_edit['allow_smilies'], +			'S_MAGIC_URL_DISABLE_CHECKED'	=> !$contact_admin_edit['allow_urls'], + +			'BBCODE_STATUS'			=> $user->lang('BBCODE_IS_ON', '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'), +			'SMILIES_STATUS'		=> $user->lang['SMILIES_ARE_ON'], +			'IMG_STATUS'			=> $user->lang['IMAGES_ARE_ON'], +			'FLASH_STATUS'			=> $user->lang['FLASH_IS_ON'], +			'URL_STATUS'			=> $user->lang['URL_IS_ON'], + +			'S_BBCODE_ALLOWED'		=> true, +			'S_SMILIES_ALLOWED'		=> true, +			'S_BBCODE_IMG'			=> true, +			'S_BBCODE_FLASH'		=> true, +			'S_LINKS_ALLOWED'		=> true, +		)); + +		// Assigning custom bbcodes +		display_custom_bbcodes(); +	} +} diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 758cd10434..0c52f82459 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_database  {  	var $db_tools; @@ -29,11 +29,7 @@ class acp_database  		global $cache, $db, $user, $auth, $template, $table_prefix;  		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; -		if (!class_exists('phpbb_db_tools')) -		{ -			require($phpbb_root_path . 'includes/db/db_tools.' . $phpEx); -		} -		$this->db_tools = new phpbb_db_tools($db); +		$this->db_tools = new \phpbb\db\tools($db);  		$user->add_lang('acp/database'); @@ -94,34 +90,34 @@ class acp_database  						$time = time();  						$filename = 'backup_' . $time . '_' . unique_id(); -						switch ($db->sql_layer) +						switch ($db->get_sql_layer())  						{  							case 'mysqli':  							case 'mysql4':  							case 'mysql': -								$extractor = new mysql_extractor($download, $store, $format, $filename, $time); +								$extractor = new mysql_extractor($format, $filename, $time, $download, $store);  							break;  							case 'sqlite': -								$extractor = new sqlite_extractor($download, $store, $format, $filename, $time); +								$extractor = new sqlite_extractor($format, $filename, $time, $download, $store); +							break; + +							case 'sqlite3': +								$extractor = new sqlite3_extractor($format, $filename, $time, $download, $store);  							break;  							case 'postgres': -								$extractor = new postgres_extractor($download, $store, $format, $filename, $time); +								$extractor = new postgres_extractor($format, $filename, $time, $download, $store);  							break;  							case 'oracle': -								$extractor = new oracle_extractor($download, $store, $format, $filename, $time); +								$extractor = new oracle_extractor($format, $filename, $time, $download, $store);  							break;  							case 'mssql':  							case 'mssql_odbc':  							case 'mssqlnative': -								$extractor = new mssql_extractor($download, $store, $format, $filename, $time); -							break; - -							case 'firebird': -								$extractor = new firebird_extractor($download, $store, $format, $filename, $time); +								$extractor = new mssql_extractor($format, $filename, $time, $download, $store);  							break;  						} @@ -137,10 +133,10 @@ class acp_database  							else  							{  								// We might wanna empty out all that junk :D -								switch ($db->sql_layer) +								switch ($db->get_sql_layer())  								{  									case 'sqlite': -									case 'firebird': +									case 'sqlite3':  										$extractor->flush('DELETE FROM ' . $table_name . ";\n");  									break; @@ -273,7 +269,7 @@ class acp_database  									break;  								} -								header('Pragma: no-cache'); +								header('Cache-Control: private, no-cache');  								header("Content-Type: $mimetype; name=\"$name\"");  								header("Content-disposition: attachment; filename=$name"); @@ -324,32 +320,19 @@ class acp_database  								break;  							} -							switch ($db->sql_layer) +							switch ($db->get_sql_layer())  							{  								case 'mysql':  								case 'mysql4':  								case 'mysqli':  								case 'sqlite': +								case 'sqlite3':  									while (($sql = $fgetd($fp, ";\n", $read, $seek, $eof)) !== false)  									{  										$db->sql_query($sql);  									}  								break; -								case 'firebird': -									$delim = ";\n"; -									while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false) -									{ -										$query = trim($sql); -										if (substr($query, 0, 8) === 'SET TERM') -										{ -											$delim = $query[9] . "\n"; -											continue; -										} -										$db->sql_query($query); -									} -								break; -  								case 'postgres':  									$delim = ";\n";  									while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false) @@ -382,10 +365,10 @@ class acp_database  												{  													trigger_error($user->lang['RESTORE_FAILURE'] . adm_back_link($this->u_action), E_USER_WARNING);  												} -												pg_put_line($db->db_connect_id, $sub . "\n"); +												pg_put_line($db->get_db_connect_id(), $sub . "\n");  											} -											pg_put_line($db->db_connect_id, "\\.\n"); -											pg_end_copy($db->db_connect_id); +											pg_put_line($db->get_db_connect_id(), "\\.\n"); +											pg_end_copy($db->get_db_connect_id());  										}  									}  								break; @@ -478,9 +461,6 @@ class acp_database  	}  } -/** -* @package acp -*/  class base_extractor  {  	var $fh; @@ -493,8 +473,10 @@ class base_extractor  	var $format;  	var $run_comp = false; -	function base_extractor($download = false, $store = false, $format, $filename, $time) +	function base_extractor($format, $filename, $time, $download = false, $store = false)  	{ +		global $request; +  		$this->download = $download;  		$this->store = $store;  		$this->time = $time; @@ -528,7 +510,7 @@ class base_extractor  		if ($download == true)  		{  			$name = $filename . $ext; -			header('Pragma: no-cache'); +			header('Cache-Control: private, no-cache');  			header("Content-Type: $mimetype; name=\"$name\"");  			header("Content-disposition: attachment; filename=$name"); @@ -539,7 +521,7 @@ class base_extractor  				break;  				case 'gzip': -					if ((isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) && strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'msie') === false) +					if (strpos($request->header('Accept-Encoding'), 'gzip') !== false && strpos(strtolower($request->header('User-Agent')), 'msie') === false)  					{  						ob_start('ob_gzhandler');  					} @@ -622,9 +604,6 @@ class base_extractor  	}  } -/** -* @package acp -*/  class mysql_extractor extends base_extractor  {  	function write_start($table_prefix) @@ -644,7 +623,7 @@ class mysql_extractor extends base_extractor  		if ($new_extract === null)  		{ -			if ($db->sql_layer === 'mysqli' || version_compare($db->sql_server_info(true), '3.23.20', '>=')) +			if ($db->get_sql_layer() === 'mysqli' || version_compare($db->sql_server_info(true), '3.23.20', '>='))  			{  				$new_extract = true;  			} @@ -667,7 +646,7 @@ class mysql_extractor extends base_extractor  	function write_data($table_name)  	{  		global $db; -		if ($db->sql_layer === 'mysqli') +		if ($db->get_sql_layer() === 'mysqli')  		{  			$this->write_data_mysqli($table_name);  		} @@ -682,7 +661,7 @@ class mysql_extractor extends base_extractor  		global $db;  		$sql = "SELECT *  			FROM $table_name"; -		$result = mysqli_query($db->db_connect_id, $sql, MYSQLI_USE_RESULT); +		$result = mysqli_query($db->get_db_connect_id(), $sql, MYSQLI_USE_RESULT);  		if ($result != false)  		{  			$fields_cnt = mysqli_num_fields($result); @@ -761,7 +740,7 @@ class mysql_extractor extends base_extractor  		global $db;  		$sql = "SELECT *  			FROM $table_name"; -		$result = mysql_unbuffered_query($sql, $db->db_connect_id); +		$result = mysql_unbuffered_query($sql, $db->get_db_connect_id());  		if ($result != false)  		{ @@ -948,9 +927,6 @@ class mysql_extractor extends base_extractor  	}  } -/** -* @package acp -*/  class sqlite_extractor extends base_extractor  {  	function write_start($prefix) @@ -1016,50 +992,118 @@ class sqlite_extractor extends base_extractor  	function write_data($table_name)  	{  		global $db; -		static $proper; -		if (is_null($proper)) -		{ -			$proper = version_compare(PHP_VERSION, '5.1.3', '>='); -		} +		$col_types = sqlite_fetch_column_types($db->get_db_connect_id(), $table_name); -		if ($proper) +		$sql = "SELECT * +			FROM $table_name"; +		$result = sqlite_unbuffered_query($db->get_db_connect_id(), $sql); +		$rows = sqlite_fetch_all($result, SQLITE_ASSOC); +		$sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES ('; +		foreach ($rows as $row)  		{ -			$col_types = sqlite_fetch_column_types($db->db_connect_id, $table_name); +			foreach ($row as $column_name => $column_data) +			{ +				if (is_null($column_data)) +				{ +					$row[$column_name] = 'NULL'; +				} +				else if ($column_data == '') +				{ +					$row[$column_name] = "''"; +				} +				else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false) +				{ +					$row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data)); +				} +			} +			$this->flush($sql_insert . implode(', ', $row) . ");\n");  		} -		else -		{ -			$sql = "SELECT sql -				FROM sqlite_master -				WHERE type = 'table' -					AND name = '" . $table_name . "'"; -			$table_data = sqlite_single_query($db->db_connect_id, $sql); -			$table_data = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', '', $table_data); -			$table_data = trim($table_data); +	} + +	function write_end() +	{ +		$this->flush("COMMIT;\n"); +		parent::write_end(); +	} +} -			preg_match('#\((.*)\)#s', $table_data, $matches); +class sqlite3_extractor extends base_extractor +{ +	function write_start($prefix) +	{ +		$sql_data = "--\n"; +		$sql_data .= "-- phpBB Backup Script\n"; +		$sql_data .= "-- Dump of tables for $prefix\n"; +		$sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; +		$sql_data .= "--\n"; +		$sql_data .= "BEGIN TRANSACTION;\n"; +		$this->flush($sql_data); +	} -			$table_cols = explode(',', trim($matches[1])); -			foreach ($table_cols as $declaration) +	function write_table($table_name) +	{ +		global $db; +		$sql_data = '-- Table: ' . $table_name . "\n"; +		$sql_data .= "DROP TABLE $table_name;\n"; + +		$sql = "SELECT sql +			FROM sqlite_master +			WHERE type = 'table' +				AND name = '" . $db->sql_escape($table_name) . "' +			ORDER BY name ASC;"; +		$result = $db->sql_query($sql); +		$row = $db->sql_fetchrow($result); +		$db->sql_freeresult($result); + +		// Create Table +		$sql_data .= $row['sql'] . ";\n"; + +		$result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');"); + +		while ($row = $db->sql_fetchrow($result)) +		{ +			if (strpos($row['name'], 'autoindex') !== false)  			{ -				$entities = preg_split('#\s+#', trim($declaration)); -				$column_name = preg_replace('/"?([^"]+)"?/', '\1', $entities[0]); +				continue; +			} -				// Hit a primary key, those are not what we need :D -				if (empty($entities[1]) || (strtolower($entities[0]) === 'primary' && strtolower($entities[1]) === 'key')) -				{ -					continue; -				} -				$col_types[$column_name] = $entities[1]; +			$result2 = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($row['name']) . "');"); + +			$fields = array(); +			while ($row2 = $db->sql_fetchrow($result2)) +			{ +				$fields[] = $row2['name'];  			} +			$db->sql_freeresult($result2); + +			$sql_data .= 'CREATE ' . ($row['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $row['name'] . ' ON ' . $table_name . ' (' . implode(', ', $fields) . ");\n"; +		} +		$db->sql_freeresult($result); + +		$this->flush($sql_data . "\n"); +	} + +	function write_data($table_name) +	{ +		global $db; + +		$result = $db->sql_query("PRAGMA table_info('" . $db->sql_escape($table_name) . "');"); + +		$col_types = array(); +		while ($row = $db->sql_fetchrow($result)) +		{ +			$col_types[$row['name']] = $row['type'];  		} +		$db->sql_freeresult($result); + +		$sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES (';  		$sql = "SELECT *  			FROM $table_name"; -		$result = sqlite_unbuffered_query($db->db_connect_id, $sql); -		$rows = sqlite_fetch_all($result, SQLITE_ASSOC); -		$sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES ('; -		foreach ($rows as $row) +		$result = $db->sql_query($sql); + +		while ($row = $db->sql_fetchrow($result))  		{  			foreach ($row as $column_name => $column_data)  			{ @@ -1067,11 +1111,11 @@ class sqlite_extractor extends base_extractor  				{  					$row[$column_name] = 'NULL';  				} -				else if ($column_data == '') +				else if ($column_data === '')  				{  					$row[$column_name] = "''";  				} -				else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false) +				else if (stripos($col_types[$column_name], 'text') !== false || stripos($col_types[$column_name], 'char') !== false || stripos($col_types[$column_name], 'blob') !== false)  				{  					$row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data));  				} @@ -1087,9 +1131,6 @@ class sqlite_extractor extends base_extractor  	}  } -/** -* @package acp -*/  class postgres_extractor extends base_extractor  {  	function write_start($prefix) @@ -1218,7 +1259,6 @@ class postgres_extractor extends base_extractor  		}  		$db->sql_freeresult($result); -  		// Get the listing of primary keys.  		$sql_pri_keys = "SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key  			FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia @@ -1318,7 +1358,6 @@ class postgres_extractor extends base_extractor  			$ary_type[] = pg_field_type($result, $i);  			$ary_name[] = pg_field_name($result, $i); -  			$sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault  				FROM pg_attrdef d, pg_class c  				WHERE (c.relname = '{$table_name}') @@ -1381,9 +1420,6 @@ class postgres_extractor extends base_extractor  	}  } -/** -* @package acp -*/  class mssql_extractor extends base_extractor  {  	function write_end() @@ -1517,11 +1553,11 @@ class mssql_extractor extends base_extractor  	{  		global $db; -		if ($db->sql_layer === 'mssql') +		if ($db->get_sql_layer() === 'mssql')  		{  			$this->write_data_mssql($table_name);  		} -		else if($db->sql_layer === 'mssqlnative') +		else if($db->get_sql_layer() === 'mssqlnative')  		{  			$this->write_data_mssqlnative($table_name);  		} @@ -1624,7 +1660,7 @@ class mssql_extractor extends base_extractor  		}  		$this->flush($sql_data);  	} -	 +  	function write_data_mssqlnative($table_name)  	{  		global $db; @@ -1645,16 +1681,17 @@ class mssql_extractor extends base_extractor  			return;  		} -		$sql = "SELECT * FROM $table_name"; -		$result_fields = $db->sql_query_limit($sql, 1); +		$sql = "SELECT COLUMN_NAME, DATA_TYPE +			FROM INFORMATION_SCHEMA.COLUMNS +			WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = '" . $db->sql_escape($table_name) . "'"; +		$result_fields = $db->sql_query($sql); -		$row = new result_mssqlnative($result_fields); -		$i_num_fields = $row->num_fields(); -		 -		for ($i = 0; $i < $i_num_fields; $i++) +		$i_num_fields = 0; +		while ($row = $db->sql_fetchrow($result_fields))  		{ -			$ary_type[$i] = $row->field_type($i); -			$ary_name[$i] = $row->field_name($i); +			$ary_type[$i_num_fields] = $row['DATA_TYPE']; +			$ary_name[$i_num_fields] = $row['COLUMN_NAME']; +			$i_num_fields++;  		}  		$db->sql_freeresult($result_fields); @@ -1663,7 +1700,7 @@ class mssql_extractor extends base_extractor  			WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";  		$result2 = $db->sql_query($sql);  		$row2 = $db->sql_fetchrow($result2); -		 +  		if (!empty($row2['has_identity']))  		{  			$sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; @@ -1727,8 +1764,8 @@ class mssql_extractor extends base_extractor  			$sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";  		}  		$this->flush($sql_data); -	}	 -	 +	} +  	function write_data_odbc($table_name)  	{  		global $db; @@ -1827,9 +1864,6 @@ class mssql_extractor extends base_extractor  } -/** -* @package acp -*/  class oracle_extractor extends base_extractor  {  	function write_table($table_name) @@ -2057,238 +2091,6 @@ class oracle_extractor extends base_extractor  	}  } -/** -* @package acp -*/ -class firebird_extractor extends base_extractor -{ -	function write_start($prefix) -	{ -		$sql_data = "--\n"; -		$sql_data .= "-- phpBB Backup Script\n"; -		$sql_data .= "-- Dump of tables for $prefix\n"; -		$sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; -		$sql_data .= "--\n"; -		$this->flush($sql_data); -	} - -	function write_data($table_name) -	{ -		global $db; -		$ary_type = $ary_name = array(); - -		// Grab all of the data from current table. -		$sql = "SELECT * -			FROM $table_name"; -		$result = $db->sql_query($sql); - -		$i_num_fields = ibase_num_fields($result); - -		for ($i = 0; $i < $i_num_fields; $i++) -		{ -			$info = ibase_field_info($result, $i); -			$ary_type[$i] = $info['type']; -			$ary_name[$i] = $info['name']; -		} - -		while ($row = $db->sql_fetchrow($result)) -		{ -			$schema_vals = $schema_fields = array(); - -			// Build the SQL statement to recreate the data. -			for ($i = 0; $i < $i_num_fields; $i++) -			{ -				$str_val = $row[strtolower($ary_name[$i])]; - -				if (preg_match('#char|text|bool|varbinary|blob#i', $ary_type[$i])) -				{ -					$str_quote = ''; -					$str_empty = "''"; -					$str_val = sanitize_data_generic(str_replace("'", "''", $str_val)); -				} -				else if (preg_match('#date|timestamp#i', $ary_type[$i])) -				{ -					if (empty($str_val)) -					{ -						$str_quote = ''; -					} -					else -					{ -						$str_quote = "'"; -					} -				} -				else -				{ -					$str_quote = ''; -					$str_empty = 'NULL'; -				} - -				if (empty($str_val) && $str_val !== '0') -				{ -					$str_val = $str_empty; -				} - -				$schema_vals[$i] = $str_quote . $str_val . $str_quote; -				$schema_fields[$i] = '"' . $ary_name[$i] . '"'; -			} - -			// Take the ordered fields and their associated data and build it -			// into a valid sql statement to recreate that field in the data. -			$sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n"; - -			$this->flush($sql_data); -		} -		$db->sql_freeresult($result); -	} - -	function write_table($table_name) -	{ -		global $db; - -		$sql_data = '-- Table: ' . $table_name . "\n"; -		$sql_data .= "DROP TABLE $table_name;\n"; - -		$data_types = array(7 => 'SMALLINT', 8 => 'INTEGER', 10 => 'FLOAT', 12 => 'DATE', 13 => 'TIME', 14 => 'CHARACTER', 27 => 'DOUBLE PRECISION', 35 => 'TIMESTAMP', 37 => 'VARCHAR', 40 => 'CSTRING', 261 => 'BLOB', 701 => 'DECIMAL', 702 => 'NUMERIC'); - -		$sql_data .= "\nCREATE TABLE $table_name (\n"; - -		$sql = 'SELECT DISTINCT R.RDB$FIELD_NAME as FNAME, R.RDB$NULL_FLAG as NFLAG, R.RDB$DEFAULT_SOURCE as DSOURCE, F.RDB$FIELD_TYPE as FTYPE, F.RDB$FIELD_SUB_TYPE as STYPE, F.RDB$FIELD_LENGTH as FLEN -			FROM RDB$RELATION_FIELDS R -			JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME -			LEFT JOIN RDB$FIELD_DIMENSIONS D ON R.RDB$FIELD_SOURCE = D.RDB$FIELD_NAME -			WHERE F.RDB$SYSTEM_FLAG = 0 -				AND R.RDB$RELATION_NAME = \''. $table_name . '\' -			ORDER BY R.RDB$FIELD_POSITION'; -		$result = $db->sql_query($sql); - -		$rows = array(); -		while ($row = $db->sql_fetchrow($result)) -		{ -			$line = "\t" . '"' . $row['fname'] . '" ' . $data_types[$row['ftype']]; - -			if ($row['ftype'] == 261 && $row['stype'] == 1) -			{ -				$line .= ' SUB_TYPE TEXT'; -			} - -			if ($row['ftype'] == 37 || $row['ftype'] == 14) -			{ -				$line .= ' (' . $row['flen'] . ')'; -			} - -			if (!empty($row['dsource'])) -			{ -				$line .= ' ' . $row['dsource']; -			} - -			if (!empty($row['nflag'])) -			{ -				$line .= ' NOT NULL'; -			} -			$rows[] = $line; -		} -		$db->sql_freeresult($result); - -		$sql_data .= implode(",\n", $rows); -		$sql_data .= "\n);\n"; -		$keys = array(); - -		$sql = 'SELECT I.RDB$FIELD_NAME as NAME -			FROM RDB$RELATION_CONSTRAINTS RC, RDB$INDEX_SEGMENTS I, RDB$INDICES IDX -			WHERE (I.RDB$INDEX_NAME = RC.RDB$INDEX_NAME) -				AND (IDX.RDB$INDEX_NAME = RC.RDB$INDEX_NAME) -				AND (RC.RDB$RELATION_NAME = \''. $table_name . '\') -			ORDER BY I.RDB$FIELD_POSITION'; -		$result = $db->sql_query($sql); - -		while ($row = $db->sql_fetchrow($result)) -		{ -			$keys[] = $row['name']; -		} - -		if (sizeof($keys)) -		{ -			$sql_data .= "\nALTER TABLE $table_name ADD PRIMARY KEY (" . implode(', ', $keys) . ');'; -		} - -		$db->sql_freeresult($result); - -		$sql = 'SELECT I.RDB$INDEX_NAME as INAME, I.RDB$UNIQUE_FLAG as UFLAG, S.RDB$FIELD_NAME as FNAME -			FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON S.RDB$INDEX_NAME=I.RDB$INDEX_NAME -			WHERE (I.RDB$SYSTEM_FLAG IS NULL  OR  I.RDB$SYSTEM_FLAG=0) -				AND I.RDB$FOREIGN_KEY IS NULL -				AND I.RDB$RELATION_NAME = \''. $table_name . '\' -				AND I.RDB$INDEX_NAME NOT STARTING WITH \'RDB$\' -			ORDER BY S.RDB$FIELD_POSITION'; -		$result = $db->sql_query($sql); - -		$index = array(); -		while ($row = $db->sql_fetchrow($result)) -		{ -			$index[$row['iname']]['unique'] = !empty($row['uflag']); -			$index[$row['iname']]['values'][] = $row['fname']; -		} - -		foreach ($index as $index_name => $data) -		{ -			$sql_data .= "\nCREATE "; -			if ($data['unique']) -			{ -				$sql_data .= 'UNIQUE '; -			} -			$sql_data .= "INDEX $index_name ON $table_name(" . implode(', ', $data['values']) . ");"; -		} -		$sql_data .= "\n"; - -		$db->sql_freeresult($result); - -		$sql = 'SELECT D1.RDB$DEPENDENT_NAME as DNAME, D1.RDB$FIELD_NAME as FNAME, D1.RDB$DEPENDENT_TYPE, R1.RDB$RELATION_NAME -			FROM RDB$DEPENDENCIES D1 -			LEFT JOIN RDB$RELATIONS R1 ON ((D1.RDB$DEPENDENT_NAME = R1.RDB$RELATION_NAME) AND (NOT (R1.RDB$VIEW_BLR IS NULL))) -			WHERE (D1.RDB$DEPENDED_ON_TYPE = 0) -				AND (D1.RDB$DEPENDENT_TYPE <> 3) -				AND (D1.RDB$DEPENDED_ON_NAME = \'' . $table_name . '\') -			UNION SELECT DISTINCT F2.RDB$RELATION_NAME, D2.RDB$FIELD_NAME, D2.RDB$DEPENDENT_TYPE, R2.RDB$RELATION_NAME FROM RDB$DEPENDENCIES D2, RDB$RELATION_FIELDS F2 -			LEFT JOIN RDB$RELATIONS R2 ON ((F2.RDB$RELATION_NAME = R2.RDB$RELATION_NAME) AND (NOT (R2.RDB$VIEW_BLR IS NULL))) -			WHERE (D2.RDB$DEPENDENT_TYPE = 3) -				AND (D2.RDB$DEPENDENT_NAME = F2.RDB$FIELD_SOURCE) -				AND (D2.RDB$DEPENDED_ON_NAME = \'' . $table_name . '\') -			ORDER BY 1, 2'; -		$result = $db->sql_query($sql); -		while ($row = $db->sql_fetchrow($result)) -		{ -			$sql = 'SELECT T1.RDB$DEPENDED_ON_NAME as GEN, T1.RDB$FIELD_NAME, T1.RDB$DEPENDED_ON_TYPE -				FROM RDB$DEPENDENCIES T1 -				WHERE (T1.RDB$DEPENDENT_NAME = \'' . $row['dname'] . '\') -					AND (T1.RDB$DEPENDENT_TYPE = 2 AND T1.RDB$DEPENDED_ON_TYPE = 14) -				UNION ALL SELECT DISTINCT D.RDB$DEPENDED_ON_NAME, D.RDB$FIELD_NAME, D.RDB$DEPENDED_ON_TYPE -				FROM RDB$DEPENDENCIES D, RDB$RELATION_FIELDS F -				WHERE (D.RDB$DEPENDENT_TYPE = 3) -					AND (D.RDB$DEPENDENT_NAME = F.RDB$FIELD_SOURCE) -					AND (F.RDB$RELATION_NAME = \'' . $row['dname'] . '\') -				ORDER BY 1,2'; -			$result2 = $db->sql_query($sql); -			$row2 = $db->sql_fetchrow($result2); -			$db->sql_freeresult($result2); -			$gen_name = $row2['gen']; - -			$sql_data .= "\nDROP GENERATOR " . $gen_name . ";"; -			$sql_data .= "\nSET TERM ^ ;"; -			$sql_data .= "\nCREATE GENERATOR " . $gen_name . "^"; -			$sql_data .= "\nSET GENERATOR  " . $gen_name . " TO 0^\n"; -			$sql_data .= "\nCREATE TRIGGER {$row['dname']} FOR $table_name"; -			$sql_data .= "\nBEFORE INSERT\nAS\nBEGIN"; -			$sql_data .= "\n  NEW.{$row['fname']} = GEN_ID(" . $gen_name . ", 1);"; -			$sql_data .= "\nEND^\n"; -			$sql_data .= "\nSET TERM ; ^\n"; -		} - -		$this->flush($sql_data); - -		$db->sql_freeresult($result); -	} -} -  // get how much space we allow for a chunk of data, very similar to phpMyAdmin's way of doing things ;-) (hey, we only do this for MySQL anyway :P)  function get_usable_memory()  { @@ -2464,5 +2266,3 @@ function fgetd_seekless(&$fp, $delim, $read, $seek, $eof, $buffer = 8192)  	return false;  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_disallow.php b/phpBB/includes/acp/acp_disallow.php index e2176b7bcd..4c8f3cc65b 100644 --- a/phpBB/includes/acp/acp_disallow.php +++ b/phpBB/includes/acp/acp_disallow.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_disallow  {  	var $u_action; @@ -116,5 +116,3 @@ class acp_disallow  		);  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index df0d44c0c5..fcc2bd7641 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_email  {  	var $u_action; @@ -26,7 +26,7 @@ class acp_email  	function main($id, $mode)  	{  		global $config, $db, $user, $auth, $template, $cache; -		global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; +		global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $phpbb_dispatcher;  		$user->add_lang('acp/email');  		$this->tpl_name = 'acp_email'; @@ -40,6 +40,7 @@ class acp_email  		$error = array();  		$usernames	= request_var('usernames', '', true); +		$usernames	= (!empty($usernames)) ? explode("\n", $usernames) : array();  		$group_id	= request_var('g', 0);  		$subject	= utf8_normalize_nfc(request_var('subject', '', true));  		$message	= utf8_normalize_nfc(request_var('message', '', true)); @@ -69,14 +70,18 @@ class acp_email  			if (!sizeof($error))  			{ -				if ($usernames) +				if (!empty($usernames))  				{  					// If giving usernames the admin is able to email inactive users too... -					$sql = 'SELECT username, user_email, user_jabber, user_notify_type, user_lang -						FROM ' . USERS_TABLE . ' -						WHERE ' . $db->sql_in_set('username_clean', array_map('utf8_clean_string', explode("\n", $usernames))) . ' -							AND user_allow_massemail = 1 -						ORDER BY user_lang, user_notify_type'; // , SUBSTRING(user_email FROM INSTR(user_email, '@')) +					$sql_ary = array( +						'SELECT'	=> 'username, user_email, user_jabber, user_notify_type, user_lang', +						'FROM'		=> array( +							USERS_TABLE		=> '', +						), +						'WHERE'		=> $db->sql_in_set('username_clean', array_map('utf8_clean_string', $usernames)) . ' +							AND user_allow_massemail = 1', +						'ORDER_BY'	=> 'user_lang, user_notify_type', +					);  				}  				else  				{ @@ -123,8 +128,18 @@ class acp_email  							),  						);  					} -					$sql = $db->sql_build_query('SELECT', $sql_ary);  				} +				/** +				* Modify sql query to change the list of users the email is sent to +				* +				* @event core.acp_email_modify_sql +				* @var	array	sql_ary		Array which is used to build the sql query +				* @since 3.1.2-RC1 +				*/ +				$vars = array('sql_ary'); +				extract($phpbb_dispatcher->trigger_event('core.acp_email_modify_sql', compact($vars))); + +				$sql = $db->sql_build_query('SELECT', $sql_ary);  				$result = $db->sql_query($sql);  				$row = $db->sql_fetchrow($result); @@ -180,6 +195,39 @@ class acp_email  				$errored = false; +				$email_template = 'admin_send_email'; +				$template_data = array( +					'CONTACT_EMAIL' => phpbb_get_board_contact($config, $phpEx), +					'MESSAGE'		=> htmlspecialchars_decode($message), +				); +				$generate_log_entry = true; + +				/** +				* Modify email template data before the emails are sent +				* +				* @event core.acp_email_send_before +				* @var	string	email_template		The template to be used for sending the email +				* @var	string	subject				The subject of the email +				* @var	array	template_data		Array with template data assigned to email template +				* @var	bool	generate_log_entry	If false, no log entry will be created +				* @var	array	usernames			Usernames which will be displayed in log entry, if it will be created +				* @var	int		group_id			The group this email will be sent to +				* @var	bool	use_queue			If true, email queue will be used for sending +				* @var	int		priority			Priority of sent emails +				* @since 3.1.3-RC1 +				*/ +				$vars = array( +					'email_template', +					'subject', +					'template_data', +					'generate_log_entry', +					'usernames', +					'group_id', +					'use_queue', +					'priority', +				); +				extract($phpbb_dispatcher->trigger_event('core.acp_email_send_before', compact($vars))); +  				for ($i = 0, $size = sizeof($email_list); $i < $size; $i++)  				{  					$used_lang = $email_list[$i][0]['lang']; @@ -193,17 +241,14 @@ class acp_email  						$messenger->im($email_row['jabber'], $email_row['name']);  					} -					$messenger->template('admin_send_email', $used_lang); +					$messenger->template($email_template, $used_lang);  					$messenger->anti_abuse_headers($config, $user);  					$messenger->subject(htmlspecialchars_decode($subject));  					$messenger->set_mail_priority($priority); -					$messenger->assign_vars(array( -						'CONTACT_EMAIL' => $config['board_contact'], -						'MESSAGE'		=> htmlspecialchars_decode($message)) -					); +					$messenger->assign_vars($template_data);  					if (!($messenger->send($used_method)))  					{ @@ -214,24 +259,26 @@ class acp_email  				$messenger->save_queue(); -				if ($usernames) -				{ -					$usernames = explode("\n", $usernames); -					add_log('admin', 'LOG_MASS_EMAIL', implode(', ', utf8_normalize_nfc($usernames))); -				} -				else +				if ($generate_log_entry)  				{ -					if ($group_id) +					if (!empty($usernames))  					{ -						$group_name = get_group_name($group_id); +						add_log('admin', 'LOG_MASS_EMAIL', implode(', ', utf8_normalize_nfc($usernames)));  					}  					else  					{ -						// Not great but the logging routine doesn't cope well with localising on the fly -						$group_name = $user->lang['ALL_USERS']; -					} +						if ($group_id) +						{ +							$group_name = get_group_name($group_id); +						} +						else +						{ +							// Not great but the logging routine doesn't cope well with localising on the fly +							$group_name = $user->lang['ALL_USERS']; +						} -					add_log('admin', 'LOG_MASS_EMAIL', $group_name); +						add_log('admin', 'LOG_MASS_EMAIL', $group_name); +					}  				}  				if (!$errored) @@ -272,7 +319,7 @@ class acp_email  			'WARNING_MSG'			=> (sizeof($error)) ? implode('<br />', $error) : '',  			'U_ACTION'				=> $this->u_action,  			'S_GROUP_OPTIONS'		=> $select_list, -			'USERNAMES'				=> $usernames, +			'USERNAMES'				=> implode("\n", $usernames),  			'U_FIND_USERNAME'		=> append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=acp_email&field=usernames'),  			'SUBJECT'				=> $subject,  			'MESSAGE'				=> $message, @@ -281,5 +328,3 @@ class acp_email  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php new file mode 100644 index 0000000000..89fdc8b863 --- /dev/null +++ b/phpBB/includes/acp/acp_extensions.php @@ -0,0 +1,555 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +class acp_extensions +{ +	var $u_action; + +	private $db; +	private $config; +	private $template; +	private $user; +	private $cache; +	private $log; +	private $request; + +	function main() +	{ +		// Start the page +		global $config, $user, $template, $request, $phpbb_extension_manager, $db, $phpbb_root_path, $phpEx, $phpbb_log, $cache; + +		$this->db = $db; +		$this->config = $config; +		$this->template = $template; +		$this->user = $user; +		$this->cache = $cache; +		$this->request = $request; +		$this->log = $phpbb_log; + +		$user->add_lang(array('install', 'acp/extensions', 'migrator')); + +		$this->page_title = 'ACP_EXTENSIONS'; + +		$action = $request->variable('action', 'list'); +		$ext_name = $request->variable('ext_name', ''); + +		// What is a safe limit of execution time? Half the max execution time should be safe. +		$safe_time_limit = (ini_get('max_execution_time') / 2); +		$start_time = time(); + +		// Cancel action +		if ($request->is_set_post('cancel')) +		{ +			$action = 'list'; +			$ext_name = ''; +		} + +		if (in_array($action, array('enable', 'disable', 'delete_data')) && !check_link_hash($request->variable('hash', ''), $action . '.' . $ext_name)) +		{ +			trigger_error('FORM_INVALID', E_USER_WARNING); +		} + +		// If they've specified an extension, let's load the metadata manager and validate it. +		if ($ext_name) +		{ +			$md_manager = new \phpbb\extension\metadata_manager($ext_name, $config, $phpbb_extension_manager, $template, $user, $phpbb_root_path); + +			try +			{ +				$md_manager->get_metadata('all'); +			} +			catch(\phpbb\extension\exception $e) +			{ +				trigger_error($e, E_USER_WARNING); +			} +		} + +		// What are we doing? +		switch ($action) +		{ +			case 'set_config_version_check_force_unstable': +				$force_unstable = $this->request->variable('force_unstable', false); + +				if ($force_unstable) +				{ +					$s_hidden_fields = build_hidden_fields(array( +						'force_unstable'	=> $force_unstable, +					)); + +					confirm_box(false, $user->lang('EXTENSION_FORCE_UNSTABLE_CONFIRM'), $s_hidden_fields); +				} +				else +				{ +					$config->set('extension_force_unstable', false); +					trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); +				} +				break; + +			case 'list': +			default: +				if (confirm_box(true)) +				{ +					$config->set('extension_force_unstable', true); +					trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); +				} + +				$this->list_enabled_exts($phpbb_extension_manager); +				$this->list_disabled_exts($phpbb_extension_manager); +				$this->list_available_exts($phpbb_extension_manager); + +				$this->template->assign_vars(array( +					'U_VERSIONCHECK_FORCE' 	=> $this->u_action . '&action=list&versioncheck_force=1', +					'FORCE_UNSTABLE'		=> $config['extension_force_unstable'], +					'U_ACTION' 				=> $this->u_action, +				)); + +				add_form_key('version_check_settings'); + +				$this->tpl_name = 'acp_ext_list'; +			break; + +			case 'enable_pre': +				if (!$md_manager->validate_dir()) +				{ +					trigger_error($user->lang['EXTENSION_DIR_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); +				} + +				if (!$md_manager->validate_enable()) +				{ +					trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action), E_USER_WARNING); +				} + +				$extension = $phpbb_extension_manager->get_extension($ext_name); +				if (!$extension->is_enableable()) +				{ +					trigger_error($user->lang['EXTENSION_NOT_ENABLEABLE'] . adm_back_link($this->u_action), E_USER_WARNING); +				} + +				if ($phpbb_extension_manager->is_enabled($ext_name)) +				{ +					redirect($this->u_action); +				} + +				$this->tpl_name = 'acp_ext_enable'; + +				$template->assign_vars(array( +					'PRE'				=> true, +					'L_CONFIRM_MESSAGE'	=> $this->user->lang('EXTENSION_ENABLE_CONFIRM', $md_manager->get_metadata('display-name')), +					'U_ENABLE'			=> $this->u_action . '&action=enable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('enable.' . $ext_name), +				)); +			break; + +			case 'enable': +				if (!$md_manager->validate_dir()) +				{ +					trigger_error($user->lang['EXTENSION_DIR_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); +				} + +				if (!$md_manager->validate_enable()) +				{ +					trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action), E_USER_WARNING); +				} + +				$extension = $phpbb_extension_manager->get_extension($ext_name); +				if (!$extension->is_enableable()) +				{ +					trigger_error($user->lang['EXTENSION_NOT_ENABLEABLE'] . adm_back_link($this->u_action), E_USER_WARNING); +				} + +				if ($phpbb_extension_manager->is_enabled($ext_name)) +				{ +					redirect($this->u_action); +				} + +				try +				{ +					while ($phpbb_extension_manager->enable_step($ext_name)) +					{ +						// Are we approaching the time limit? If so we want to pause the update and continue after refreshing +						if ((time() - $start_time) >= $safe_time_limit) +						{ +							$template->assign_var('S_NEXT_STEP', true); + +							meta_refresh(0, $this->u_action . '&action=enable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('enable.' . $ext_name)); +						} +					} +					$this->log->add('admin', $user->data['user_id'], $user->ip, 'LOG_EXT_ENABLE', time(), array($ext_name)); +				} +				catch (\phpbb\db\migration\exception $e) +				{ +					$template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($user)); +				} + +				$this->tpl_name = 'acp_ext_enable'; + +				$template->assign_vars(array( +					'U_RETURN'		=> $this->u_action . '&action=list', +				)); +			break; + +			case 'disable_pre': +				if (!$phpbb_extension_manager->is_enabled($ext_name)) +				{ +					redirect($this->u_action); +				} + +				$this->tpl_name = 'acp_ext_disable'; + +				$template->assign_vars(array( +					'PRE'				=> true, +					'L_CONFIRM_MESSAGE'	=> $this->user->lang('EXTENSION_DISABLE_CONFIRM', $md_manager->get_metadata('display-name')), +					'U_DISABLE'			=> $this->u_action . '&action=disable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('disable.' . $ext_name), +				)); +			break; + +			case 'disable': +				if (!$phpbb_extension_manager->is_enabled($ext_name)) +				{ +					redirect($this->u_action); +				} + +				while ($phpbb_extension_manager->disable_step($ext_name)) +				{ +					// Are we approaching the time limit? If so we want to pause the update and continue after refreshing +					if ((time() - $start_time) >= $safe_time_limit) +					{ +						$template->assign_var('S_NEXT_STEP', true); + +						meta_refresh(0, $this->u_action . '&action=disable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('disable.' . $ext_name)); +					} +				} +				$this->log->add('admin', $user->data['user_id'], $user->ip, 'LOG_EXT_DISABLE', time(), array($ext_name)); + +				$this->tpl_name = 'acp_ext_disable'; + +				$template->assign_vars(array( +					'U_RETURN'	=> $this->u_action . '&action=list', +				)); +			break; + +			case 'delete_data_pre': +				if ($phpbb_extension_manager->is_enabled($ext_name)) +				{ +					redirect($this->u_action); +				} +				$this->tpl_name = 'acp_ext_delete_data'; + +				$template->assign_vars(array( +					'PRE'				=> true, +					'L_CONFIRM_MESSAGE'	=> $this->user->lang('EXTENSION_DELETE_DATA_CONFIRM', $md_manager->get_metadata('display-name')), +					'U_PURGE'			=> $this->u_action . '&action=delete_data&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('delete_data.' . $ext_name), +				)); +			break; + +			case 'delete_data': +				if ($phpbb_extension_manager->is_enabled($ext_name)) +				{ +					redirect($this->u_action); +				} + +				try +				{ +					while ($phpbb_extension_manager->purge_step($ext_name)) +					{ +						// Are we approaching the time limit? If so we want to pause the update and continue after refreshing +						if ((time() - $start_time) >= $safe_time_limit) +						{ +							$template->assign_var('S_NEXT_STEP', true); + +							meta_refresh(0, $this->u_action . '&action=delete_data&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('delete_data.' . $ext_name)); +						} +					} +					$this->log->add('admin', $user->data['user_id'], $user->ip, 'LOG_EXT_PURGE', time(), array($ext_name)); +				} +				catch (\phpbb\db\migration\exception $e) +				{ +					$template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($user)); +				} + +				$this->tpl_name = 'acp_ext_delete_data'; + +				$template->assign_vars(array( +					'U_RETURN'	=> $this->u_action . '&action=list', +				)); +			break; + +			case 'details': +				// Output it to the template +				$md_manager->output_template_data(); + +				try +				{ +					$updates_available = $this->version_check($md_manager, $request->variable('versioncheck_force', false)); + +					$template->assign_vars(array( +						'S_UP_TO_DATE'		=> empty($updates_available), +						'S_VERSIONCHECK'	=> true, +						'UP_TO_DATE_MSG'	=> $this->user->lang(empty($updates_available) ? 'UP_TO_DATE' : 'NOT_UP_TO_DATE', $md_manager->get_metadata('display-name')), +					)); + +					foreach ($updates_available as $branch => $version_data) +					{ +						$template->assign_block_vars('updates_available', $version_data); +					} +				} +				catch (\RuntimeException $e) +				{ +					$template->assign_vars(array( +						'S_VERSIONCHECK_STATUS'			=> $e->getCode(), +						'VERSIONCHECK_FAIL_REASON'		=> ($e->getMessage() !== $user->lang('VERSIONCHECK_FAIL')) ? $e->getMessage() : '', +					)); +				} + +				$template->assign_vars(array( +					'U_BACK'				=> $this->u_action . '&action=list', +					'U_VERSIONCHECK_FORCE'	=> $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')), +				)); + +				$this->tpl_name = 'acp_ext_details'; +			break; +		} +	} + +	/** +	* Lists all the enabled extensions and dumps to the template +	* +	* @param  $phpbb_extension_manager     An instance of the extension manager +	* @return null +	*/ +	public function list_enabled_exts(\phpbb\extension\manager $phpbb_extension_manager) +	{ +		$enabled_extension_meta_data = array(); + +		foreach ($phpbb_extension_manager->all_enabled() as $name => $location) +		{ +			$md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name, $this->template); + +			try +			{ +				$meta = $md_manager->get_metadata('all'); +				$enabled_extension_meta_data[$name] = array( +					'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'), +					'META_VERSION' => $meta['version'], +				); + +				$force_update = $this->request->variable('versioncheck_force', false); +				$updates = $this->version_check($md_manager, $force_update, !$force_update); + +				$enabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); +				$enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; +				$enabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); +			} +			catch(\phpbb\extension\exception $e) +			{ +				$this->template->assign_block_vars('disabled', array( +					'META_DISPLAY_NAME'		=> $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), +					'S_VERSIONCHECK'		=> false, +				)); +			} +			catch (\RuntimeException $e) +			{ +				$enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false; +			} +		} + +		uasort($enabled_extension_meta_data, array($this, 'sort_extension_meta_data_table')); + +		foreach ($enabled_extension_meta_data as $name => $block_vars) +		{ +			$block_vars['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name); + +			$this->template->assign_block_vars('enabled', $block_vars); + +			$this->output_actions('enabled', array( +				'DISABLE'		=> $this->u_action . '&action=disable_pre&ext_name=' . urlencode($name), +			)); +		} +	} + +	/** +	* Lists all the disabled extensions and dumps to the template +	* +	* @param  $phpbb_extension_manager     An instance of the extension manager +	* @return null +	*/ +	public function list_disabled_exts(\phpbb\extension\manager $phpbb_extension_manager) +	{ +		$disabled_extension_meta_data = array(); + +		foreach ($phpbb_extension_manager->all_disabled() as $name => $location) +		{ +			$md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name, $this->template); + +			try +			{ +				$meta = $md_manager->get_metadata('all'); +				$disabled_extension_meta_data[$name] = array( +					'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'), +					'META_VERSION' => $meta['version'], +				); + +				$force_update = $this->request->variable('versioncheck_force', false); +				$updates = $this->version_check($md_manager, $force_update, !$force_update); + +				$disabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); +				$disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; +				$disabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); +			} +			catch(\phpbb\extension\exception $e) +			{ +				$this->template->assign_block_vars('disabled', array( +					'META_DISPLAY_NAME'		=> $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), +					'S_VERSIONCHECK'		=> false, +				)); +			} +			catch (\RuntimeException $e) +			{ +				$disabeld_extension_meta_data[$name]['S_VERSIONCHECK'] = false; +			} +		} + +		uasort($disabled_extension_meta_data, array($this, 'sort_extension_meta_data_table')); + +		foreach ($disabled_extension_meta_data as $name => $block_vars) +		{ +			$block_vars['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name); + +			$this->template->assign_block_vars('disabled', $block_vars); + +			$this->output_actions('disabled', array( +				'ENABLE'		=> $this->u_action . '&action=enable_pre&ext_name=' . urlencode($name), +				'DELETE_DATA'	=> $this->u_action . '&action=delete_data_pre&ext_name=' . urlencode($name), +			)); +		} +	} + +	/** +	* Lists all the available extensions and dumps to the template +	* +	* @param  $phpbb_extension_manager     An instance of the extension manager +	* @return null +	*/ +	public function list_available_exts(\phpbb\extension\manager $phpbb_extension_manager) +	{ +		$uninstalled = array_diff_key($phpbb_extension_manager->all_available(), $phpbb_extension_manager->all_configured()); + +		$available_extension_meta_data = array(); + +		foreach ($uninstalled as $name => $location) +		{ +			$md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name, $this->template); + +			try +			{ +				$meta = $md_manager->get_metadata('all'); +				$available_extension_meta_data[$name] = array( +					'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'), +					'META_VERSION' => $meta['version'], +				); + +				$force_update = $this->request->variable('versioncheck_force', false); +				$updates = $this->version_check($md_manager, $force_update, !$force_update); + +				$available_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates); +				$available_extension_meta_data[$name]['S_VERSIONCHECK'] = true; +				$available_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); +			} +			catch(\phpbb\extension\exception $e) +			{ +				$this->template->assign_block_vars('disabled', array( +					'META_DISPLAY_NAME'		=> $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), +					'S_VERSIONCHECK'		=> false, +				)); +			} +			catch (\RuntimeException $e) +			{ +				$available_extension_meta_data[$name]['S_VERSIONCHECK'] = false; +			} +		} + +		uasort($available_extension_meta_data, array($this, 'sort_extension_meta_data_table')); + +		foreach ($available_extension_meta_data as $name => $block_vars) +		{ +			$block_vars['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name); + +			$this->template->assign_block_vars('disabled', $block_vars); + +			$this->output_actions('disabled', array( +				'ENABLE'		=> $this->u_action . '&action=enable_pre&ext_name=' . urlencode($name), +			)); +		} +	} + +	/** +	* Output actions to a block +	* +	* @param string $block +	* @param array $actions +	*/ +	private function output_actions($block, $actions) +	{ +		foreach ($actions as $lang => $url) +		{ +			$this->template->assign_block_vars($block . '.actions', array( +				'L_ACTION'			=> $this->user->lang('EXTENSION_' . $lang), +				'L_ACTION_EXPLAIN'	=> (isset($this->user->lang['EXTENSION_' . $lang . '_EXPLAIN'])) ? $this->user->lang('EXTENSION_' . $lang . '_EXPLAIN') : '', +				'U_ACTION'			=> $url, +			)); +		} +	} + +	/** +	* Check the version and return the available updates. +	* +	* @param \phpbb\extension\metadata_manager $md_manager The metadata manager for the version to check. +	* @param bool $force_update Ignores cached data. Defaults to false. +	* @param bool $force_cache Force the use of the cache. Override $force_update. +	* @return string +	* @throws RuntimeException +	*/ +	protected function version_check(\phpbb\extension\metadata_manager $md_manager, $force_update = false, $force_cache = false) +	{ +		$meta = $md_manager->get_metadata('all'); + +		if (!isset($meta['extra']['version-check'])) +		{ +			throw new \RuntimeException($this->user->lang('NO_VERSIONCHECK'), 1); +		} + +		$version_check = $meta['extra']['version-check']; + +		$version_helper = new \phpbb\version_helper($this->cache, $this->config, new \phpbb\file_downloader(), $this->user); +		$version_helper->set_current_version($meta['version']); +		$version_helper->set_file_location($version_check['host'], $version_check['directory'], $version_check['filename']); +		$version_helper->force_stability($this->config['extension_force_unstable'] ? 'unstable' : null); + +		return $updates = $version_helper->get_suggested_updates($force_update, $force_cache); +	} + +	/** +	* Sort helper for the table containing the metadata about the extensions. +	*/ +	protected function sort_extension_meta_data_table($val1, $val2) +	{ +		return strnatcasecmp($val1['META_DISPLAY_NAME'], $val2['META_DISPLAY_NAME']); +	} +} diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index dc2e6b75fb..adf5de44f5 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_forums  {  	var $u_action; @@ -26,7 +26,7 @@ class acp_forums  	function main($id, $mode)  	{ -		global $db, $user, $auth, $template, $cache; +		global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher;  		global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx;  		$user->add_lang('acp/forums'); @@ -139,17 +139,31 @@ class acp_forums  						'enable_prune'			=> request_var('enable_prune', false),  						'enable_post_review'	=> request_var('enable_post_review', true),  						'enable_quick_reply'	=> request_var('enable_quick_reply', false), +						'enable_shadow_prune'		=> request_var('enable_shadow_prune', false),  						'prune_days'			=> request_var('prune_days', 7),  						'prune_viewed'			=> request_var('prune_viewed', 7),  						'prune_freq'			=> request_var('prune_freq', 1),  						'prune_old_polls'		=> request_var('prune_old_polls', false),  						'prune_announce'		=> request_var('prune_announce', false),  						'prune_sticky'			=> request_var('prune_sticky', false), +						'prune_shadow_days'		=> request_var('prune_shadow_days', 7), +						'prune_shadow_freq'		=> request_var('prune_shadow_freq', 1),  						'forum_password'		=> request_var('forum_password', '', true),  						'forum_password_confirm'=> request_var('forum_password_confirm', '', true),  						'forum_password_unset'	=> request_var('forum_password_unset', false),  					); +					/** +					* Request forum data and operate on it (parse texts, etc.) +					* +					* @event core.acp_manage_forums_request_data +					* @var	string	action		Type of the action: add|edit +					* @var	array	forum_data	Array with new forum data +					* @since 3.1.0-a1 +					*/ +					$vars = array('action', 'forum_data'); +					extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_request_data', compact($vars))); +  					// On add, add empty forum_options... else do not consider it (not updating it)  					if ($action == 'add')  					{ @@ -195,7 +209,7 @@ class acp_forums  							($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))))  						{  							copy_forum_permissions($forum_perm_from, $forum_data['forum_id'], ($action == 'edit') ? true : false); -							cache_moderators(); +							phpbb_cache_moderators($db, $cache, $auth);  							$copied_permissions = true;  						}  /* Commented out because of questionable UI workflow - re-visit for 3.0.7 @@ -256,6 +270,12 @@ class acp_forums  					$cache->destroy('sql', FORUMS_TABLE);  				} +				if ($request->is_ajax()) +				{ +					$json_response = new \phpbb\json_response; +					$json_response->send(array('success' => ($move_forum_name !== false))); +				} +  			break;  			case 'sync': @@ -266,7 +286,7 @@ class acp_forums  				@set_time_limit(0); -				$sql = 'SELECT forum_name, forum_topics_real +				$sql = 'SELECT forum_name, (forum_topics_approved + forum_topics_unapproved + forum_topics_softdeleted) AS total_topics  					FROM ' . FORUMS_TABLE . "  					WHERE forum_id = $forum_id";  				$result = $db->sql_query($sql); @@ -278,7 +298,7 @@ class acp_forums  					trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING);  				} -				if ($row['forum_topics_real']) +				if ($row['total_topics'])  				{  					$sql = 'SELECT MIN(topic_id) as min_topic_id, MAX(topic_id) as max_topic_id  						FROM ' . TOPICS_TABLE . ' @@ -297,7 +317,6 @@ class acp_forums  					$end = $start + $batch_size;  					// Sync all topics in batch mode... -					sync('topic_approved', 'range', 'topic_id BETWEEN ' . $start . ' AND ' . $end, true, false);  					sync('topic', 'range', 'topic_id BETWEEN ' . $start . ' AND ' . $end, true, true);  					if ($end < $row2['max_topic_id']) @@ -313,15 +332,15 @@ class acp_forums  						$start += $batch_size; -						$url = $this->u_action . "&parent_id={$this->parent_id}&f=$forum_id&action=sync&start=$start&topics_done=$topics_done&total={$row['forum_topics_real']}"; +						$url = $this->u_action . "&parent_id={$this->parent_id}&f=$forum_id&action=sync&start=$start&topics_done=$topics_done&total={$row['total_topics']}";  						meta_refresh(0, $url);  						$template->assign_vars(array( -							'U_PROGRESS_BAR'		=> $this->u_action . "&action=progress_bar&start=$topics_done&total={$row['forum_topics_real']}", -							'UA_PROGRESS_BAR'		=> addslashes($this->u_action . "&action=progress_bar&start=$topics_done&total={$row['forum_topics_real']}"), +							'U_PROGRESS_BAR'		=> $this->u_action . "&action=progress_bar&start=$topics_done&total={$row['total_topics']}", +							'UA_PROGRESS_BAR'		=> addslashes($this->u_action . "&action=progress_bar&start=$topics_done&total={$row['total_topics']}"),  							'S_CONTINUE_SYNC'		=> true, -							'L_PROGRESS_EXPLAIN'	=> sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], $topics_done, $row['forum_topics_real'])) +							'L_PROGRESS_EXPLAIN'	=> sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], $topics_done, $row['total_topics']))  						);  						return; @@ -335,7 +354,7 @@ class acp_forums  					'U_PROGRESS_BAR'		=> $this->u_action . '&action=progress_bar',  					'UA_PROGRESS_BAR'		=> addslashes($this->u_action . '&action=progress_bar'),  					'S_CONTINUE_SYNC'		=> true, -					'L_PROGRESS_EXPLAIN'	=> sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], 0, $row['forum_topics_real'])) +					'L_PROGRESS_EXPLAIN'	=> sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], 0, $row['total_topics']))  				);  				return; @@ -380,6 +399,9 @@ class acp_forums  					$forum_data['forum_flags'] += (request_var('enable_quick_reply', false)) ? FORUM_FLAG_QUICK_REPLY : 0;  				} +				// Initialise $row, so we always have it in the event +				$row = array(); +  				// Show form to create/modify a forum  				if ($action == 'edit')  				{ @@ -439,6 +461,9 @@ class acp_forums  							'prune_days'			=> 7,  							'prune_viewed'			=> 7,  							'prune_freq'			=> 1, +							'enable_shadow_prune'		=> false, +							'prune_shadow_days'		=> 7, +							'prune_shadow_freq'		=> 1,  							'forum_flags'			=> FORUM_FLAG_POST_REVIEW + FORUM_FLAG_ACTIVE_TOPICS,  							'forum_options'			=> 0,  							'forum_password'		=> '', @@ -447,6 +472,24 @@ class acp_forums  					}  				} +				/** +				* Initialise data before we display the add/edit form +				* +				* @event core.acp_manage_forums_initialise_data +				* @var	string	action		Type of the action: add|edit +				* @var	bool	update		Do we display the form only +				*							or did the user press submit +				* @var	int		forum_id	When editing: the forum id, +				*							when creating: the parent forum id +				* @var	array	row			Array with current forum data +				*							empty when creating new forum +				* @var	array	forum_data	Array with new forum data +				* @var	string	parents_list	List of parent options +				* @since 3.1.0-a1 +				*/ +				$vars = array('action', 'update', 'forum_id', 'row', 'forum_data', 'parents_list'); +				extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_initialise_data', compact($vars))); +  				$forum_rules_data = array(  					'text'			=> $forum_data['forum_rules'],  					'allow_bbcode'	=> true, @@ -576,7 +619,7 @@ class acp_forums  					$errors[] = $user->lang['FORUM_PASSWORD_OLD'];  				} -				$template->assign_vars(array( +				$template_data = array(  					'S_EDIT_FORUM'		=> true,  					'S_ERROR'			=> (sizeof($errors)) ? true : false,  					'S_PARENT_ID'		=> $this->parent_id, @@ -600,6 +643,8 @@ class acp_forums  					'PRUNE_FREQ'				=> $forum_data['prune_freq'],  					'PRUNE_DAYS'				=> $forum_data['prune_days'],  					'PRUNE_VIEWED'				=> $forum_data['prune_viewed'], +					'PRUNE_SHADOW_FREQ'			=> $forum_data['prune_shadow_freq'], +					'PRUNE_SHADOW_DAYS'			=> $forum_data['prune_shadow_days'],  					'TOPICS_PER_PAGE'			=> $forum_data['forum_topics_per_page'],  					'FORUM_RULES_LINK'			=> $forum_data['forum_rules_link'],  					'FORUM_RULES'				=> $forum_data['forum_rules'], @@ -632,6 +677,7 @@ class acp_forums  					'S_DISPLAY_SUBFORUM_LIST'	=> ($forum_data['display_subforum_list']) ? true : false,  					'S_DISPLAY_ON_INDEX'		=> ($forum_data['display_on_index']) ? true : false,  					'S_PRUNE_ENABLE'			=> ($forum_data['enable_prune']) ? true : false, +					'S_PRUNE_SHADOW_ENABLE'			=> ($forum_data['enable_shadow_prune']) ? true : false,  					'S_FORUM_LINK_TRACK'		=> ($forum_data['forum_flags'] & FORUM_FLAG_LINK_TRACK) ? true : false,  					'S_PRUNE_OLD_POLLS'			=> ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_POLL) ? true : false,  					'S_PRUNE_ANNOUNCE'			=> ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_ANNOUNCE) ? true : false, @@ -641,7 +687,40 @@ class acp_forums  					'S_ENABLE_POST_REVIEW'		=> ($forum_data['forum_flags'] & FORUM_FLAG_POST_REVIEW) ? true : false,  					'S_ENABLE_QUICK_REPLY'		=> ($forum_data['forum_flags'] & FORUM_FLAG_QUICK_REPLY) ? true : false,  					'S_CAN_COPY_PERMISSIONS'	=> ($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))) ? true : false, -				)); +				); + +				/** +				* Modify forum template data before we display the form +				* +				* @event core.acp_manage_forums_display_form +				* @var	string	action		Type of the action: add|edit +				* @var	bool	update		Do we display the form only +				*							or did the user press submit +				* @var	int		forum_id	When editing: the forum id, +				*							when creating: the parent forum id +				* @var	array	row			Array with current forum data +				*							empty when creating new forum +				* @var	array	forum_data	Array with new forum data +				* @var	string	parents_list	List of parent options +				* @var	array	errors		Array of errors, if you add errors +				*					ensure to update the template variables +				*					S_ERROR and ERROR_MSG to display it +				* @var	array	template_data	Array with new forum data +				* @since 3.1.0-a1 +				*/ +				$vars = array( +					'action', +					'update', +					'forum_id', +					'row', +					'forum_data', +					'parents_list', +					'errors', +					'template_data', +				); +				extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_display_form', compact($vars))); + +				$template->assign_vars($template_data);  				return; @@ -706,7 +785,7 @@ class acp_forums  				if (!empty($forum_perm_from) && $forum_perm_from != $forum_id)  				{  					copy_forum_permissions($forum_perm_from, $forum_id, true); -					cache_moderators(); +					phpbb_cache_moderators($db, $cache, $auth);  					$auth->acl_clear_prefetch();  					$cache->destroy('sql', FORUMS_TABLE); @@ -795,8 +874,8 @@ class acp_forums  					'FORUM_IMAGE_SRC'	=> ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '',  					'FORUM_NAME'		=> $row['forum_name'],  					'FORUM_DESCRIPTION'	=> generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield'], $row['forum_desc_options']), -					'FORUM_TOPICS'		=> $row['forum_topics'], -					'FORUM_POSTS'		=> $row['forum_posts'], +					'FORUM_TOPICS'		=> $row['forum_topics_approved'], +					'FORUM_POSTS'		=> $row['forum_posts_approved'],  					'S_FORUM_LINK'		=> ($forum_type == FORUM_LINK) ? true : false,  					'S_FORUM_POST'		=> ($forum_type == FORUM_POST) ? true : false, @@ -866,10 +945,22 @@ class acp_forums  	*/  	function update_forum_data(&$forum_data)  	{ -		global $db, $user, $cache, $phpbb_root_path; +		global $db, $user, $cache, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher;  		$errors = array(); +		/** +		* Validate the forum data before we create/update the forum +		* +		* @event core.acp_manage_forums_validate_data +		* @var	array	forum_data	Array with new forum data +		* @var	array	errors		Array of errors, should be strings and not +		*							language key. +		* @since 3.1.0-a1 +		*/ +		$vars = array('forum_data', 'errors'); +		extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_validate_data', compact($vars))); +  		if ($forum_data['forum_name'] == '')  		{  			$errors[] = $user->lang['FORUM_NAME_EMPTY']; @@ -958,11 +1049,29 @@ class acp_forums  		}  		else  		{ -			$forum_data_sql['forum_password'] = phpbb_hash($forum_data_sql['forum_password']); +			// Instantiate passwords manager +			$passwords_manager = $phpbb_container->get('passwords.manager'); + +			$forum_data_sql['forum_password'] = $passwords_manager->hash($forum_data_sql['forum_password']);  		}  		unset($forum_data_sql['forum_password_unset']); -		if (!isset($forum_data_sql['forum_id'])) +		/** +		* Remove invalid values from forum_data_sql that should not be updated +		* +		* @event core.acp_manage_forums_update_data_before +		* @var	array	forum_data		Array with forum data +		* @var	array	forum_data_sql	Array with data we are going to update +		*						If forum_data_sql[forum_id] is set, we update +		*						that forum, otherwise a new one is created. +		* @since 3.1.0-a1 +		*/ +		$vars = array('forum_data', 'forum_data_sql'); +		extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_update_data_before', compact($vars))); + +		$is_new_forum = !isset($forum_data_sql['forum_id']); + +		if ($is_new_forum)  		{  			// no forum_id means we're creating a new forum  			unset($forum_data_sql['type_action']); @@ -1055,7 +1164,8 @@ class acp_forums  					return array($user->lang['NO_FORUM_ACTION']);  				} -				$forum_data_sql['forum_posts'] = $forum_data_sql['forum_topics'] = $forum_data_sql['forum_topics_real'] = $forum_data_sql['forum_last_post_id'] = $forum_data_sql['forum_last_poster_id'] = $forum_data_sql['forum_last_post_time'] = 0; +				$forum_data_sql['forum_posts_approved'] = $forum_data_sql['forum_posts_unapproved'] = $forum_data_sql['forum_posts_softdeleted'] = $forum_data_sql['forum_topics_approved'] = $forum_data_sql['forum_topics_unapproved'] = $forum_data_sql['forum_topics_softdeleted'] = 0; +				$forum_data_sql['forum_last_post_id'] = $forum_data_sql['forum_last_poster_id'] = $forum_data_sql['forum_last_post_time'] = 0;  				$forum_data_sql['forum_last_poster_name'] = $forum_data_sql['forum_last_poster_colour'] = '';  			}  			else if ($row['forum_type'] == FORUM_CAT && $forum_data_sql['forum_type'] == FORUM_LINK) @@ -1175,9 +1285,12 @@ class acp_forums  			else if ($row['forum_type'] == FORUM_CAT && $forum_data_sql['forum_type'] == FORUM_POST)  			{  				// Changing a category to a forum? Reset the data (you can't post directly in a cat, you must use a forum) -				$forum_data_sql['forum_posts'] = 0; -				$forum_data_sql['forum_topics'] = 0; -				$forum_data_sql['forum_topics_real'] = 0; +				$forum_data_sql['forum_posts_approved'] = 0; +				$forum_data_sql['forum_posts_unapproved'] = 0; +				$forum_data_sql['forum_posts_softdeleted'] = 0; +				$forum_data_sql['forum_topics_approved'] = 0; +				$forum_data_sql['forum_topics_unapproved'] = 0; +				$forum_data_sql['forum_topics_softdeleted'] = 0;  				$forum_data_sql['forum_last_post_id'] = 0;  				$forum_data_sql['forum_last_post_subject'] = '';  				$forum_data_sql['forum_last_post_time'] = 0; @@ -1233,6 +1346,22 @@ class acp_forums  			add_log('admin', 'LOG_FORUM_EDIT', $forum_data['forum_name']);  		} +		/** +		* Event after a forum was updated or created +		* +		* @event core.acp_manage_forums_update_data_after +		* @var	array	forum_data		Array with forum data +		* @var	array	forum_data_sql	Array with data we updated +		* @var	bool	is_new_forum	Did we create a forum or update one +		*								If you want to overwrite this value, +		*								ensure to set forum_data_sql[forum_id] +		* @var	array	errors		Array of errors, should be strings and not +		*							language key. +		* @since 3.1.0-a1 +		*/ +		$vars = array('forum_data', 'forum_data_sql', 'is_new_forum', 'errors'); +		extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_update_data_after', compact($vars))); +  		return $errors;  	} @@ -1241,7 +1370,7 @@ class acp_forums  	*/  	function move_forum($from_id, $to_id)  	{ -		global $db, $user; +		global $db, $user, $phpbb_dispatcher;  		$to_data = $moved_ids = $errors = array(); @@ -1253,10 +1382,30 @@ class acp_forums  			if ($to_data['forum_type'] == FORUM_LINK)  			{  				$errors[] = $user->lang['PARENT_IS_LINK_FORUM']; -				return $errors;  			}  		} +		/** +		* Event when we move all children of one forum to another +		* +		* This event may be triggered, when a forum is deleted +		* +		* @event core.acp_manage_forums_move_children +		* @var	int		from_id		If of the current parent forum +		* @var	int		to_id		If of the new parent forum +		* @var	array	errors		Array of errors, should be strings and not +		*							language key. +		* @since 3.1.0-a1 +		*/ +		$vars = array('from_id', 'to_id', 'errors'); +		extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_move_children', compact($vars))); + +		// Return if there were errors +		if (!empty($errors)) +		{ +			return $errors; +		} +  		$moved_forums = get_forum_branch($from_id, 'children', 'descending');  		$from_data = $moved_forums[0];  		$diff = sizeof($moved_forums) * 2; @@ -1336,7 +1485,30 @@ class acp_forums  	*/  	function move_forum_content($from_id, $to_id, $sync = true)  	{ -		global $db; +		global $db, $phpbb_dispatcher; + +		$errors = array(); + +		/** +		* Event when we move content from one forum to another +		* +		* @event core.acp_manage_forums_move_content +		* @var	int		from_id		If of the current parent forum +		* @var	int		to_id		If of the new parent forum +		* @var	bool	sync		Shall we sync the "to"-forum's data +		* @var	array	errors		Array of errors, should be strings and not +		*							language key. If this array is not empty, +		*							The content will not be moved. +		* @since 3.1.0-a1 +		*/ +		$vars = array('from_id', 'to_id', 'sync', 'errors'); +		extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_move_content', compact($vars))); + +		// Return if there were errors +		if (!empty($errors)) +		{ +			return $errors; +		}  		$table_ary = array(LOG_TABLE, POSTS_TABLE, TOPICS_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE); @@ -1645,7 +1817,7 @@ class acp_forums  			FROM ' . POSTS_TABLE . '  			WHERE forum_id = ' . $forum_id . '  				AND post_postcount = 1 -				AND post_approved = 1'; +				AND post_visibility = ' . ITEM_APPROVED;  		$result = $db->sql_query($sql);  		$post_counts = array(); @@ -1655,7 +1827,7 @@ class acp_forums  		}  		$db->sql_freeresult($result); -		switch ($db->sql_layer) +		switch ($db->get_sql_layer())  		{  			case 'mysql4':  			case 'mysqli': @@ -1783,7 +1955,7 @@ class acp_forums  		// Make sure the overall post/topic count is correct...  		$sql = 'SELECT COUNT(post_id) AS stat  			FROM ' . POSTS_TABLE . ' -			WHERE post_approved = 1'; +			WHERE post_visibility = ' . ITEM_APPROVED;  		$result = $db->sql_query($sql);  		$row = $db->sql_fetchrow($result);  		$db->sql_freeresult($result); @@ -1792,7 +1964,7 @@ class acp_forums  		$sql = 'SELECT COUNT(topic_id) AS stat  			FROM ' . TOPICS_TABLE . ' -			WHERE topic_approved = 1'; +			WHERE topic_visibility = ' . ITEM_APPROVED;  		$result = $db->sql_query($sql);  		$row = $db->sql_fetchrow($result);  		$db->sql_freeresult($result); @@ -1945,5 +2117,3 @@ class acp_forums  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php index c9d476b8ae..edfada1bf1 100644 --- a/phpBB/includes/acp/acp_groups.php +++ b/phpBB/includes/acp/acp_groups.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_groups  {  	var $u_action; @@ -27,6 +27,7 @@ class acp_groups  	{  		global $config, $db, $user, $auth, $template, $cache;  		global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $file_uploads; +		global $request, $phpbb_container, $phpbb_dispatcher;  		$user->add_lang('acp/groups');  		$this->tpl_name = 'acp_groups'; @@ -35,6 +36,12 @@ class acp_groups  		$form_key = 'acp_groups';  		add_form_key($form_key); +		if ($mode == 'position') +		{ +			$this->manage_position(); +			return; +		} +  		include($phpbb_root_path . 'includes/functions_user.' . $phpEx);  		// Check and set some common vars @@ -47,17 +54,17 @@ class acp_groups  		$start		= request_var('start', 0);  		$update		= (isset($_POST['update'])) ? true : false; -  		// Clear some vars -		$can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && phpbb_is_writable($phpbb_root_path . $config['avatar_path']) && $file_uploads) ? true : false;  		$group_row = array();  		// Grab basic data for group, if group_id is set and exists  		if ($group_id)  		{ -			$sql = 'SELECT * -				FROM ' . GROUPS_TABLE . " -				WHERE group_id = $group_id"; +			$sql = 'SELECT g.*, t.teampage_position AS group_teampage +				FROM ' . GROUPS_TABLE . ' g +				LEFT JOIN ' . TEAMPAGE_TABLE . ' t +					ON (t.group_id = g.group_id) +				WHERE g.group_id = ' . $group_id;  			$result = $db->sql_query($sql);  			$group_row = $db->sql_fetchrow($result);  			$db->sql_freeresult($result); @@ -133,7 +140,7 @@ class acp_groups  				if (confirm_box(true))  				{  					$group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; -					group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row);	 +					group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row);  					trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&action=list&g=' . $group_id));  				}  				else @@ -305,8 +312,46 @@ class acp_groups  				$error = array();  				$user->add_lang('ucp'); -				$avatar_select = basename(request_var('avatar_select', '')); -				$category = basename(request_var('category', '')); +				// Setup avatar data for later +				$avatars_enabled = false; +				$avatar_drivers = null; +				$avatar_data = null; +				$avatar_error = array(); + +				if ($config['allow_avatar']) +				{ +					$phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); +					$avatar_drivers = $phpbb_avatar_manager->get_enabled_drivers(); + +					// This is normalised data, without the group_ prefix +					$avatar_data = \phpbb\avatar\manager::clean_row($group_row, 'group'); +					if (!isset($avatar_data['id'])) +					{ +						$avatar_data['id'] = 'g' . $group_id; +					} +				} + +				if ($request->is_set_post('avatar_delete')) +				{ +					if (confirm_box(true)) +					{ +						$avatar_data['id'] = substr($avatar_data['id'], 1); +						$phpbb_avatar_manager->handle_avatar_delete($db, $user, $avatar_data, GROUPS_TABLE, 'group_'); + +						$message = ($action == 'edit') ? 'GROUP_UPDATED' : 'GROUP_CREATED'; +						trigger_error($user->lang[$message] . adm_back_link($this->u_action)); +					} +					else +					{ +						confirm_box(false, $user->lang('CONFIRM_AVATAR_DELETE'), build_hidden_fields(array( +								'avatar_delete'     => true, +								'i'                 => $id, +								'mode'              => $mode, +								'g'			        => $group_id, +								'action'            => $action)) +						); +					} +				}  				// Did we submit?  				if ($update) @@ -324,17 +369,12 @@ class acp_groups  					$allow_desc_urls	= request_var('desc_parse_urls', false);  					$allow_desc_smilies	= request_var('desc_parse_smilies', false); -					$data['uploadurl']	= request_var('uploadurl', ''); -					$data['remotelink']	= request_var('remotelink', ''); -					$data['width']		= request_var('width', ''); -					$data['height']		= request_var('height', ''); -					$delete				= request_var('delete', ''); -  					$submit_ary = array(  						'colour'			=> request_var('group_colour', ''),  						'rank'				=> request_var('group_rank', 0),  						'receive_pm'		=> isset($_REQUEST['group_receive_pm']) ? 1 : 0,  						'legend'			=> isset($_REQUEST['group_legend']) ? 1 : 0, +						'teampage'			=> isset($_REQUEST['group_teampage']) ? 1 : 0,  						'message_limit'		=> request_var('group_message_limit', 0),  						'max_recipients'	=> request_var('group_max_recipients', 0),  						'founder_manage'	=> 0, @@ -346,81 +386,39 @@ class acp_groups  						$submit_ary['founder_manage'] = isset($_REQUEST['group_founder_manage']) ? 1 : 0;  					} -					if (!empty($_FILES['uploadfile']['tmp_name']) || $data['uploadurl'] || $data['remotelink']) +					if ($config['allow_avatar'])  					{ -						// Avatar stuff -						$var_ary = array( -							'uploadurl'		=> array('string', true, 5, 255), -							'remotelink'	=> array('string', true, 5, 255), -							'width'			=> array('string', true, 1, 3), -							'height'		=> array('string', true, 1, 3), -						); - -						if (!($error = validate_data($data, $var_ary))) -						{ -							$data['user_id'] = "g$group_id"; +						// Handle avatar +						$driver_name = $phpbb_avatar_manager->clean_driver_name($request->variable('avatar_driver', '')); -							if ((!empty($_FILES['uploadfile']['tmp_name']) || $data['uploadurl']) && $can_upload) -							{ -								list($submit_ary['avatar_type'], $submit_ary['avatar'], $submit_ary['avatar_width'], $submit_ary['avatar_height']) = avatar_upload($data, $error); -							} -							else if ($data['remotelink']) -							{ -								list($submit_ary['avatar_type'], $submit_ary['avatar'], $submit_ary['avatar_width'], $submit_ary['avatar_height']) = avatar_remote($data, $error); -							} -						} -					} -					else if ($avatar_select && $config['allow_avatar_local']) -					{ -						// check avatar gallery -						if (is_dir($phpbb_root_path . $config['avatar_gallery_path'] . '/' . $category)) +						if (in_array($driver_name, $avatar_drivers) && !$request->is_set_post('avatar_delete'))  						{ -							$submit_ary['avatar_type'] = AVATAR_GALLERY; +							$driver = $phpbb_avatar_manager->get_driver($driver_name); +							$result = $driver->process_form($request, $template, $user, $avatar_data, $avatar_error); -							list($submit_ary['avatar_width'], $submit_ary['avatar_height']) = getimagesize($phpbb_root_path . $config['avatar_gallery_path'] . '/' . $category . '/' . $avatar_select); -							$submit_ary['avatar'] = $category . '/' . $avatar_select; -						} -					} -					else if ($delete) -					{ -						$submit_ary['avatar'] = ''; -						$submit_ary['avatar_type'] = $submit_ary['avatar_width'] = $submit_ary['avatar_height'] = 0; -					} -					else if ($data['width'] && $data['height']) -					{ -						// Only update the dimensions? -						if ($config['avatar_max_width'] || $config['avatar_max_height']) -						{ -							if ($data['width'] > $config['avatar_max_width'] || $data['height'] > $config['avatar_max_height']) +							if ($result && empty($avatar_error))  							{ -								$error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); +								$result['avatar_type'] = $driver_name; +								$submit_ary = array_merge($submit_ary, $result);  							}  						} - -						if (!sizeof($error)) +						else  						{ -							if ($config['avatar_min_width'] || $config['avatar_min_height']) +							$driver = $phpbb_avatar_manager->get_driver($avatar_data['avatar_type']); +							if ($driver)  							{ -								if ($data['width'] < $config['avatar_min_width'] || $data['height'] < $config['avatar_min_height']) -								{ -									$error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); -								} +								$driver->delete($avatar_data);  							} -						} -						if (!sizeof($error)) -						{ -							$submit_ary['avatar_width'] = $data['width']; -							$submit_ary['avatar_height'] = $data['height']; +							// Removing the avatar +							$submit_ary['avatar_type'] = ''; +							$submit_ary['avatar'] = ''; +							$submit_ary['avatar_width'] = 0; +							$submit_ary['avatar_height'] = 0;  						} -					} -					if ((isset($submit_ary['avatar']) && $submit_ary['avatar'] && (!isset($group_row['group_avatar']))) || $delete) -					{ -						if (isset($group_row['group_avatar']) && $group_row['group_avatar']) -						{ -							avatar_delete('group', $group_row, true); -						} +						// Merge any avatar errors into the primary error array +						$error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error));  					}  					/* @@ -434,6 +432,42 @@ class acp_groups  						'colour'	=> array('hex_colour', true),  					); +					/** +					* Request group data and operate on it +					* +					* @event core.acp_manage_group_request_data +					* @var	string	action				Type of the action: add|edit +					* @var	int		group_id			The group id +					* @var	array	group_row			Array with new group data +					* @var	array	error				Array of errors, if you add errors +					*							ensure to update the template variables +					*							S_ERROR and ERROR_MSG to display it +					* @var	string	group_name			The group name +					* @var	string	group_desc			The group description +					* @var	int		group_type			The group type +					* @var	bool	allow_desc_bbcode	Allow bbcode in group description: true|false +					* @var	bool	allow_desc_urls		Allow urls in group description: true|false +					* @var	bool	allow_desc_smilies	Allow smiles in group description: true|false +					* @var	array	submit_ary			Array with new group data +					* @var	array	validation_checks	Array with validation data +					* @since 3.1.0-b5 +					*/ +					$vars = array( +						'action', +						'group_id', +						'group_row', +						'error', +						'group_name', +						'group_desc', +						'group_type', +						'allow_desc_bbcode', +						'allow_desc_urls', +						'allow_desc_smilies', +						'submit_ary', +						'validation_checks', +					); +					extract($phpbb_dispatcher->trigger_event('core.acp_manage_group_request_data', compact($vars))); +  					if ($validation_error = validate_data($submit_ary, $validation_checks))  					{  						// Replace "error" string with its real, localised form @@ -445,26 +479,66 @@ class acp_groups  						// Only set the rank, colour, etc. if it's changed or if we're adding a new  						// group. This prevents existing group members being updated if no changes  						// were made. +						// However there are some attributes that need to be set everytime, +						// otherwise the group gets removed from the feature. +						$set_attributes = array('legend', 'teampage');  						$group_attributes = array();  						$test_variables = array(  							'rank'			=> 'int',  							'colour'		=> 'string',  							'avatar'		=> 'string', -							'avatar_type'	=> 'int', +							'avatar_type'	=> 'string',  							'avatar_width'	=> 'int',  							'avatar_height'	=> 'int',  							'receive_pm'	=> 'int',  							'legend'		=> 'int', +							'teampage'		=> 'int',  							'message_limit'	=> 'int',  							'max_recipients'=> 'int',  							'founder_manage'=> 'int',  							'skip_auth'		=> 'int',  						); +						/** +						* Initialise data before we display the add/edit form +						* +						* @event core.acp_manage_group_initialise_data +						* @var	string	action				Type of the action: add|edit +						* @var	int		group_id			The group id +						* @var	array	group_row			Array with new group data +						* @var	array	error				Array of errors, if you add errors +						*							ensure to update the template variables +						*							S_ERROR and ERROR_MSG to display it +						* @var	string	group_name			The group name +						* @var	string	group_desc			The group description +						* @var	int		group_type			The group type +						* @var	bool	allow_desc_bbcode	Allow bbcode in group description: true|false +						* @var	bool	allow_desc_urls		Allow urls in group description: true|false +						* @var	bool	allow_desc_smilies	Allow smiles in group description: true|false +						* @var	array	submit_ary			Array with new group data +						* @var	array	test_variables		Array with variables for test +						* @since 3.1.0-b5 +						*/ +						$vars = array( +							'action', +							'group_id', +							'group_row', +							'error', +							'group_name', +							'group_desc', +							'group_type', +							'allow_desc_bbcode', +							'allow_desc_urls', +							'allow_desc_smilies', +							'submit_ary', +							'test_variables', +						); +						extract($phpbb_dispatcher->trigger_event('core.acp_manage_group_initialise_data', compact($vars))); +  						foreach ($test_variables as $test => $type)  						{ -							if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test])) +							if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test] || isset($group_attributes['group_avatar']) && strpos($test, 'avatar') === 0 || in_array($test, $set_attributes)))  							{  								settype($submit_ary[$test], $type);  								$group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test]; @@ -521,7 +595,7 @@ class acp_groups  								}  							} -							$cache->destroy('sql', GROUPS_TABLE); +							$cache->destroy('sql', array(GROUPS_TABLE, TEAMPAGE_TABLE));  							$message = ($action == 'edit') ? 'GROUP_UPDATED' : 'GROUP_CREATED';  							trigger_error($user->lang[$message] . adm_back_link($this->u_action)); @@ -581,13 +655,44 @@ class acp_groups  				$type_closed	= ($group_type == GROUP_CLOSED) ? ' checked="checked"' : '';  				$type_hidden	= ($group_type == GROUP_HIDDEN) ? ' checked="checked"' : ''; -				$avatar_img = (!empty($group_row['group_avatar'])) ? get_user_avatar($group_row['group_avatar'], $group_row['group_avatar_type'], $group_row['group_avatar_width'], $group_row['group_avatar_height'], 'GROUP_AVATAR') : '<img src="' . $phpbb_admin_path . 'images/no_avatar.gif" alt="" />'; +				// Load up stuff for avatars +				if ($config['allow_avatar']) +				{ +					$avatars_enabled = false; +					$selected_driver = $phpbb_avatar_manager->clean_driver_name($request->variable('avatar_driver', $avatar_data['avatar_type'])); + +					foreach ($avatar_drivers as $current_driver) +					{ +						$driver = $phpbb_avatar_manager->get_driver($current_driver); -				$display_gallery = (isset($_POST['display_gallery'])) ? true : false; +						$avatars_enabled = true; +						$config_name = $phpbb_avatar_manager->get_driver_config_name($driver); +						$template->set_filenames(array( +							'avatar' => "acp_avatar_options_{$config_name}.html", +						)); -				if ($config['allow_avatar_local'] && $display_gallery) +						if ($driver->prepare_form($request, $template, $user, $avatar_data, $avatar_error)) +						{ +							$driver_name = $phpbb_avatar_manager->prepare_driver_name($current_driver); +							$driver_upper = strtoupper($driver_name); +							$template->assign_block_vars('avatar_drivers', array( +								'L_TITLE' => $user->lang($driver_upper . '_TITLE'), +								'L_EXPLAIN' => $user->lang($driver_upper . '_EXPLAIN'), + +								'DRIVER' => $driver_name, +								'SELECTED' => $current_driver == $selected_driver, +								'OUTPUT' => $template->assign_display('avatar'), +							)); +						} +					} +				} + +				$avatar = phpbb_get_group_avatar($group_row, 'GROUP_AVATAR', true); + +				if (isset($phpbb_avatar_manager) && !$update)  				{ -					avatar_gallery($category, $avatar_select, 4); +					// Merge any avatar errors into the primary error array +					$error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error));  				}  				$back_link = request_var('back_link', ''); @@ -608,12 +713,10 @@ class acp_groups  					'S_ADD_GROUP'		=> ($action == 'add') ? true : false,  					'S_GROUP_PERM'		=> ($action == 'add' && $auth->acl_get('a_authgroups') && $auth->acl_gets('a_aauth', 'a_fauth', 'a_mauth', 'a_uauth')) ? true : false,  					'S_INCLUDE_SWATCH'	=> true, -					'S_CAN_UPLOAD'		=> $can_upload,  					'S_ERROR'			=> (sizeof($error)) ? true : false,  					'S_SPECIAL_GROUP'	=> ($group_type == GROUP_SPECIAL) ? true : false, -					'S_DISPLAY_GALLERY'	=> ($config['allow_avatar_local'] && !$display_gallery) ? true : false, -					'S_IN_GALLERY'		=> ($config['allow_avatar_local'] && $display_gallery) ? true : false,  					'S_USER_FOUNDER'	=> ($user->data['user_type'] == USER_FOUNDER) ? true : false, +					'S_AVATARS_ENABLED'		=> ($config['allow_avatar'] && $avatars_enabled),  					'ERROR_MSG'				=> (sizeof($error)) ? implode('<br />', $error) : '',  					'GROUP_NAME'			=> ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_name] : $group_name, @@ -622,6 +725,7 @@ class acp_groups  					'GROUP_RECEIVE_PM'		=> (isset($group_row['group_receive_pm']) && $group_row['group_receive_pm']) ? ' checked="checked"' : '',  					'GROUP_FOUNDER_MANAGE'	=> (isset($group_row['group_founder_manage']) && $group_row['group_founder_manage']) ? ' checked="checked"' : '',  					'GROUP_LEGEND'			=> (isset($group_row['group_legend']) && $group_row['group_legend']) ? ' checked="checked"' : '', +					'GROUP_TEAMPAGE'		=> (isset($group_row['group_teampage']) && $group_row['group_teampage']) ? ' checked="checked"' : '',  					'GROUP_MESSAGE_LIMIT'	=> (isset($group_row['group_message_limit'])) ? $group_row['group_message_limit'] : 0,  					'GROUP_MAX_RECIPIENTS'	=> (isset($group_row['group_max_recipients'])) ? $group_row['group_max_recipients'] : 0,  					'GROUP_COLOUR'			=> (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '', @@ -633,8 +737,7 @@ class acp_groups  					'S_RANK_OPTIONS'		=> $rank_options,  					'S_GROUP_OPTIONS'		=> group_select_options(false, false, (($user->data['user_type'] == USER_FOUNDER) ? false : 0)), -					'AVATAR'				=> $avatar_img, -					'AVATAR_IMAGE'			=> $avatar_img, +					'AVATAR'				=> empty($avatar) ? '<img src="' . $phpbb_admin_path . 'images/no_avatar.gif" alt="" />' : $avatar,  					'AVATAR_MAX_FILESIZE'	=> $config['avatar_filesize'],  					'AVATAR_WIDTH'			=> (isset($group_row['group_avatar_width'])) ? $group_row['group_avatar_width'] : '',  					'AVATAR_HEIGHT'			=> (isset($group_row['group_avatar_height'])) ? $group_row['group_avatar_height'] : '', @@ -651,11 +754,43 @@ class acp_groups  					'GROUP_HIDDEN'		=> $type_hidden,  					'U_BACK'			=> $u_back, -					'U_SWATCH'			=> append_sid("{$phpbb_admin_path}swatch.$phpEx", 'form=settings&name=group_colour'),  					'U_ACTION'			=> "{$this->u_action}&action=$action&g=$group_id", -					'L_AVATAR_EXPLAIN'	=> sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], round($config['avatar_filesize'] / 1024)), +					'L_AVATAR_EXPLAIN'	=> phpbb_avatar_explanation_string(),  				)); +				/** +				* Modify group template data before we display the form +				* +				* @event core.acp_manage_group_display_form +				* @var	string	action				Type of the action: add|edit +				* @var	bool	update				Do we display the form only +				*							or did the user press submit +				* @var	int		group_id			The group id +				* @var	array	group_row			Array with new group data +				* @var	string	group_name			The group name +				* @var	int		group_type			The group type +				* @var	array	group_desc_data		The group description data +				* @var	string	group_rank			The group rank +				* @var	string	rank_options		The rank options +				* @var	array	error				Array of errors, if you add errors +				*							ensure to update the template variables +				*							S_ERROR and ERROR_MSG to display it +				* @since 3.1.0-b5 +				*/ +				$vars = array( +					'action', +					'update', +					'group_id', +					'group_row', +					'group_desc_data', +					'group_name', +					'group_type', +					'group_rank', +					'rank_options', +					'error', +				); +				extract($phpbb_dispatcher->trigger_event('core.acp_manage_group_display_form', compact($vars))); +  				return;  			break; @@ -667,6 +802,7 @@ class acp_groups  				}  				$this->page_title = 'GROUP_MEMBERS'; +				$pagination = $phpbb_container->get('pagination');  				// Grab the leaders - always, on every page...  				$sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_colour, u.user_posts, u.group_id, ug.group_leader, ug.user_pending @@ -709,13 +845,14 @@ class acp_groups  					$s_action_options .= '<option value="' . $option . '">' . $user->lang['GROUP_' . $lang] . '</option>';  				} +				$base_url = $this->u_action . "&action=$action&g=$group_id"; +				$pagination->generate_template_pagination($base_url, 'pagination', 'start', $total_members, $config['topics_per_page'], $start); +  				$template->assign_vars(array(  					'S_LIST'			=> true,  					'S_GROUP_SPECIAL'	=> ($group_row['group_type'] == GROUP_SPECIAL) ? true : false,  					'S_ACTION_OPTIONS'	=> $s_action_options, -					'S_ON_PAGE'		=> on_page($total_members, $config['topics_per_page'], $start), -					'PAGINATION'	=> generate_pagination($this->u_action . "&action=$action&g=$group_id", $total_members, $config['topics_per_page'], $start, true),  					'GROUP_NAME'	=> ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'],  					'U_ACTION'			=> $this->u_action . "&g=$group_id", @@ -831,6 +968,222 @@ class acp_groups  			}  		}  	} -} -?> +	public function manage_position() +	{ +		global $config, $db, $template, $user, $request, $phpbb_container; + +		$this->tpl_name = 'acp_groups_position'; +		$this->page_title = 'ACP_GROUPS_POSITION'; + +		$field = $request->variable('field', ''); +		$action = $request->variable('action', ''); +		$group_id = $request->variable('g', 0); +		$teampage_id = $request->variable('t', 0); +		$category_id = $request->variable('c', 0); + +		if ($field && !in_array($field, array('legend', 'teampage'))) +		{ +			// Invalid mode +			trigger_error($user->lang['NO_MODE'] . adm_back_link($this->u_action), E_USER_WARNING); +		} +		else if ($field && in_array($field, array('legend', 'teampage'))) +		{ + +			$group_position = $phpbb_container->get('groupposition.' . $field); +		} + +		if ($field == 'teampage') +		{ +			try +			{ +				switch ($action) +				{ +					case 'add': +						$group_position->add_group_teampage($group_id, $category_id); +					break; + +					case 'add_category': +						$group_position->add_category_teampage($request->variable('category_name', '', true)); +					break; + +					case 'delete': +						$group_position->delete_teampage($teampage_id); +					break; + +					case 'move_up': +						$group_position->move_up_teampage($teampage_id); +					break; + +					case 'move_down': +						$group_position->move_down_teampage($teampage_id); +					break; +				} +			} +			catch (\phpbb\groupposition\exception $exception) +			{ +				trigger_error($user->lang($exception->getMessage()) . adm_back_link($this->u_action), E_USER_WARNING); +			} +		} +		else if ($field == 'legend') +		{ +			try +			{ +				switch ($action) +				{ +					case 'add': +						$group_position->add_group($group_id); +					break; + +					case 'delete': +						$group_position->delete_group($group_id); +					break; + +					case 'move_up': +						$group_position->move_up($group_id); +					break; + +					case 'move_down': +						$group_position->move_down($group_id); +					break; +				} +			} +			catch (\phpbb\groupposition\exception $exception) +			{ +				trigger_error($user->lang($exception->getMessage()) . adm_back_link($this->u_action), E_USER_WARNING); +			} +		} +		else +		{ +			switch ($action) +			{ +				case 'set_config_teampage': +					$config->set('teampage_forums', $request->variable('teampage_forums', 0)); +					$config->set('teampage_memberships', $request->variable('teampage_memberships', 0)); +					trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); +				break; + +				case 'set_config_legend': +					$config->set('legend_sort_groupname', $request->variable('legend_sort_groupname', 0)); +					trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); +				break; +			} +		} + +		if (($action == 'move_up' || $action == 'move_down') && $request->is_ajax()) +		{ +			$json_response = new \phpbb\json_response; +			$json_response->send(array('success' => true)); +		} + +		$sql = 'SELECT group_id, group_name, group_colour, group_type, group_legend +			FROM ' . GROUPS_TABLE . ' +			ORDER BY group_legend ASC, group_type DESC, group_name ASC'; +		$result = $db->sql_query($sql); + +		$s_group_select_legend = ''; +		while ($row = $db->sql_fetchrow($result)) +		{ +			$group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; +			if ($row['group_legend']) +			{ +				$template->assign_block_vars('legend', array( +					'GROUP_NAME'	=> $group_name, +					'GROUP_COLOUR'	=> ($row['group_colour']) ? '#' . $row['group_colour'] : '', +					'GROUP_TYPE'	=> $user->lang[\phpbb\groupposition\legend::group_type_language($row['group_type'])], + +					'U_MOVE_DOWN'	=> "{$this->u_action}&field=legend&action=move_down&g=" . $row['group_id'], +					'U_MOVE_UP'		=> "{$this->u_action}&field=legend&action=move_up&g=" . $row['group_id'], +					'U_DELETE'		=> "{$this->u_action}&field=legend&action=delete&g=" . $row['group_id'], +				)); +			} +			else +			{ +				$template->assign_block_vars('add_legend', array( +					'GROUP_ID'		=> (int) $row['group_id'], +					'GROUP_NAME'	=> $group_name, +					'GROUP_SPECIAL'	=> ($row['group_type'] == GROUP_SPECIAL), +				)); +			} +		} +		$db->sql_freeresult($result); + +		$category_url_param = (($category_id) ? '&c=' . $category_id : ''); + +		$sql = 'SELECT t.*, g.group_name, g.group_colour, g.group_type +			FROM ' . TEAMPAGE_TABLE . ' t +			LEFT JOIN ' . GROUPS_TABLE . ' g +				ON (t.group_id = g.group_id) +			WHERE t.teampage_parent = ' . $category_id . ' +				OR t.teampage_id = ' . $category_id . ' +			ORDER BY t.teampage_position ASC'; +		$result = $db->sql_query($sql); + +		$category_data = array(); +		while ($row = $db->sql_fetchrow($result)) +		{ +			if ($row['teampage_id'] == $category_id) +			{ +				$template->assign_vars(array( +					'CURRENT_CATEGORY_NAME'		=> $row['teampage_name'], +				)); +				continue; +			} + +			if ($row['group_id']) +			{ +				$group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; +				$group_type = $user->lang[\phpbb\groupposition\teampage::group_type_language($row['group_type'])]; +			} +			else +			{ +				$group_name = $row['teampage_name']; +				$group_type = ''; +			} + +			$template->assign_block_vars('teampage', array( +				'GROUP_NAME'	=> $group_name, +				'GROUP_COLOUR'	=> ($row['group_colour']) ? '#' . $row['group_colour'] : '', +				'GROUP_TYPE'	=> $group_type, + +				'U_CATEGORY'	=> (!$row['group_id']) ? "{$this->u_action}&c=" . $row['teampage_id'] : '', +				'U_MOVE_DOWN'	=> "{$this->u_action}&field=teampage&action=move_down{$category_url_param}&t=" . $row['teampage_id'], +				'U_MOVE_UP'		=> "{$this->u_action}&field=teampage&action=move_up{$category_url_param}&t=" . $row['teampage_id'], +				'U_DELETE'		=> "{$this->u_action}&field=teampage&action=delete{$category_url_param}&t=" . $row['teampage_id'], +			)); +		} +		$db->sql_freeresult($result); + +		$sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_type +			FROM ' . GROUPS_TABLE . ' g +			LEFT JOIN ' . TEAMPAGE_TABLE . ' t +				ON (t.group_id = g.group_id) +			WHERE t.teampage_id IS NULL +			ORDER BY g.group_type DESC, g.group_name ASC'; +		$result = $db->sql_query($sql); + +		$s_group_select_teampage = ''; +		while ($row = $db->sql_fetchrow($result)) +		{ +			$group_name = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; +			$template->assign_block_vars('add_teampage', array( +				'GROUP_ID'		=> (int) $row['group_id'], +				'GROUP_NAME'	=> $group_name, +				'GROUP_SPECIAL'	=> ($row['group_type'] == GROUP_SPECIAL), +			)); +		} +		$db->sql_freeresult($result); + +		$template->assign_vars(array( +			'U_ACTION'					=> $this->u_action, +			'U_ACTION_LEGEND'			=> $this->u_action . '&field=legend', +			'U_ACTION_TEAMPAGE'			=> $this->u_action . '&field=teampage' . $category_url_param, +			'U_ACTION_TEAMPAGE_CAT'		=> $this->u_action . '&field=teampage_cat', + +			'S_TEAMPAGE_CATEGORY'		=> $category_id, +			'DISPLAY_FORUMS'			=> ($config['teampage_forums']) ? true : false, +			'DISPLAY_MEMBERSHIPS'		=> $config['teampage_memberships'], +			'LEGEND_SORT_GROUPNAME'		=> ($config['legend_sort_groupname']) ? true : false, +		)); +	} +} diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index 24f6cbbcbf..9265415dd1 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -18,7 +21,6 @@ if (!defined('IN_PHPBB'))  /**  * @todo [smilies] check regular expressions for special char replacements (stored specialchared in db) -* @package acp  */  class acp_icons  { @@ -28,6 +30,7 @@ class acp_icons  	{  		global $db, $user, $auth, $template, $cache;  		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; +		global $request, $phpbb_container;  		$user->add_lang('acp/posting'); @@ -203,7 +206,6 @@ class acp_icons  						unset($_images[$row[$fields . '_url']]);  					} -  					if ($row[$fields . '_id'] == $icon_id)  					{  						$after = true; @@ -307,7 +309,6 @@ class acp_icons  						'IMG_SRC'			=> $phpbb_root_path . $img_path . '/' . $default_row['smiley_url'],  						'IMG_PATH'			=> $img_path, -						'PHPBB_ROOT_PATH'	=> $phpbb_root_path,  						'CODE'				=> $default_row['code'],  						'EMOTION'			=> $default_row['emotion'], @@ -338,7 +339,7 @@ class acp_icons  				$image_display_on_posting = (isset($_POST['display_on_posting'])) ? request_var('display_on_posting', array('' => 0)) : array();  				// Ok, add the relevant bits if we are adding new codes to existing emoticons... -				if (!empty($_POST['add_additional_code'])) +				if ($request->variable('add_additional_code', false, false, \phpbb\request\request_interface::POST))  				{  					$add_image			= request_var('add_image', '');  					$add_code			= utf8_normalize_nfc(request_var('add_code', '', true)); @@ -354,7 +355,7 @@ class acp_icons  						$image_width[$add_image] = request_var('add_width', 0);  						$image_height[$add_image] = request_var('add_height', 0); -						if (!empty($_POST['add_display_on_posting'])) +						if ($request->variable('add_display_on_posting', false, false, \phpbb\request\request_interface::POST))  						{  							$image_display_on_posting[$add_image] = 1;  						} @@ -378,7 +379,7 @@ class acp_icons  					if ($smiley_count + $addable_smileys_count > SMILEY_LIMIT)  					{ -						trigger_error(sprintf($user->lang['TOO_MANY_SMILIES'], SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING); +						trigger_error($user->lang('TOO_MANY_SMILIES', SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING);  					}  				} @@ -480,27 +481,13 @@ class acp_icons  							$icons_updated++;  						} - 					} +					}  				}  				$cache->destroy('_icons');  				$cache->destroy('sql', $table); -				$level = E_USER_NOTICE; -				switch ($icons_updated) -				{ -					case 0: -						$suc_lang = "{$lang}_NONE"; -						$level = E_USER_WARNING; -						break; - -					case 1: -						$suc_lang = "{$lang}_ONE"; -						break; - -					default: -						$suc_lang = $lang; -				} +				$level = ($icons_updated) ? E_USER_NOTICE : E_USER_WARNING;  				$errormsgs = '';  				foreach ($errors as $img => $error)  				{ @@ -508,11 +495,11 @@ class acp_icons  				}  				if ($action == 'modify')  				{ -					trigger_error($user->lang[$suc_lang . '_EDITED'] . $errormsgs . adm_back_link($this->u_action), $level); +					trigger_error($user->lang($lang . '_EDITED', $icons_updated) . $errormsgs . adm_back_link($this->u_action), $level);  				}  				else  				{ -					trigger_error($user->lang[$suc_lang . '_ADDED'] . $errormsgs . adm_back_link($this->u_action), $level); +					trigger_error($user->lang($lang . '_ADDED', $icons_updated) . $errormsgs . adm_back_link($this->u_action), $level);  				}  			break; @@ -551,10 +538,10 @@ class acp_icons  					// The user has already selected a smilies_pak file  					if ($current == 'delete')  					{ -						switch ($db->sql_layer) +						switch ($db->get_sql_layer())  						{  							case 'sqlite': -							case 'firebird': +							case 'sqlite3':  								$db->sql_query('DELETE FROM ' . $table);  							break; @@ -598,7 +585,7 @@ class acp_icons  						$smiley_count = $this->item_count($table);  						if ($smiley_count + sizeof($pak_ary) > SMILEY_LIMIT)  						{ -							trigger_error(sprintf($user->lang['TOO_MANY_SMILIES'], SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING); +							trigger_error($user->lang('TOO_MANY_SMILIES', SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING);  						}  					} @@ -750,7 +737,7 @@ class acp_icons  				{  					garbage_collection(); -					header('Pragma: public'); +					header('Cache-Control: public');  					// Send out the Headers  					header('Content-Type: text/x-delimtext; name="' . $mode . '.pak"'); @@ -796,6 +783,18 @@ class acp_icons  					$cache->destroy('_icons');  					$cache->destroy('sql', $table); + +					if ($request->is_ajax()) +					{ +						$json_response = new \phpbb\json_response; +						$json_response->send(array( +							'MESSAGE_TITLE'	=> $user->lang['INFORMATION'], +							'MESSAGE_TEXT'	=> $notice, +							'REFRESH_DATA'	=> array( +								'time'	=> 3 +							) +						)); +					}  				}  				else  				{ @@ -835,9 +834,10 @@ class acp_icons  					WHERE {$fields}_order = $switch_order_id  						AND {$fields}_id <> $icon_id";  				$db->sql_query($sql); +				$move_executed = (bool) $db->sql_affectedrows();  				// Only update the other entry too if the previous entry got updated -				if ($db->sql_affectedrows()) +				if ($move_executed)  				{  					$sql = "UPDATE $table  						SET {$fields}_order = $switch_order_id @@ -849,6 +849,14 @@ class acp_icons  				$cache->destroy('_icons');  				$cache->destroy('sql', $table); +				if ($request->is_ajax()) +				{ +					$json_response = new \phpbb\json_response; +					$json_response->send(array( +						'success'	=> $move_executed, +					)); +				} +  			break;  		} @@ -896,6 +904,7 @@ class acp_icons  		);  		$spacer = false; +		$pagination = $phpbb_container->get('pagination');  		$pagination_start = request_var('start', 0);  		$item_count = $this->item_count($table); @@ -930,9 +939,7 @@ class acp_icons  		}  		$db->sql_freeresult($result); -		$template->assign_var('PAGINATION', -			generate_pagination($this->u_action, $item_count, $config['smilies_per_page'], $pagination_start, true) -		); +		$pagination->generate_template_pagination($this->u_action, 'pagination', 'start', $item_count, $config['smilies_per_page'], $pagination_start);  	}  	/** @@ -954,5 +961,3 @@ class acp_icons  		return $item_count;  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index f3f332d707..e96c42de05 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_inactive  {  	var $u_action; @@ -31,7 +31,7 @@ class acp_inactive  	function main($id, $mode)  	{ -		global $config, $db, $user, $auth, $template; +		global $config, $db, $user, $auth, $template, $phpbb_container;  		global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix;  		include($phpbb_root_path . 'includes/functions_user.' . $phpEx); @@ -50,6 +50,7 @@ class acp_inactive  		$form_key = 'acp_inactive';  		add_form_key($form_key); +		$pagination = $phpbb_container->get('pagination');  		// We build the sort key and per page settings here, because they may be needed later @@ -116,7 +117,7 @@ class acp_inactive  							{  								$messenger->template('admin_welcome_activated', $row['user_lang']); -								$messenger->to($row['user_email'], $row['username']); +								$messenger->set_addresses($row);  								$messenger->anti_abuse_headers($config, $user); @@ -137,6 +138,8 @@ class acp_inactive  								add_log('admin', 'LOG_USER_ACTIVE', $row['username']);  								add_log('user', $row['user_id'], 'LOG_USER_ACTIVE_USER');  							} + +							trigger_error(sprintf($user->lang['LOG_INACTIVE_ACTIVATE'], implode($user->lang['COMMA_SEPARATOR'], $user_affected) . ' ' . adm_back_link($this->u_action)));  						}  						// For activate we really need to redirect, else a refresh can result in users being deactivated again @@ -154,12 +157,11 @@ class acp_inactive  								trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);  							} -							foreach ($mark as $user_id) -							{ -								user_delete('retain', $user_id, $user_affected[$user_id]); -							} +							user_delete('retain', $mark, true);  							add_log('admin', 'LOG_INACTIVE_' . strtoupper($action), implode(', ', $user_affected)); + +							trigger_error(sprintf($user->lang['LOG_INACTIVE_DELETE'], implode($user->lang['COMMA_SEPARATOR'], $user_affected) . ' ' . adm_back_link($this->u_action)));  						}  						else  						{ @@ -203,8 +205,7 @@ class acp_inactive  						{  							$messenger->template('user_remind_inactive', $row['user_lang']); -							$messenger->to($row['user_email'], $row['username']); -							$messenger->im($row['user_jabber'], $row['username']); +							$messenger->set_addresses($row);  							$messenger->anti_abuse_headers($config, $user); @@ -231,7 +232,8 @@ class acp_inactive  						$db->sql_query($sql);  						add_log('admin', 'LOG_INACTIVE_REMIND', implode(', ', $usernames)); -						unset($usernames); + +						trigger_error(sprintf($user->lang['LOG_INACTIVE_REMIND'], implode($user->lang['COMMA_SEPARATOR'], $usernames) . ' ' . adm_back_link($this->u_action)));  					}  					$db->sql_freeresult($result); @@ -284,6 +286,9 @@ class acp_inactive  			$option_ary += array('remind' => 'REMIND');  		} +		$base_url = $this->u_action . "&$u_sort_param&users_per_page=$per_page"; +		$pagination->generate_template_pagination($base_url, 'pagination', 'start', $inactive_count, $per_page, $start); +  		$template->assign_vars(array(  			'S_INACTIVE_USERS'		=> true,  			'S_INACTIVE_OPTIONS'	=> build_select($option_ary), @@ -291,8 +296,6 @@ class acp_inactive  			'S_LIMIT_DAYS'	=> $s_limit_days,  			'S_SORT_KEY'	=> $s_sort_key,  			'S_SORT_DIR'	=> $s_sort_dir, -			'S_ON_PAGE'		=> on_page($inactive_count, $per_page, $start), -			'PAGINATION'	=> generate_pagination($this->u_action . "&$u_sort_param&users_per_page=$per_page", $inactive_count, $per_page, $start, true),  			'USERS_PER_PAGE'	=> $per_page,  			'U_ACTION'		=> $this->u_action . "&$u_sort_param&users_per_page=$per_page&start=$start", @@ -302,5 +305,3 @@ class acp_inactive  		$this->page_title = 'ACP_INACTIVE_USERS';  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_jabber.php b/phpBB/includes/acp/acp_jabber.php index 9925527b34..8d2e9d41a3 100644 --- a/phpBB/includes/acp/acp_jabber.php +++ b/phpBB/includes/acp/acp_jabber.php @@ -1,11 +1,17 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package.  * +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/**  * @todo Check/enter/update transport info  */ @@ -17,9 +23,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_jabber  {  	var $u_action; @@ -44,13 +47,13 @@ class acp_jabber  		$this->tpl_name = 'acp_jabber';  		$this->page_title = 'ACP_JABBER_SETTINGS'; -		$jab_enable			= request_var('jab_enable',			(bool)		$config['jab_enable']); -		$jab_host			= request_var('jab_host',			(string)	$config['jab_host']); -		$jab_port			= request_var('jab_port',			(int)		$config['jab_port']); -		$jab_username		= request_var('jab_username',		(string)	$config['jab_username']); -		$jab_password		= request_var('jab_password',		(string)	$config['jab_password']); -		$jab_package_size	= request_var('jab_package_size',	(int)		$config['jab_package_size']); -		$jab_use_ssl		= request_var('jab_use_ssl',		(bool)		$config['jab_use_ssl']); +		$jab_enable			= request_var('jab_enable',			(bool) $config['jab_enable']); +		$jab_host			= request_var('jab_host',			(string) $config['jab_host']); +		$jab_port			= request_var('jab_port',			(int) $config['jab_port']); +		$jab_username		= request_var('jab_username',		(string) $config['jab_username']); +		$jab_password		= request_var('jab_password',		(string) $config['jab_password']); +		$jab_package_size	= request_var('jab_package_size',	(int) $config['jab_package_size']); +		$jab_use_ssl		= request_var('jab_use_ssl',		(bool) $config['jab_use_ssl']);  		$form_name = 'acp_jabber';  		add_form_key($form_name); @@ -127,5 +130,3 @@ class acp_jabber  		));  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index d560cdd0c5..60e338ae7c 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_language  {  	var $u_action; @@ -31,21 +31,13 @@ class acp_language  	function main($id, $mode)  	{ -		global $config, $db, $user, $auth, $template, $cache; -		global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; -		global $safe_mode, $file_uploads; +		global $config, $db, $user, $template; +		global $phpbb_root_path, $phpEx, $request;  		include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); -		$this->default_variables(); -  		// Check and set some common vars -  		$action		= (isset($_POST['update_details'])) ? 'update_details' : ''; -		$action		= (isset($_POST['download_file'])) ? 'download_file' : $action; -		$action		= (isset($_POST['upload_file'])) ? 'upload_file' : $action; -		$action		= (isset($_POST['upload_data'])) ? 'upload_data' : $action; -		$action		= (isset($_POST['submit_file'])) ? 'submit_file' : $action;  		$action		= (isset($_POST['remove_store'])) ? 'details' : $action;  		$submit = (empty($action) && !isset($_POST['update']) && !isset($_POST['test_connection'])) ? false : true; @@ -55,11 +47,6 @@ class acp_language  		add_form_key('acp_lang');  		$lang_id = request_var('id', 0); -		if (isset($_POST['missing_file'])) -		{ -			$missing_file = request_var('missing_file', array('' => 0)); -			list($_REQUEST['language_file'], ) = array_keys($missing_file); -		}  		$selected_lang_file = request_var('language_file', '|common.' . $phpEx); @@ -72,78 +59,8 @@ class acp_language  		$this->tpl_name = 'acp_language';  		$this->page_title = 'ACP_LANGUAGE_PACKS'; -		if ($submit && $action == 'upload_data' && request_var('test_connection', '')) -		{ -			$test_connection = false; -			$action = 'upload_file'; -			$method = request_var('method', ''); - -			include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx); - -			switch ($method) -			{ -				case 'ftp': -					$transfer = new ftp(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', '')); -				break; - -				case 'ftp_fsock': -					$transfer = new ftp_fsock(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', '')); -				break; - -				default: -					trigger_error($user->lang['INVALID_UPLOAD_METHOD'], E_USER_ERROR); -				break; -			} - -			$test_connection = $transfer->open_session(); -			$transfer->close_session(); -		} -  		switch ($action)  		{ -			case 'upload_file': - -				include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx); - -				$method = request_var('method', ''); - -				if (!class_exists($method)) -				{ -					trigger_error('Method does not exist.', E_USER_ERROR); -				} - -				$requested_data = call_user_func(array($method, 'data')); -				foreach ($requested_data as $data => $default) -				{ -					$template->assign_block_vars('data', array( -						'DATA'		=> $data, -						'NAME'		=> $user->lang[strtoupper($method . '_' . $data)], -						'EXPLAIN'	=> $user->lang[strtoupper($method . '_' . $data) . '_EXPLAIN'], -						'DEFAULT'	=> (!empty($_REQUEST[$data])) ? request_var($data, '') : $default -					)); -				} - -				$hidden_data = build_hidden_fields(array( -					'file'			=> $this->language_file, -					'dir'			=> $this->language_directory, -					'language_file'	=> $selected_lang_file, -					'method'		=> $method) -				); - -				$hidden_data .= build_hidden_fields(array('entry' => $_POST['entry']), true, STRIP); - -				$template->assign_vars(array( -					'S_UPLOAD'	=> true, -					'NAME'		=> $method, -					'U_ACTION'	=> $this->u_action . "&id=$lang_id&action=upload_data", -					'U_BACK'	=> $this->u_action . "&id=$lang_id&action=details&language_file=" . urlencode($selected_lang_file), -					'HIDDEN'	=> $hidden_data, - -					'S_CONNECTION_SUCCESS'		=> (request_var('test_connection', '') && $test_connection === true) ? true : false, -					'S_CONNECTION_FAILED'		=> (request_var('test_connection', '') && $test_connection !== true) ? true : false -				)); -			break; -  			case 'update_details':  				if (!$submit || !check_form_key($form_name)) @@ -178,255 +95,6 @@ class acp_language  				trigger_error($user->lang['LANGUAGE_DETAILS_UPDATED'] . adm_back_link($this->u_action));  			break; -			case 'submit_file': -			case 'download_file': -			case 'upload_data': - -				if (!$submit || !check_form_key($form_name)) -				{ -					trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); -				} - -				if (!$lang_id || empty($_POST['entry'])) -				{ -					trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); -				} - -				if ($this->language_directory != 'email' && !is_array($_POST['entry'])) -				{ -					trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); -				} - -				if (!$this->language_file || (!$this->language_directory && !in_array($this->language_file, $this->main_files))) -				{ -					trigger_error($user->lang['NO_FILE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); -				} - -				$sql = 'SELECT * -					FROM ' . LANG_TABLE . " -					WHERE lang_id = $lang_id"; -				$result = $db->sql_query($sql); -				$row = $db->sql_fetchrow($result); -				$db->sql_freeresult($result); - -				if (!$row) -				{ -					trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); -				} - -				// Before we attempt to write anything let's check if the admin really chose a correct filename -				switch ($this->language_directory) -				{ -					case 'email': -						// Get email templates -						$email_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'email', 'txt'); -						$email_files = $email_files['email/']; - -						if (!in_array($this->language_file, $email_files)) -						{ -							trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); -						} -					break; - -					case 'acp': -						// Get acp files -						$acp_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'acp', $phpEx); -						$acp_files = $acp_files['acp/']; - -						if (!in_array($this->language_file, $acp_files)) -						{ -							trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); -						} -					break; - -					case 'mods': -						// Get mod files -						$mods_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'mods', $phpEx); -						$mods_files = (isset($mods_files['mods/'])) ? $mods_files['mods/'] : array(); - -						if (!in_array($this->language_file, $mods_files)) -						{ -							trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); -						} -					break; - -					default: -						if (!in_array($this->language_file, $this->main_files)) -						{ -							trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); -						} -					break; -				} - -				if (!$safe_mode) -				{ -					$mkdir_ary = array('language', 'language/' . $row['lang_iso']); - -					if ($this->language_directory) -					{ -						$mkdir_ary[] = 'language/' . $row['lang_iso'] . '/' . $this->language_directory; -					} - -					foreach ($mkdir_ary as $dir) -					{ -						$dir = $phpbb_root_path . 'store/' . $dir; - -						if (!is_dir($dir)) -						{ -							if (!@mkdir($dir, 0777)) -							{ -								trigger_error("Could not create directory $dir", E_USER_ERROR); -							} -							@chmod($dir, 0777); -						} -					} -				} - -				// Get target filename for storage folder -				$filename = $this->get_filename($row['lang_iso'], $this->language_directory, $this->language_file, true, true); -				$fp = @fopen($phpbb_root_path . $filename, 'wb'); - -				if (!$fp) -				{ -					trigger_error(sprintf($user->lang['UNABLE_TO_WRITE_FILE'], $filename) . adm_back_link($this->u_action . '&id=' . $lang_id . '&action=details&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); -				} - -				if ($this->language_directory == 'email') -				{ -					// Email Template -					$entry = $this->prepare_lang_entry($_POST['entry'], false); -					fwrite($fp, $entry); -				} -				else -				{ -					$name = (($this->language_directory) ? $this->language_directory . '_' : '') . $this->language_file; -					$header = str_replace(array('{FILENAME}', '{LANG_NAME}', '{CHANGED}', '{AUTHOR}'), array($name, $row['lang_english_name'], date('Y-m-d', time()), $row['lang_author']), $this->language_file_header); - -					if (strpos($this->language_file, 'help_') === 0) -					{ -						// Help File -						$header .= '$help = array(' . "\n"; -						fwrite($fp, $header); - -						foreach ($_POST['entry'] as $key => $value) -						{ -							if (!is_array($value)) -							{ -								continue; -							} - -							$entry = "\tarray(\n"; - -							foreach ($value as $_key => $_value) -							{ -								$entry .= "\t\t" . (int) $_key . "\t=> '" . $this->prepare_lang_entry($_value) . "',\n"; -							} - -							$entry .= "\t),\n"; -							fwrite($fp, $entry); -						} - -						$footer = ");\n\n?>"; -						fwrite($fp, $footer); -					} -					else -					{ -						// Language File -						$header .= $this->lang_header; -						fwrite($fp, $header); - -						foreach ($_POST['entry'] as $key => $value) -						{ -							$entry = $this->format_lang_array($key, $value); -							fwrite($fp, $entry); -						} - -						$footer = "));\n\n?>"; -						fwrite($fp, $footer); -					} -				} - -				fclose($fp); - -				if ($action == 'download_file') -				{ -					header('Pragma: no-cache'); -					header('Content-Type: application/octetstream; name="' . $this->language_file . '"'); -					header('Content-disposition: attachment; filename=' . $this->language_file); - -					$fp = @fopen($phpbb_root_path . $filename, 'rb'); -					while ($buffer = fread($fp, 1024)) -					{ -						echo $buffer; -					} -					fclose($fp); - -					add_log('admin', 'LOG_LANGUAGE_FILE_SUBMITTED', $this->language_file); - -					exit; -				} -				else if ($action == 'upload_data') -				{ -					$sql = 'SELECT lang_iso -						FROM ' . LANG_TABLE . " -						WHERE lang_id = $lang_id"; -					$result = $db->sql_query($sql); -					$row = $db->sql_fetchrow($result); -					$db->sql_freeresult($result); - -					$file = request_var('file', ''); -					$dir = request_var('dir', ''); - -					$selected_lang_file = $dir . '|' . $file; - -					$old_file = '/' . $this->get_filename($row['lang_iso'], $dir, $file, false, true); -					$lang_path = 'language/' . $row['lang_iso'] . '/' . (($dir) ? $dir . '/' : ''); - -					include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx); -					$method = request_var('method', ''); - -					if ($method != 'ftp' && $method != 'ftp_fsock') -					{ -						trigger_error($user->lang['INVALID_UPLOAD_METHOD'], E_USER_ERROR); -					} - -					$transfer = new $method(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', '')); - -					if (($result = $transfer->open_session()) !== true) -					{ -						trigger_error($user->lang[$result] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id . '&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); -					} - -					$transfer->rename($lang_path . $file, $lang_path . $file . '.bak'); -					$result = $transfer->copy_file('store/' . $lang_path . $file, $lang_path . $file); - -					if ($result === false) -					{ -						// If failed, try to rename again and print error out... -						$transfer->delete_file($lang_path . $file); -						$transfer->rename($lang_path . $file . '.bak', $lang_path . $file); - -						trigger_error($user->lang['UPLOAD_FAILED'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id . '&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); -					} - -					$transfer->close_session(); - -					// Remove from storage folder -					if (file_exists($phpbb_root_path . 'store/' . $lang_path . $file)) -					{ -						@unlink($phpbb_root_path . 'store/' . $lang_path . $file); -					} - -					add_log('admin', 'LOG_LANGUAGE_FILE_REPLACED', $file); - -					trigger_error($user->lang['UPLOAD_COMPLETED'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id . '&language_file=' . urlencode($selected_lang_file))); -				} - -				add_log('admin', 'LOG_LANGUAGE_FILE_SUBMITTED', $this->language_file); -				$action = 'details'; - -			// no break; -  			case 'details':  				if (!$lang_id) @@ -443,308 +111,82 @@ class acp_language  				$lang_entries = $db->sql_fetchrow($result);  				$db->sql_freeresult($result); -				$lang_iso = $lang_entries['lang_iso']; -				$missing_vars = $missing_files = array(); - -				// Get email templates -				$email_files = filelist($phpbb_root_path . 'language/' . $config['default_lang'], 'email', 'txt'); -				$email_files = $email_files['email/']; - -				// Get acp files -				$acp_files = filelist($phpbb_root_path . 'language/' . $config['default_lang'], 'acp', $phpEx); -				$acp_files = $acp_files['acp/']; - -				// Get mod files -				$mods_files = filelist($phpbb_root_path . 'language/' . $config['default_lang'], 'mods', $phpEx); -				$mods_files = (isset($mods_files['mods/'])) ? $mods_files['mods/'] : array(); - -				// Check if our current filename matches the files -				switch ($this->language_directory) +				if (!$lang_entries)  				{ -					case 'email': -						if (!in_array($this->language_file, $email_files)) -						{ -							trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); -						} -					break; - -					case 'acp': -						if (!in_array($this->language_file, $acp_files)) -						{ -							trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); -						} -					break; - -					case 'mods': -						if (!in_array($this->language_file, $mods_files)) -						{ -							trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); -						} -					break; - -					default: -						if (!in_array($this->language_file, $this->main_files)) -						{ -							trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); -						} -				} - -				if (isset($_POST['remove_store'])) -				{ -					$store_filename = $this->get_filename($lang_iso, $this->language_directory, $this->language_file, true, true); - -					if (file_exists($phpbb_root_path . $store_filename)) -					{ -						@unlink($phpbb_root_path . $store_filename); -					} +					trigger_error($user->lang['LANGUAGE_PACK_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING);  				} -				include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx); - -				$methods = transfer::methods(); - -				foreach ($methods as $method) -				{ -					$template->assign_block_vars('buttons', array( -						'VALUE' => $method -					)); -				} +				$lang_iso = $lang_entries['lang_iso'];  				$template->assign_vars(array(  					'S_DETAILS'			=> true,  					'U_ACTION'			=> $this->u_action . "&action=details&id=$lang_id",  					'U_BACK'			=> $this->u_action, +  					'LANG_LOCAL_NAME'	=> $lang_entries['lang_local_name'],  					'LANG_ENGLISH_NAME'	=> $lang_entries['lang_english_name'], -					'LANG_ISO'			=> $lang_entries['lang_iso'], +					'LANG_ISO'			=> $lang_iso,  					'LANG_AUTHOR'		=> $lang_entries['lang_author'], -					'ALLOW_UPLOAD'		=> sizeof($methods) -					) -				); +					'L_MISSING_FILES'			=> $user->lang('THOSE_MISSING_LANG_FILES', $lang_entries['lang_local_name']), +					'L_MISSING_VARS_EXPLAIN'	=> $user->lang('THOSE_MISSING_LANG_VARIABLES', $lang_entries['lang_local_name']), +				)); -				// If current lang is different from the default lang, then first try to grab missing/additional vars +				// If current lang is different from the default lang, then highlight missing files and variables  				if ($lang_iso != $config['default_lang'])  				{ -					$is_missing_var = false; - -					foreach ($this->main_files as $file) +					try  					{ -						if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file))) -						{ -							$missing_vars[$file] = $this->compare_language_files($config['default_lang'], $lang_iso, '', $file); - -							if (sizeof($missing_vars[$file])) -							{ -								$is_missing_var = true; -							} -						} -						else -						{ -							$missing_files[] = $this->get_filename($lang_iso, '', $file); -						} +						$iterator = new \RecursiveIteratorIterator( +							new \phpbb\recursive_dot_prefix_filter_iterator( +								new \RecursiveDirectoryIterator( +									$phpbb_root_path . 'language/' . $config['default_lang'] . '/', +									\FilesystemIterator::SKIP_DOTS +								) +							), +							\RecursiveIteratorIterator::LEAVES_ONLY +						);  					} - -					// Now go through acp/mods directories -					foreach ($acp_files as $file) +					catch (\Exception $e)  					{ -						if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'acp', $file))) -						{ -							$missing_vars['acp/' . $file] = $this->compare_language_files($config['default_lang'], $lang_iso, 'acp', $file); - -							if (sizeof($missing_vars['acp/' . $file])) -							{ -								$is_missing_var = true; -							} -						} -						else -						{ -							$missing_files[] = $this->get_filename($lang_iso, 'acp', $file); -						} +						return array();  					} -					if (sizeof($mods_files)) +					foreach ($iterator as $file_info)  					{ -						foreach ($mods_files as $file) +						/** @var \RecursiveDirectoryIterator $file_info */ +						$relative_path = $iterator->getInnerIterator()->getSubPathname(); +						$relative_path = str_replace(DIRECTORY_SEPARATOR, '/', $relative_path); + +						if (file_exists($phpbb_root_path . 'language/' . $lang_iso . '/' . $relative_path))  						{ -							if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'mods', $file))) +							if (substr($relative_path, 0 - strlen($phpEx)) === $phpEx)  							{ -								$missing_vars['mods/' . $file] = $this->compare_language_files($config['default_lang'], $lang_iso, 'mods', $file); +								$missing_vars = $this->compare_language_files($config['default_lang'], $lang_iso, $relative_path); -								if (sizeof($missing_vars['mods/' . $file])) +								if (!empty($missing_vars))  								{ -									$is_missing_var = true; +									$template->assign_block_vars('missing_varfile', array( +										'FILE_NAME'			=> $relative_path, +									)); + +									foreach ($missing_vars as $var) +									{ +										$template->assign_block_vars('missing_varfile.variable', array( +												'VAR_NAME'			=> $var, +										)); +									}  								}  							} -							else -							{ -								$missing_files[] = $this->get_filename($lang_iso, 'mods', $file); -							} -						} -					} - -					// More missing files... for example email templates? -					foreach ($email_files as $file) -					{ -						if (!file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'email', $file))) -						{ -							$missing_files[] = $this->get_filename($lang_iso, 'email', $file);  						} -					} - -					if (sizeof($missing_files)) -					{ -						$template->assign_vars(array( -							'S_MISSING_FILES'		=> true, -							'L_MISSING_FILES'		=> sprintf($user->lang['THOSE_MISSING_LANG_FILES'], $lang_entries['lang_local_name']), -							'MISSING_FILES'			=> implode('<br />', $missing_files)) -						); -					} - -					if ($is_missing_var) -					{ -						$template->assign_vars(array( -							'S_MISSING_VARS'			=> true, -							'L_MISSING_VARS_EXPLAIN'	=> sprintf($user->lang['THOSE_MISSING_LANG_VARIABLES'], $lang_entries['lang_local_name']), -							'U_MISSING_ACTION'			=> $this->u_action . "&action=$action&id=$lang_id") -						); - -						foreach ($missing_vars as $file => $vars) -						{ -							if (!sizeof($vars)) -							{ -								continue; -							} - -							$template->assign_block_vars('missing', array( -								'FILE'			=> $file, -								'TPL'			=> $this->print_language_entries($vars, '', false), -								'KEY'			=> (strpos($file, '/') === false) ? '|' . $file : str_replace('/', '|', $file)) -							); -						} -					} -				} - -				// Main language files -				$s_lang_options = '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang['LANGUAGE_FILES'] . '</option>'; -				foreach ($this->main_files as $file) -				{ -					if (strpos($file, 'help_') === 0) -					{ -						continue; -					} - -					$prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file, true, true))) ? '* ' : ''; - -					$selected = (!$this->language_directory && $this->language_file == $file) ? ' selected="selected"' : ''; -					$s_lang_options .= '<option value="|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>'; -				} - -				// Help Files -				$s_lang_options .= '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang['HELP_FILES'] . '</option>'; -				foreach ($this->main_files as $file) -				{ -					if (strpos($file, 'help_') !== 0) -					{ -						continue; -					} - -					$prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file, true, true))) ? '* ' : ''; - -					$selected = (!$this->language_directory && $this->language_file == $file) ? ' selected="selected"' : ''; -					$s_lang_options .= '<option value="|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>'; -				} - -				// Now every other language directory -				$check_files = array('email', 'acp', 'mods'); - -				foreach ($check_files as $check) -				{ -					if (!sizeof(${$check . '_files'})) -					{ -						continue; -					} - -					$s_lang_options .= '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang[strtoupper($check) . '_FILES'] . '</option>'; - -					foreach (${$check . '_files'} as $file) -					{ -						$prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, $check, $file, true, true))) ? '* ' : ''; - -						$selected = ($this->language_directory == $check && $this->language_file == $file) ? ' selected="selected"' : ''; -						$s_lang_options .= '<option value="' . $check . '|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>'; -					} -				} - -				// Get Language Entries - if saved within store folder, we take this one (with the option to remove it) -				$lang = array(); - -				$is_email_file = ($this->language_directory == 'email') ? true : false; -				$is_help_file = (strpos($this->language_file, 'help_') === 0) ? true : false; - -				$file_from_store = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, true, true))) ? true : false; -				$no_store_filename = $this->get_filename($lang_iso, $this->language_directory, $this->language_file); - -				if (!$file_from_store && !file_exists($phpbb_root_path . $no_store_filename)) -				{ -					$print_message = sprintf($user->lang['MISSING_LANGUAGE_FILE'], $no_store_filename); -				} -				else -				{ -					if ($is_email_file) -					{ -						$lang = file_get_contents($phpbb_root_path . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, $file_from_store)); -					} -					else -					{ -						$help = array(); -						include($phpbb_root_path . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, $file_from_store)); - -						if ($is_help_file) +						else  						{ -							$lang = $help; -							unset($help); +							$template->assign_block_vars('missing_files', array( +								'FILE_NAME' => $relative_path, +							));  						}  					} - -					$print_message = (($this->language_directory) ? $this->language_directory . '/' : '') . $this->language_file; -				} - -				// Normal language pack entries -				$template->assign_vars(array( -					'U_ENTRY_ACTION'		=> $this->u_action . "&action=details&id=$lang_id#entries", -					'S_EMAIL_FILE'			=> $is_email_file, -					'S_FROM_STORE'			=> $file_from_store, -					'S_LANG_OPTIONS'		=> $s_lang_options, -					'PRINT_MESSAGE'			=> $print_message, -					) -				); - -				if (!$is_email_file) -				{ -					$tpl = ''; -					$name = (($this->language_directory) ? $this->language_directory . '/' : '') . $this->language_file; - -					if (isset($missing_vars[$name]) && sizeof($missing_vars[$name])) -					{ -						$tpl .= $this->print_language_entries($missing_vars[$name], '* '); -					} - -					$tpl .= $this->print_language_entries($lang); - -					$template->assign_var('TPL', $tpl); -					unset($tpl);  				} -				else -				{ -					$template->assign_vars(array( -						'LANG'		=> $lang) -					); - -					unset($lang); -				} -  				return; -  			break;  			case 'delete': @@ -782,11 +224,6 @@ class acp_language  					$sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_id;  					$db->sql_query($sql); -					$sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " WHERE image_lang = '" . $db->sql_escape($row['lang_iso']) . "'"; -					$result = $db->sql_query($sql); - -					$cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); -  					add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']);  					trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action)); @@ -799,7 +236,7 @@ class acp_language  						'action'	=> $action,  						'id'		=> $lang_id,  					); -					confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields)); +					confirm_box(false, $user->lang('DELETE_LANGUAGE_CONFIRM', $row['lang_english_name']), build_hidden_fields($s_hidden_fields));  				}  			break; @@ -851,66 +288,6 @@ class acp_language  				$db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));  				$lang_id = $db->sql_nextid(); -				$valid_localized = array( -					'icon_back_top', 'icon_contact_aim', 'icon_contact_email', 'icon_contact_icq', 'icon_contact_jabber', 'icon_contact_msnm', 'icon_contact_pm', 'icon_contact_yahoo', 'icon_contact_www', 'icon_post_delete', 'icon_post_edit', 'icon_post_info', 'icon_post_quote', 'icon_post_report', 'icon_user_online', 'icon_user_offline', 'icon_user_profile', 'icon_user_search', 'icon_user_warn', 'button_pm_forward', 'button_pm_new', 'button_pm_reply', 'button_topic_locked', 'button_topic_new', 'button_topic_reply', -				); - -				$sql_ary = array(); - -				$sql = 'SELECT * -					FROM ' . STYLES_IMAGESET_TABLE; -				$result = $db->sql_query($sql); -				while ($imageset_row = $db->sql_fetchrow($result)) -				{ -					if (@file_exists("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$lang_pack['iso']}/imageset.cfg")) -					{ -						$cfg_data_imageset_data = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$lang_pack['iso']}/imageset.cfg"); -						foreach ($cfg_data_imageset_data as $image_name => $value) -						{ -							if (strpos($value, '*') !== false) -							{ -								if (substr($value, -1, 1) === '*') -								{ -									list($image_filename, $image_height) = explode('*', $value); -									$image_width = 0; -								} -								else -								{ -									list($image_filename, $image_height, $image_width) = explode('*', $value); -								} -							} -							else -							{ -								$image_filename = $value; -								$image_height = $image_width = 0; -							} - -							if (strpos($image_name, 'img_') === 0 && $image_filename) -							{ -								$image_name = substr($image_name, 4); -								if (in_array($image_name, $valid_localized)) -								{ -									$sql_ary[] = array( -										'image_name'		=> (string) $image_name, -										'image_filename'	=> (string) $image_filename, -										'image_height'		=> (int) $image_height, -										'image_width'		=> (int) $image_width, -										'imageset_id'		=> (int) $imageset_row['imageset_id'], -										'image_lang'		=> (string) $lang_pack['iso'], -									); -								} -							} -						} -					} -				} -				$db->sql_freeresult($result); - -				if (sizeof($sql_ary)) -				{ -					$db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); -					$cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); -				} -  				// Now let's copy the default language entries for custom profile fields for this new language - makes admin's life easier.  				$sql = 'SELECT lang_id  					FROM ' . LANG_TABLE . " @@ -959,127 +336,6 @@ class acp_language  				trigger_error($message . adm_back_link($this->u_action));  			break; - -			case 'download': - -				if (!$lang_id) -				{ -					trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); -				} - -				$sql = 'SELECT * -					FROM ' . LANG_TABLE . ' -					WHERE lang_id = ' . $lang_id; -				$result = $db->sql_query($sql); -				$row = $db->sql_fetchrow($result); -				$db->sql_freeresult($result); - -				$use_method = request_var('use_method', ''); -				$methods = array('.tar'); - -				$available_methods = array('.tar.gz' => 'zlib', '.tar.bz2' => 'bz2', '.zip' => 'zlib'); -				foreach ($available_methods as $type => $module) -				{ -					if (!@extension_loaded($module)) -					{ -						continue; -					} - -					$methods[] = $type; -				} - -				// Let the user decide in which format he wants to have the pack -				if (!$use_method) -				{ -					$this->page_title = 'SELECT_DOWNLOAD_FORMAT'; - -					$radio_buttons = ''; -					foreach ($methods as $method) -					{ -						$radio_buttons .= '<label><input type="radio"' . ((!$radio_buttons) ? ' id="use_method"' : '') . ' class="radio" value="' . $method . '" name="use_method" /> ' . $method . '</label>'; -					} - -					$template->assign_vars(array( -						'S_SELECT_METHOD'		=> true, -						'U_BACK'				=> $this->u_action, -						'U_ACTION'				=> $this->u_action . "&action=$action&id=$lang_id", -						'RADIO_BUTTONS'			=> $radio_buttons) -					); - -					return; -				} - -				if (!in_array($use_method, $methods)) -				{ -					$use_method = '.tar'; -				} - -				include_once($phpbb_root_path . 'includes/functions_compress.' . $phpEx); - -				if ($use_method == '.zip') -				{ -					$compress = new compress_zip('w', $phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method); -				} -				else -				{ -					$compress = new compress_tar('w', $phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method, $use_method); -				} - -				// Get email templates -				$email_templates = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'email', 'txt'); -				$email_templates = $email_templates['email/']; - -				// Get acp files -				$acp_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'acp', $phpEx); -				$acp_files = $acp_files['acp/']; - -				// Get mod files -				$mod_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'mods', $phpEx); -				$mod_files = (isset($mod_files['mods/'])) ? $mod_files['mods/'] : array(); - -				// Add main files -				$this->add_to_archive($compress, $this->main_files, $row['lang_iso']); - -				// Add search files if they exist... -				if (file_exists($phpbb_root_path . 'language/' . $row['lang_iso'] . '/search_ignore_words.' . $phpEx)) -				{ -					$this->add_to_archive($compress, array("search_ignore_words.$phpEx"), $row['lang_iso']); -				} - -				if (file_exists($phpbb_root_path . 'language/' . $row['lang_iso'] . '/search_synonyms.' . $phpEx)) -				{ -					$this->add_to_archive($compress, array("search_synonyms.$phpEx"), $row['lang_iso']); -				} - -				// Write files in folders -				$this->add_to_archive($compress, $email_templates, $row['lang_iso'], 'email'); -				$this->add_to_archive($compress, $acp_files, $row['lang_iso'], 'acp'); -				$this->add_to_archive($compress, $mod_files, $row['lang_iso'], 'mods'); - -				// Write ISO File -				$iso_src = htmlspecialchars_decode($row['lang_english_name']) . "\n"; -				$iso_src .= htmlspecialchars_decode($row['lang_local_name']) . "\n"; -				$iso_src .= htmlspecialchars_decode($row['lang_author']); -				$compress->add_data($iso_src, 'language/' . $row['lang_iso'] . '/iso.txt'); - -				// index.htm files -				$compress->add_data('', 'language/' . $row['lang_iso'] . '/index.htm'); -				$compress->add_data('', 'language/' . $row['lang_iso'] . '/email/index.htm'); -				$compress->add_data('', 'language/' . $row['lang_iso'] . '/acp/index.htm'); - -				if (sizeof($mod_files)) -				{ -					$compress->add_data('', 'language/' . $row['lang_iso'] . '/mods/index.htm'); -				} - -				$compress->close(); - -				$compress->download('lang_' . $row['lang_iso']); -				@unlink($phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method); - -				exit; - -			break;  		}  		$sql = 'SELECT user_lang, COUNT(user_lang) AS lang_count @@ -1172,294 +428,31 @@ class acp_language  		unset($new_ary);  	} - -	/** -	* Set default language variables/header -	*/ -	function default_variables() -	{ -		global $phpEx; - -		$this->language_file_header = '<?php -/** -* -* {FILENAME} [{LANG_NAME}] -* -* @package language -* @version $' . 'Id: ' . '$ -* @copyright (c) ' . date('Y') . ' phpBB Group -* @author {CHANGED} - {AUTHOR} -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* DO NOT CHANGE -*/ -if (!defined(\'IN_PHPBB\')) -{ -	exit; -} - -if (empty($lang) || !is_array($lang)) -{ -	$lang = array(); -} - -// DEVELOPERS PLEASE NOTE -// -// All language files should use UTF-8 as their encoding and the files must not contain a BOM. -// -// Placeholders can now contain order information, e.g. instead of -// \'Page %s of %s\' you can (and should) write \'Page %1$s of %2$s\', this allows -// translators to re-order the output of data while ensuring it remains correct -// -// You do not need this where single placeholders are used, e.g. \'Message %d\' is fine -// equally where a string contains only two placeholders which are used to wrap text -// in a url you again do not need to specify an order e.g., \'Click %sHERE%s\' is fine -'; - -		$this->lang_header = ' -$lang = array_merge($lang, array( -'; - -		// Language files in language root directory -		$this->main_files = array("captcha_qa.$phpEx", "captcha_recaptcha.$phpEx", "common.$phpEx", "groups.$phpEx", "install.$phpEx", "mcp.$phpEx", "memberlist.$phpEx", "posting.$phpEx", "search.$phpEx", "ucp.$phpEx", "viewforum.$phpEx", "viewtopic.$phpEx", "help_bbcode.$phpEx", "help_faq.$phpEx"); -	} -  	/** -	* Get filename/location of language file -	*/ -	function get_filename($lang_iso, $directory, $filename, $check_store = false, $only_return_filename = false) -	{ -		global $phpbb_root_path, $safe_mode; - -		$check_filename = "language/$lang_iso/" . (($directory) ? $directory . '/' : '') . $filename; - -		if ($check_store) -		{ -			$check_store_filename = ($safe_mode) ? "store/langfile_{$lang_iso}" . (($directory) ? '_' . $directory : '') . "_{$filename}" : "store/language/$lang_iso/" . (($directory) ? $directory . '/' : '') . $filename; - -			if (!$only_return_filename && file_exists($phpbb_root_path . $check_store_filename)) -			{ -				return $check_store_filename; -			} -			else if ($only_return_filename) -			{ -				return $check_store_filename; -			} -		} - -		return $check_filename; -	} - -	/** -	* Add files to archive +	* Compare two language files  	*/ -	function add_to_archive(&$compress, $filelist, $lang_iso, $directory = '') +	function compare_language_files($source_lang, $dest_lang, $file)  	{  		global $phpbb_root_path; -		foreach ($filelist as $file) -		{ -			// Get source filename -			$source = $this->get_filename($lang_iso, $directory, $file, true); -			$destination = 'language/' . $lang_iso . '/' . (($directory) ? $directory . '/' : '') . $file; - -			// Add file to archive -			$compress->add_custom_file($phpbb_root_path . $source, $destination); -		} -	} - -	/** -	* Little helper to add some hardcoded template bits -	*/ -	function add_input_field() -	{ -		$keys = func_get_args(); - -		$non_static		= array_shift($keys); -		$value			= utf8_normalize_nfc(array_shift($keys)); +		$source_file = $phpbb_root_path . 'language/' . $source_lang . '/' . $file; +		$dest_file = $phpbb_root_path . 'language/' . $dest_lang . '/' . $file; -		if (!$non_static) +		if (!file_exists($dest_file))  		{ -			return '<strong>' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '</strong>'; -		} - -		// If more then 270 characters, then we present a textarea, else an input field -		$textarea = (utf8_strlen($value) > 270) ? true : false; -		$tpl = ''; - -		$tpl .= ($textarea) ? '<textarea name="' : '<input type="text" name="'; -		$tpl .= 'entry[' . implode('][', array_map('utf8_htmlspecialchars', $keys)) . ']"'; - -		$tpl .= ($textarea) ? ' cols="80" rows="5" class="langvalue">' : ' class="langvalue" value="'; -		$tpl .= htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); -		$tpl .= ($textarea) ? '</textarea>' : '" />'; - -		return $tpl; -	} - -	/** -	* Print language entries -	*/ -	function print_language_entries(&$lang_ary, $key_prefix = '', $input_field = true) -	{ -		$tpl = ''; - -		foreach ($lang_ary as $key => $value) -		{ -			if (is_array($value)) -			{ -				// Write key -				$tpl .= ' -				<tr> -					<td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</strong></td> -				</tr>'; - -				foreach ($value as $_key => $_value) -				{ -					if (is_array($_value)) -					{ -						// Write key -						$tpl .= ' -							<tr> -								<td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '   <strong>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</strong></td> -							</tr>'; - -						foreach ($_value as $__key => $__value) -						{ -							// Write key -							$tpl .= ' -								<tr> -									<td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($__key, ENT_COMPAT, 'UTF-8') . '</strong></td> -									<td class="row2">'; - -							$tpl .= $this->add_input_field($input_field, $__value, $key, $_key, $__key); - -							$tpl .= '</td> -								</tr>'; -						} -					} -					else -					{ -						// Write key -						$tpl .= ' -							<tr> -								<td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</strong></td> -								<td class="row2">'; - -						$tpl .= $this->add_input_field($input_field, $_value, $key, $_key); - -						$tpl .= '</td> -							</tr>'; -					} -				} - -				$tpl .= ' -				<tr> -					<td class="spacer" colspan="2"> </td> -				</tr>'; -			} -			else -			{ -				// Write key -				$tpl .= ' -				<tr> -					<td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</strong></td> -					<td class="row2">'; - -				$tpl .= $this->add_input_field($input_field, $value, $key); - -				$tpl .= '</td> -					</tr>'; -			} +			return array();  		} -		return $tpl; -	} - -	/** -	* Compare two language files -	*/ -	function compare_language_files($source_lang, $dest_lang, $directory, $file) -	{ -		global $phpbb_root_path, $phpEx; - -		$return_ary = array(); -  		$lang = array(); -		include("{$phpbb_root_path}language/{$source_lang}/" . (($directory) ? $directory . '/' : '') . $file); +		include($source_file);  		$lang_entry_src = $lang;  		$lang = array(); - -		if (!file_exists($phpbb_root_path . $this->get_filename($dest_lang, $directory, $file, true))) -		{ -			return array(); -		} - -		include($phpbb_root_path . $this->get_filename($dest_lang, $directory, $file, true)); - +		include($dest_file);  		$lang_entry_dst = $lang;  		unset($lang); -		$diff_array_keys = array_diff(array_keys($lang_entry_src), array_keys($lang_entry_dst)); -		unset($lang_entry_dst); - -		foreach ($diff_array_keys as $key) -		{ -			$return_ary[$key] = $lang_entry_src[$key]; -		} - -		unset($lang_entry_src); - -		return $return_ary; -	} - -	/** -	* Return language string value for storage -	*/ -	function prepare_lang_entry($text, $store = true) -	{ -		$text = (STRIP) ? stripslashes($text) : $text; - -		// Adjust for storage... -		if ($store) -		{ -			$text = str_replace("'", "\\'", str_replace('\\', '\\\\', $text)); -		} - -		return $text; -	} - -	/** -	* Format language array for storage -	*/ -	function format_lang_array($key, $value, $tabs = "\t") -	{ -		$entry = ''; - -		if (!is_array($value)) -		{ -			$entry .= "{$tabs}'" . $this->prepare_lang_entry($key) . "'\t=> '" . $this->prepare_lang_entry($value) . "',\n"; -		} -		else -		{ -			$_tabs = $tabs . "\t"; -			$entry .= "\n{$tabs}'" . $this->prepare_lang_entry($key) . "'\t=> array(\n"; - -			foreach ($value as $_key => $_value) -			{ -				$entry .= $this->format_lang_array($_key, $_value, $_tabs); -			} - -			$entry .= "{$tabs}),\n\n"; -		} - -		return $entry; +		return array_diff(array_keys($lang_entry_src), array_keys($lang_entry_dst));  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_logs.php b/phpBB/includes/acp/acp_logs.php index 2fc86e325f..80dee1d620 100644 --- a/phpBB/includes/acp/acp_logs.php +++ b/phpBB/includes/acp/acp_logs.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,17 +19,15 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_logs  {  	var $u_action;  	function main($id, $mode)  	{ -		global $db, $user, $auth, $template, $cache; +		global $db, $user, $auth, $template, $cache, $phpbb_container;  		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; +		global $request;  		$user->add_lang('mcp'); @@ -35,8 +36,8 @@ class acp_logs  		$forum_id	= request_var('f', 0);  		$topic_id	= request_var('t', 0);  		$start		= request_var('start', 0); -		$deletemark = (!empty($_POST['delmarked'])) ? true : false; -		$deleteall	= (!empty($_POST['delall'])) ? true : false; +		$deletemark = $request->variable('delmarked', false, false, \phpbb\request\request_interface::POST); +		$deleteall	= $request->variable('delall', false, false, \phpbb\request\request_interface::POST);  		$marked		= request_var('mark', array(0));  		// Sort keys @@ -46,34 +47,33 @@ class acp_logs  		$this->tpl_name = 'acp_logs';  		$this->log_type = constant('LOG_' . strtoupper($mode)); +		$pagination = $phpbb_container->get('pagination');  		// Delete entries if requested and able  		if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs'))  		{  			if (confirm_box(true))  			{ -				$where_sql = ''; +				$conditions = array();  				if ($deletemark && sizeof($marked))  				{ -					$sql_in = array(); -					foreach ($marked as $mark) -					{ -						$sql_in[] = $mark; -					} -					$where_sql = ' AND ' . $db->sql_in_set('log_id', $sql_in); -					unset($sql_in); +					$conditions['log_id'] = array('IN' => $marked);  				} -				if ($where_sql || $deleteall) +				if ($deleteall)  				{ -					$sql = 'DELETE FROM ' . LOG_TABLE . " -						WHERE log_type = {$this->log_type} -						$where_sql"; -					$db->sql_query($sql); +					if ($sort_days) +					{ +						$conditions['log_time'] = array('>=', time() - ($sort_days * 86400)); +					} -					add_log('admin', 'LOG_CLEAR_' . strtoupper($mode)); +					$keywords = utf8_normalize_nfc(request_var('keywords', '', true)); +					$conditions['keywords'] = $keywords;  				} + +				$phpbb_log = $phpbb_container->get('log'); +				$phpbb_log->delete($mode, $conditions);  			}  			else  			{ @@ -117,7 +117,7 @@ class acp_logs  		if ($mode == 'mod')  		{  			$forum_box = '<option value="0">' . $user->lang['ALL_FORUMS'] . '</option>' . make_forum_select($forum_id); -			 +  			$template->assign_vars(array(  				'S_SHOW_FORUMS'			=> true,  				'S_FORUM_BOX'			=> $forum_box) @@ -129,14 +129,14 @@ class acp_logs  		$log_count = 0;  		$start = view_log($mode, $log_data, $log_count, $config['topics_per_page'], $start, $forum_id, 0, 0, $sql_where, $sql_sort, $keywords); +		$base_url = $this->u_action . "&$u_sort_param$keywords_param"; +		$pagination->generate_template_pagination($base_url, 'pagination', 'start', $log_count, $config['topics_per_page'], $start); +  		$template->assign_vars(array(  			'L_TITLE'		=> $l_title,  			'L_EXPLAIN'		=> $l_title_explain,  			'U_ACTION'		=> $this->u_action . "&$u_sort_param$keywords_param&start=$start", -			'S_ON_PAGE'		=> on_page($log_count, $config['topics_per_page'], $start), -			'PAGINATION'	=> generate_pagination($this->u_action . "&$u_sort_param$keywords_param", $log_count, $config['topics_per_page'], $start, true), -  			'S_LIMIT_DAYS'	=> $s_limit_days,  			'S_SORT_KEY'	=> $s_sort_key,  			'S_SORT_DIR'	=> $s_sort_dir, @@ -148,7 +148,7 @@ class acp_logs  		foreach ($log_data as $row)  		{  			$data = array(); -				 +  			$checks = array('viewtopic', 'viewlogs', 'viewforum');  			foreach ($checks as $check)  			{ @@ -172,5 +172,3 @@ class acp_logs  		}  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index 79557bb5fd..48ca05a118 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,17 +19,14 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_main  {  	var $u_action;  	function main($id, $mode)  	{ -		global $config, $db, $user, $auth, $template; -		global $phpbb_root_path, $phpbb_admin_path, $phpEx; +		global $config, $db, $cache, $user, $auth, $template, $request; +		global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container, $phpbb_dispatcher;  		// Show restore permissions notice  		if ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) @@ -41,11 +41,7 @@ class acp_main  			$user_row = $db->sql_fetchrow($result);  			$db->sql_freeresult($result); -			$perm_from = '<strong' . (($user_row['user_colour']) ? ' style="color: #' . $user_row['user_colour'] . '">' : '>'); -			$perm_from .= ($user_row['user_id'] != ANONYMOUS) ? '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $user_row['user_id']) . '">' : ''; -			$perm_from .= $user_row['username']; -			$perm_from .= ($user_row['user_id'] != ANONYMOUS) ? '</a>' : ''; -			$perm_from .= '</strong>'; +			$perm_from = get_username_string('full', $user_row['user_id'], $user_row['username'], $user_row['user_colour']);  			$template->assign_vars(array(  				'S_RESTORE_PERMISSIONS'		=> true, @@ -64,9 +60,7 @@ class acp_main  			if ($action === 'admlogout')  			{  				$user->unset_admin(); -				$redirect_url = append_sid("{$phpbb_root_path}index.$phpEx"); -				meta_refresh(3, $redirect_url); -				trigger_error($user->lang['ADM_LOGGED_OUT'] . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect_url . '">', '</a>')); +				redirect(append_sid("{$phpbb_root_path}index.$phpEx"));  			}  			if (!confirm_box(true)) @@ -130,6 +124,11 @@ class acp_main  						set_config('record_online_users', 1, true);  						set_config('record_online_date', time(), true);  						add_log('admin', 'LOG_RESET_ONLINE'); + +						if ($request->is_ajax()) +						{ +							trigger_error('RESET_ONLINE_SUCCESS'); +						}  					break;  					case 'stats': @@ -140,14 +139,14 @@ class acp_main  						$sql = 'SELECT COUNT(post_id) AS stat  							FROM ' . POSTS_TABLE . ' -							WHERE post_approved = 1'; +							WHERE post_visibility = ' . ITEM_APPROVED;  						$result = $db->sql_query($sql);  						set_config('num_posts', (int) $db->sql_fetchfield('stat'), true);  						$db->sql_freeresult($result);  						$sql = 'SELECT COUNT(topic_id) AS stat  							FROM ' . TOPICS_TABLE . ' -							WHERE topic_approved = 1'; +							WHERE topic_visibility = ' . ITEM_APPROVED;  						$result = $db->sql_query($sql);  						set_config('num_topics', (int) $db->sql_fetchfield('stat'), true);  						$db->sql_freeresult($result); @@ -180,6 +179,11 @@ class acp_main  						update_last_username();  						add_log('admin', 'LOG_RESYNC_STATS'); + +						if ($request->is_ajax()) +						{ +							trigger_error('RESYNC_STATS_SUCCESS'); +						}  					break;  					case 'user': @@ -223,7 +227,7 @@ class acp_main  							$sql = 'SELECT COUNT(post_id) AS num_posts, poster_id  								FROM ' . POSTS_TABLE . '  								WHERE post_id BETWEEN ' . ($start + 1) . ' AND ' . ($start + $step) . ' -									AND post_postcount = 1 AND post_approved = 1 +									AND post_postcount = 1 AND post_visibility = ' . ITEM_APPROVED . '  								GROUP BY poster_id';  							$result = $db->sql_query($sql); @@ -243,6 +247,10 @@ class acp_main  						add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); +						if ($request->is_ajax()) +						{ +							trigger_error('RESYNC_POSTCOUNTS_SUCCESS'); +						}  					break;  					case 'date': @@ -253,13 +261,18 @@ class acp_main  						set_config('board_startdate', time() - 1);  						add_log('admin', 'LOG_RESET_DATE'); + +						if ($request->is_ajax()) +						{ +							trigger_error('RESET_DATE_SUCCESS'); +						}  					break;  					case 'db_track': -						switch ($db->sql_layer) +						switch ($db->get_sql_layer())  						{  							case 'sqlite': -							case 'firebird': +							case 'sqlite3':  								$db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE);  							break; @@ -328,22 +341,27 @@ class acp_main  						}  						add_log('admin', 'LOG_RESYNC_POST_MARKING'); -					break; -					case 'purge_cache': -						if ((int) $user->data['user_type'] !== USER_FOUNDER) +						if ($request->is_ajax())  						{ -							trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); +							trigger_error('RESYNC_POST_MARKING_SUCCESS');  						} +					break; -						global $cache; +					case 'purge_cache': +						$config->increment('assets_version', 1);  						$cache->purge();  						// Clear permissions  						$auth->acl_clear_prefetch(); -						cache_moderators(); +						phpbb_cache_moderators($db, $cache, $auth);  						add_log('admin', 'LOG_PURGE_CACHE'); + +						if ($request->is_ajax()) +						{ +							trigger_error('PURGE_CACHE_SUCCESS'); +						}  					break;  					case 'purge_sessions': @@ -356,10 +374,10 @@ class acp_main  						foreach ($tables as $table)  						{ -							switch ($db->sql_layer) +							switch ($db->get_sql_layer())  							{  								case 'sqlite': -								case 'firebird': +								case 'sqlite3':  									$db->sql_query("DELETE FROM $table");  								break; @@ -390,6 +408,11 @@ class acp_main  						$db->sql_query($sql);  						add_log('admin', 'LOG_PURGE_SESSIONS'); + +						if ($request->is_ajax()) +						{ +							trigger_error('PURGE_SESSIONS_SUCCESS'); +						}  					break;  				}  			} @@ -406,20 +429,30 @@ class acp_main  			));  		} -		$latest_version_info = false; -		if (($latest_version_info = obtain_latest_version_info(request_var('versioncheck_force', false))) === false) +		$version_helper = $phpbb_container->get('version_helper'); +		try  		{ -			$template->assign_var('S_VERSIONCHECK_FAIL', true); +			$recheck = $request->variable('versioncheck_force', false); +			$updates_available = $version_helper->get_suggested_updates($recheck); + +			$template->assign_var('S_VERSION_UP_TO_DATE', empty($updates_available));  		} -		else +		catch (\RuntimeException $e)  		{ -			$latest_version_info = explode("\n", $latest_version_info); -  			$template->assign_vars(array( -				'S_VERSION_UP_TO_DATE'	=> phpbb_version_compare(trim($latest_version_info[0]), $config['version'], '<='), +				'S_VERSIONCHECK_FAIL'		=> true, +				'VERSIONCHECK_FAIL_REASON'	=> ($e->getMessage() !== $user->lang('VERSIONCHECK_FAIL')) ? $e->getMessage() : '',  			));  		} +		/** +		* Notice admin +		* +		* @event core.acp_main_notice +		* @since 3.1.0-RC3 +		*/ +		$phpbb_dispatcher->dispatch('core.acp_main_notice'); +  		// Get forum statistics  		$total_posts = $config['num_posts'];  		$total_topics = $config['num_topics']; @@ -594,6 +627,22 @@ class acp_main  			$template->assign_var('S_REMOVE_INSTALL', true);  		} +		// Warn if no search index is created +		if ($config['num_posts'] && class_exists($config['search_type'])) +		{ +			$error = false; +			$search_type = $config['search_type']; +			$search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user); + +			if (!$search->index_created()) +			{ +				$template->assign_vars(array( +					'S_SEARCH_INDEX_MISSING'	=> true, +					'L_NO_SEARCH_INDEX'			=> $user->lang('NO_SEARCH_INDEX', $search->get_name(), '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=acp_search&mode=index') . '">', '</a>'), +				)); +			} +		} +  		if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx))  		{  			// World-Writable? (000x) @@ -621,5 +670,3 @@ class acp_main  		$this->page_title = 'ACP_MAIN';  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php index 75bc5766a9..ea6b388328 100644 --- a/phpBB/includes/acp/acp_modules.php +++ b/phpBB/includes/acp/acp_modules.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -26,9 +29,6 @@ if (!defined('IN_PHPBB'))  * - category disabled  */ -/** -* @package acp -*/  class acp_modules  {  	var $module_class = ''; @@ -37,7 +37,7 @@ class acp_modules  	function main($id, $mode)  	{ -		global $db, $user, $auth, $template, $module; +		global $db, $user, $auth, $template, $module, $request;  		global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx;  		// Set a global define for modules we might include (the author is able to prevent execution of code by checking this constant) @@ -111,7 +111,7 @@ class acp_modules  				}  			break; -			 +  			case 'enable':  			case 'disable':  				if (!$module_id) @@ -170,7 +170,15 @@ class acp_modules  					add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname']), $move_module_name);  					$this->remove_cache_file();  				} -		 + +				if ($request->is_ajax()) +				{ +					$json_response = new \phpbb\json_response; +					$json_response->send(array( +						'success'	=> ($move_module_name !== false), +					)); +				} +  			break;  			case 'quickadd': @@ -207,7 +215,7 @@ class acp_modules  						if (!sizeof($errors))  						{  							$this->remove_cache_file(); -	 +  							trigger_error($user->lang['MODULE_ADDED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id));  						}  					} @@ -231,7 +239,7 @@ class acp_modules  				{  					trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING);  				} -				 +  				$module_row = $this->get_module_row($module_id);  			// no break @@ -250,7 +258,7 @@ class acp_modules  						'module_auth'		=> '',  					);  				} -				 +  				$module_data = array();  				$module_data['module_basename'] = request_var('module_basename', (string) $module_row['module_basename']); @@ -295,7 +303,7 @@ class acp_modules  					if (!sizeof($errors))  					{  						$this->remove_cache_file(); -	 +  						trigger_error((($action == 'add') ? $user->lang['MODULE_ADDED'] : $user->lang['MODULE_EDITED']) . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id));  					}  				} @@ -316,7 +324,7 @@ class acp_modules  					}  					// Name options -					$s_name_options .= '<option value="' . $option . '"' . (($option == $module_data['module_basename']) ? ' selected="selected"' : '') . '>' . $this->lang_name($values['title']) . ' [' . $this->module_class . '_' . $option . ']</option>'; +					$s_name_options .= '<option value="' . $option . '"' . (($option == $module_data['module_basename']) ? ' selected="selected"' : '') . '>' . $this->lang_name($values['title']) . ' [' . $option . ']</option>';  					$template->assign_block_vars('m_names', array('NAME' => $option, 'A_NAME' => addslashes($option))); @@ -327,7 +335,7 @@ class acp_modules  						{  							$s_mode_options .= '<option value="' . $m_mode . '"' . (($m_mode == $module_data['module_mode']) ? ' selected="selected"' : '') . '>' . $this->lang_name($m_values['title']) . '</option>';  						} -						 +  						$template->assign_block_vars('m_names.modes', array(  							'OPTION'		=> $m_mode,  							'VALUE'			=> $this->lang_name($m_values['title']), @@ -336,7 +344,7 @@ class acp_modules  						);  					}  				} -				 +  				$s_cat_option = '<option value="0"' . (($module_data['parent_id'] == 0) ? ' selected="selected"' : '') . '>' . $user->lang['NO_PARENT'] . '</option>';  				$template->assign_vars(array_merge(array( @@ -349,7 +357,7 @@ class acp_modules  					'U_EDIT_ACTION'		=> $this->u_action . '&parent_id=' . $this->parent_id,  					'L_TITLE'			=> $user->lang[strtoupper($action) . '_MODULE'], -					 +  					'MODULENAME'		=> $this->lang_name($module_data['module_langname']),  					'ACTION'			=> $action,  					'MODULE_ID'			=> $module_id, @@ -374,6 +382,16 @@ class acp_modules  		// Default management page  		if (sizeof($errors))  		{ +			if ($request->is_ajax()) +			{ +				$json_response = new \phpbb\json_response; +				$json_response->send(array( +					'MESSAGE_TITLE'	=> $user->lang('ERROR'), +					'MESSAGE_TEXT'	=> implode('<br />', $errors), +					'SUCCESS'	=> false, +				)); +			} +  			$template->assign_vars(array(  				'S_ERROR'	=> true,  				'ERROR_MSG'	=> implode('<br />', $errors)) @@ -480,7 +498,7 @@ class acp_modules  		foreach ($module_infos as $option => $values)  		{  			// Name options -			$s_install_options .= '<optgroup label="' . $this->lang_name($values['title']) . ' [' . $this->module_class . '_' . $option . ']">'; +			$s_install_options .= '<optgroup label="' . $this->lang_name($values['title']) . ' [' . $option . ']">';  			// Build module modes  			foreach ($values['modes'] as $m_mode => $m_values) @@ -516,7 +534,7 @@ class acp_modules  		$result = $db->sql_query($sql);  		$row = $db->sql_fetchrow($result);  		$db->sql_freeresult($result); -		 +  		if (!$row)  		{  			trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); @@ -524,72 +542,79 @@ class acp_modules  		return $row;  	} -	 +  	/**  	* Get available module information from module files +	* +	* @param string $module +	* @param bool|string $module_class +	* @param bool $use_all_available Use all available instead of just all +	* 						enabled extensions +	* @return array  	*/ -	function get_module_infos($module = '', $module_class = false) +	function get_module_infos($module = '', $module_class = false, $use_all_available = false)  	{ -		global $phpbb_root_path, $phpEx; -		 +		global $phpbb_extension_manager, $phpbb_root_path, $phpEx; +  		$module_class = ($module_class === false) ? $this->module_class : $module_class;  		$directory = $phpbb_root_path . 'includes/' . $module_class . '/info/';  		$fileinfo = array(); -		if (!$module) -		{ -			$dh = @opendir($directory); +		$finder = $phpbb_extension_manager->get_finder($use_all_available); -			if (!$dh) +		$modules = $finder +			->extension_suffix('_module') +			->extension_directory("/$module_class") +			->core_path("includes/$module_class/info/") +			->core_prefix($module_class . '_') +			->get_classes(true); + +		foreach ($modules as $cur_module) +		{ +			// Skip entries we do not need if we know the module we are +			// looking for +			if ($module && strpos(str_replace('\\', '_', $cur_module), $module) === false && $module !== $cur_module)  			{ -				return $fileinfo; +				continue;  			} -			while (($file = readdir($dh)) !== false) -			{ -				// Is module? -				if (preg_match('/^' . $module_class . '_.+\.' . $phpEx . '$/', $file)) -				{ -					$class = str_replace(".$phpEx", '', $file) . '_info'; +			$info_class = preg_replace('/_module$/', '_info', $cur_module); -					if (!class_exists($class)) -					{ -						include($directory . $file); -					} +			// If the class does not exist it might be following the old +			// format. phpbb_acp_info_acp_foo needs to be turned into +			// acp_foo_info and the respective file has to be included +			// manually because it does not support auto loading +			$old_info_class_file = str_replace("phpbb_{$module_class}_info_", '', $cur_module); +			$old_info_class = $old_info_class_file . '_info'; -					// Get module title tag -					if (class_exists($class)) -					{ -						$c_class = new $class(); -						$module_info = $c_class->module(); -						$fileinfo[str_replace($module_class . '_', '', $module_info['filename'])] = $module_info; -					} -				} +			if (class_exists($old_info_class)) +			{ +				$info_class = $old_info_class;  			} -			closedir($dh); - -			ksort($fileinfo); -		} -		else -		{ -			$filename = $module_class . '_' . basename($module); -			$class = $module_class . '_' . basename($module) . '_info'; - -			if (!class_exists($class)) +			else if (!class_exists($info_class))  			{ -				include($directory . $filename . '.' . $phpEx); +				$info_class = $old_info_class; +				// need to check class exists again because previous checks triggered autoloading +				if (!class_exists($info_class) && file_exists($directory . $old_info_class_file . '.' . $phpEx)) +				{ +					include($directory . $old_info_class_file . '.' . $phpEx); +				}  			} -			// Get module title tag -			if (class_exists($class)) +			if (class_exists($info_class))  			{ -				$c_class = new $class(); -				$module_info = $c_class->module(); -				$fileinfo[str_replace($module_class . '_', '', $module_info['filename'])] = $module_info; +				$info = new $info_class(); +				$module_info = $info->module(); + +				$main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $cur_module; + +				$fileinfo[$main_class] = $module_info;  			}  		} -		 + +		ksort($fileinfo); +  		return $fileinfo;  	} @@ -717,15 +742,15 @@ class acp_modules  	*/  	function remove_cache_file()  	{ -		global $cache; +		global $phpbb_container;  		// Sanitise for future path use, it's escaped as appropriate for queries  		$p_class = str_replace(array('.', '/', '\\'), '', basename($this->module_class)); -		 -		$cache->destroy('_modules_' . $p_class); + +		$phpbb_container->get('cache.driver')->destroy('_modules_' . $p_class);  		// Additionally remove sql cache -		$cache->destroy('sql', MODULES_TABLE); +		$phpbb_container->get('cache.driver')->destroy('sql', MODULES_TABLE);  	}  	/** @@ -741,7 +766,8 @@ class acp_modules  	/**  	* Update/Add module  	* -	* @param bool $run_inline if set to true errors will be returned and no logs being written +	* @param array	&$module_data	The module data +	* @param bool	$run_inline 	if set to true errors will be returned and no logs being written  	*/  	function update_module_data(&$module_data, $run_inline = false)  	{ @@ -1061,5 +1087,3 @@ class acp_modules  		return $this->lang_name($target['module_langname']);  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php index 03ea5a39dd..cd3616208d 100644 --- a/phpBB/includes/acp/acp_permission_roles.php +++ b/phpBB/includes/acp/acp_permission_roles.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,22 +19,21 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_permission_roles  {  	var $u_action; +	protected $auth_admin;  	function main($id, $mode)  	{ -		global $db, $user, $auth, $template, $cache; +		global $db, $user, $auth, $template, $cache, $phpbb_container;  		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; +		global $request;  		include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);  		include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); -		$auth_admin = new auth_admin(); +		$this->auth_admin = new auth_admin();  		$user->add_lang('acp/permissions');  		add_permission_language(); @@ -46,6 +48,11 @@ class acp_permission_roles  		$form_name = 'acp_permissions';  		add_form_key($form_name); +		if (!$role_id && in_array($action, array('remove', 'edit', 'move_up', 'move_down'))) +		{ +			trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); +		} +  		switch ($mode)  		{  			case 'admin_roles': @@ -85,11 +92,6 @@ class acp_permission_roles  			{  				case 'remove': -					if (!$role_id) -					{ -						trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); -					} -  					$sql = 'SELECT *  						FROM ' . ACL_ROLES_TABLE . '  						WHERE role_id = ' . $role_id; @@ -123,10 +125,6 @@ class acp_permission_roles  				break;  				case 'edit': -					if (!$role_id) -					{ -						trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); -					}  					// Get role we edit  					$sql = 'SELECT * @@ -211,7 +209,7 @@ class acp_permission_roles  					}  					// Now add the auth settings -					$auth_admin->acl_set_role($role_id, $auth_settings); +					$this->auth_admin->acl_set_role($role_id, $auth_settings);  					$role_name = (!empty($user->lang[$role_name])) ? $user->lang[$role_name] : $role_name;  					add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_' . strtoupper($action), $role_name); @@ -255,7 +253,7 @@ class acp_permission_roles  				{  					$sql = 'SELECT auth_option_id, auth_option  						FROM ' . ACL_OPTIONS_TABLE . " -						WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char) . " +						WHERE auth_option " . $db->sql_like_expression($permission_type . $db->get_any_char()) . "  							AND auth_option <> '{$permission_type}'  						ORDER BY auth_option_id";  					$result = $db->sql_query($sql); @@ -274,11 +272,6 @@ class acp_permission_roles  				if ($action == 'edit')  				{ -					if (!$role_id) -					{ -						trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); -					} -					  					$sql = 'SELECT *  						FROM ' . ACL_ROLES_TABLE . '  						WHERE role_id = ' . $role_id; @@ -306,6 +299,8 @@ class acp_permission_roles  					trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);  				} +				$phpbb_permissions = $phpbb_container->get('acl.permissions'); +  				$template->assign_vars(array(  					'S_EDIT'			=> true, @@ -314,14 +309,13 @@ class acp_permission_roles  					'ROLE_NAME'			=> $role_row['role_name'],  					'ROLE_DESCRIPTION'	=> $role_row['role_description'], -					'L_ACL_TYPE'		=> $user->lang['ACL_TYPE_' . strtoupper($permission_type)], -					) -				); +					'L_ACL_TYPE'		=> $phpbb_permissions->get_type_lang($permission_type), +				));  				// We need to fill the auth options array with ACL_NO options ;)  				$sql = 'SELECT auth_option_id, auth_option  					FROM ' . ACL_OPTIONS_TABLE . " -					WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char) . " +					WHERE auth_option " . $db->sql_like_expression($permission_type . $db->get_any_char()) . "  						AND auth_option <> '{$permission_type}'  					ORDER BY auth_option_id";  				$result = $db->sql_query($sql); @@ -344,7 +338,7 @@ class acp_permission_roles  				// Get users/groups/forums using this preset...  				if ($action == 'edit')  				{ -					$hold_ary = $auth_admin->get_role_mask($role_id); +					$hold_ary = $this->auth_admin->get_role_mask($role_id);  					if (sizeof($hold_ary))  					{ @@ -355,7 +349,7 @@ class acp_permission_roles  							'L_ROLE_ASSIGNED_TO'	=> sprintf($user->lang['ROLE_ASSIGNED_TO'], $role_name))  						); -						$auth_admin->display_role_mask($hold_ary); +						$this->auth_admin->display_role_mask($hold_ary);  					}  				} @@ -365,7 +359,18 @@ class acp_permission_roles  			case 'move_up':  			case 'move_down': -				$order = request_var('order', 0); +				$sql = 'SELECT role_order +					FROM ' . ACL_ROLES_TABLE . " +					WHERE role_id = $role_id"; +				$result = $db->sql_query($sql); +				$order = $db->sql_fetchfield('role_order'); +				$db->sql_freeresult($result); + +				if ($order === false || ($order == 0 && $action == 'move_up')) +				{ +					break; +				} +				$order = (int) $order;  				$order_total = $order * 2 + (($action == 'move_up') ? -1 : 1);  				$sql = 'UPDATE ' . ACL_ROLES_TABLE . ' @@ -374,6 +379,14 @@ class acp_permission_roles  						AND role_order IN ($order, " . (($action == 'move_up') ? $order - 1 : $order + 1) . ')';  				$db->sql_query($sql); +				if ($request->is_ajax()) +				{ +					$json_response = new \phpbb\json_response; +					$json_response->send(array( +						'success'	=> (bool) $db->sql_affectedrows(), +					)); +				} +  			break;  		} @@ -420,8 +433,8 @@ class acp_permission_roles  				'U_EDIT'			=> $this->u_action . '&action=edit&role_id=' . $row['role_id'],  				'U_REMOVE'			=> $this->u_action . '&action=remove&role_id=' . $row['role_id'], -				'U_MOVE_UP'			=> $this->u_action . '&action=move_up&order=' . $row['role_order'], -				'U_MOVE_DOWN'		=> $this->u_action . '&action=move_down&order=' . $row['role_order'], +				'U_MOVE_UP'			=> $this->u_action . '&action=move_up&role_id=' . $row['role_id'], +				'U_MOVE_DOWN'		=> $this->u_action . '&action=move_down&role_id=' . $row['role_id'],  				'U_DISPLAY_ITEMS'	=> ($row['role_id'] == $display_item) ? '' : $this->u_action . '&display_item=' . $row['role_id'] . '#assigned_to')  			); @@ -446,8 +459,8 @@ class acp_permission_roles  				'S_DISPLAY_ROLE_MASK'	=> true)  			); -			$hold_ary = $auth_admin->get_role_mask($display_item); -			$auth_admin->display_role_mask($hold_ary); +			$hold_ary = $this->auth_admin->get_role_mask($display_item); +			$this->auth_admin->display_role_mask($hold_ary);  		}  	} @@ -456,14 +469,16 @@ class acp_permission_roles  	*/  	function display_auth_options($auth_options)  	{ -		global $template, $user; +		global $template, $user, $phpbb_container; + +		$phpbb_permissions = $phpbb_container->get('acl.permissions');  		$content_array = $categories = array();  		$key_sort_array = array(0);  		$auth_options = array(0 => $auth_options);  		// Making use of auth_admin method here (we do not really want to change two similar code fragments) -		auth_admin::build_permission_array($auth_options, $content_array, $categories, $key_sort_array); +		$this->auth_admin->build_permission_array($auth_options, $content_array, $categories, $key_sort_array);  		$content_array = $content_array[0]; @@ -473,7 +488,7 @@ class acp_permission_roles  		foreach ($content_array as $cat => $cat_array)  		{  			$template->assign_block_vars('auth', array( -				'CAT_NAME'	=> $user->lang['permission_cat'][$cat], +				'CAT_NAME'	=> $phpbb_permissions->get_category_lang($cat),  				'S_YES'		=> ($cat_array['S_YES'] && !$cat_array['S_NEVER'] && !$cat_array['S_NO']) ? true : false,  				'S_NEVER'	=> ($cat_array['S_NEVER'] && !$cat_array['S_YES'] && !$cat_array['S_NO']) ? true : false, @@ -488,8 +503,8 @@ class acp_permission_roles  					'S_NO'		=> ($allowed == ACL_NO) ? true : false,  					'FIELD_NAME'	=> $permission, -					'PERMISSION'	=> $user->lang['acl_' . $permission]['lang']) -				); +					'PERMISSION'	=> $phpbb_permissions->get_permission_lang($permission), +				));  			}  		}  	} @@ -501,12 +516,10 @@ class acp_permission_roles  	{  		global $db; -		$auth_admin = new auth_admin(); -  		// Get complete auth array  		$sql = 'SELECT auth_option, auth_option_id  			FROM ' . ACL_OPTIONS_TABLE . " -			WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char); +			WHERE auth_option " . $db->sql_like_expression($permission_type . $db->get_any_char());  		$result = $db->sql_query($sql);  		$auth_settings = array(); @@ -530,19 +543,19 @@ class acp_permission_roles  		$db->sql_freeresult($result);  		// Get role assignments -		$hold_ary = $auth_admin->get_role_mask($role_id); +		$hold_ary = $this->auth_admin->get_role_mask($role_id);  		// Re-assign permissions  		foreach ($hold_ary as $forum_id => $forum_ary)  		{  			if (isset($forum_ary['users']))  			{ -				$auth_admin->acl_set('user', $forum_id, $forum_ary['users'], $auth_settings, 0, false); +				$this->auth_admin->acl_set('user', $forum_id, $forum_ary['users'], $auth_settings, 0, false);  			}  			if (isset($forum_ary['groups']))  			{ -				$auth_admin->acl_set('group', $forum_id, $forum_ary['groups'], $auth_settings, 0, false); +				$this->auth_admin->acl_set('group', $forum_id, $forum_ary['groups'], $auth_settings, 0, false);  			}  		} @@ -564,8 +577,6 @@ class acp_permission_roles  			WHERE role_id = ' . $role_id;  		$db->sql_query($sql); -		$auth_admin->acl_clear_prefetch(); +		$this->auth_admin->acl_clear_prefetch();  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index e9f0af5071..cb408e304f 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,22 +19,22 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_permissions  {  	var $u_action;  	var $permission_dropdown; +	protected $permissions;  	function main($id, $mode)  	{ -		global $db, $user, $auth, $template, $cache; +		global $db, $user, $auth, $template, $cache, $phpbb_container;  		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;  		include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);  		include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); +		$this->permissions = $phpbb_container->get('acl.permissions'); +  		$auth_admin = new auth_admin();  		$user->add_lang('acp/permissions'); @@ -50,7 +53,7 @@ class acp_permissions  			if ($user_id && isset($auth_admin->acl_options['id'][$permission]) && $auth->acl_get('a_viewauth'))  			{ -				$this->page_title = sprintf($user->lang['TRACE_PERMISSION'], $user->lang['acl_' . $permission]['lang']); +				$this->page_title = sprintf($user->lang['TRACE_PERMISSION'], $this->permissions->get_permission_lang($permission));  				$this->permission_trace($user_id, $forum_id, $permission);  				return;  			} @@ -328,15 +331,6 @@ class acp_permissions  			}  		} - -		// Setting permissions screen -		$s_hidden_fields = build_hidden_fields(array( -			'user_id'		=> $user_id, -			'group_id'		=> $group_id, -			'forum_id'		=> $forum_id, -			'type'			=> $permission_type) -		); -  		// Go through the screens/options needed and present them in correct order  		foreach ($permission_victim as $victim)  		{ @@ -469,6 +463,14 @@ class acp_permissions  			// If there are more than 5 forums selected the admin is not able to select all users/groups too.  			// We need to see if the number of forums can be increased or need to be decreased. +			// Setting permissions screen +			$s_hidden_fields = build_hidden_fields(array( +					'user_id'		=> $user_id, +					'group_id'		=> $group_id, +					'forum_id'		=> $forum_id, +					'type'			=> $permission_type, +			)); +  			$template->assign_vars(array(  				'U_ACTION'				=> $this->u_action,  				'ANONYMOUS_USER_ID'		=> ANONYMOUS, @@ -498,13 +500,21 @@ class acp_permissions  				$template->assign_vars(array(  					'S_FORUM_NAMES'		=> (sizeof($forum_names)) ? true : false, -					'FORUM_NAMES'		=> implode(', ', $forum_names)) +					'FORUM_NAMES'		=> implode($user->lang['COMMA_SEPARATOR'], $forum_names))  				);  			}  			return;  		} +		// Setting permissions screen +		$s_hidden_fields = build_hidden_fields(array( +				'user_id'		=> $user_id, +				'group_id'		=> $group_id, +				'forum_id'		=> $forum_id, +				'type'			=> $permission_type, +		)); +  		// Do not allow forum_ids being set and no other setting defined (will bog down the server too much)  		if (sizeof($forum_id) && !sizeof($user_id) && !sizeof($group_id))  		{ @@ -513,7 +523,7 @@ class acp_permissions  		$template->assign_vars(array(  			'S_PERMISSION_DROPDOWN'		=> (sizeof($this->permission_dropdown) > 1) ? $this->build_permission_dropdown($this->permission_dropdown, $permission_type, $permission_scope) : false, -			'L_PERMISSION_TYPE'			=> $user->lang['ACL_TYPE_' . strtoupper($permission_type)], +			'L_PERMISSION_TYPE'			=> $this->permissions->get_type_lang($permission_type),  			'U_ACTION'					=> $this->u_action,  			'S_HIDDEN_FIELDS'			=> $s_hidden_fields) @@ -588,7 +598,7 @@ class acp_permissions  	*/  	function build_permission_dropdown($options, $default_option, $permission_scope)  	{ -		global $user, $auth; +		global $auth;  		$s_dropdown_options = '';  		foreach ($options as $setting) @@ -599,7 +609,7 @@ class acp_permissions  			}  			$selected = ($setting == $default_option) ? ' selected="selected"' : ''; -			$l_setting = (isset($user->lang['permission_type'][$permission_scope][$setting])) ? $user->lang['permission_type'][$permission_scope][$setting] : $user->lang['permission_type'][$setting]; +			$l_setting = $this->permissions->get_type_lang($setting, $permission_scope);  			$s_dropdown_options .= '<option value="' . $setting . '"' . $selected . '>' . $l_setting . '</option>';  		} @@ -657,7 +667,8 @@ class acp_permissions  	*/  	function set_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id)  	{ -		global $user, $auth; +		global $db, $cache, $user, $auth; +		global $request;  		$psubmit = request_var('psubmit', array(0 => array(0 => 0))); @@ -676,18 +687,17 @@ class acp_permissions  		list($ug_id, ) = each($psubmit);  		list($forum_id, ) = each($psubmit[$ug_id]); -		if (empty($_POST['setting']) || empty($_POST['setting'][$ug_id]) || empty($_POST['setting'][$ug_id][$forum_id]) || !is_array($_POST['setting'][$ug_id][$forum_id])) +		$settings = $request->variable('setting', array(0 => array(0 => array('' => 0))), false, \phpbb\request\request_interface::POST); +		if (empty($settings) || empty($settings[$ug_id]) || empty($settings[$ug_id][$forum_id]))  		{  			trigger_error('WRONG_PERMISSION_SETTING_FORMAT', E_USER_WARNING);  		} -		// We obtain and check $_POST['setting'][$ug_id][$forum_id] directly and not using request_var() because request_var() -		// currently does not support the amount of dimensions required. ;) -		//		$auth_settings = request_var('setting', array(0 => array(0 => array('' => 0)))); -		$auth_settings = array_map('intval', $_POST['setting'][$ug_id][$forum_id]); +		$auth_settings = $settings[$ug_id][$forum_id];  		// Do we have a role we want to set? -		$assigned_role = (isset($_POST['role'][$ug_id][$forum_id])) ? (int) $_POST['role'][$ug_id][$forum_id] : 0; +		$roles = $request->variable('role', array(0 => array(0 => 0)), false, \phpbb\request\request_interface::POST); +		$assigned_role = (isset($roles[$ug_id][$forum_id])) ? (int) $roles[$ug_id][$forum_id] : 0;  		// Do the admin want to set these permissions to other items too?  		$inherit = request_var('inherit', array(0 => array(0))); @@ -727,13 +737,13 @@ class acp_permissions  		// Do we need to recache the moderator lists?  		if ($permission_type == 'm_')  		{ -			cache_moderators(); +			phpbb_cache_moderators($db, $cache, $auth);  		}  		// Remove users who are now moderators or admins from everyones foes list  		if ($permission_type == 'm_' || $permission_type == 'a_')  		{ -			update_foes($group_id, $user_id); +			phpbb_update_foes($db, $auth, $group_id, $user_id);  		}  		$this->log_action($mode, 'add', $permission_type, $ug_type, $ug_id, $forum_id); @@ -746,7 +756,8 @@ class acp_permissions  	*/  	function set_all_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id)  	{ -		global $user, $auth; +		global $db, $cache, $user, $auth; +		global $request;  		// User or group to be set?  		$ug_type = (sizeof($user_id)) ? 'user' : 'group'; @@ -757,8 +768,8 @@ class acp_permissions  			trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);  		} -		$auth_settings = (isset($_POST['setting'])) ? $_POST['setting'] : array(); -		$auth_roles = (isset($_POST['role'])) ? $_POST['role'] : array(); +		$auth_settings = $request->variable('setting', array(0 => array(0 => array('' => 0))), false, \phpbb\request\request_interface::POST); +		$auth_roles = $request->variable('role', array(0 => array(0 => 0)), false, \phpbb\request\request_interface::POST);  		$ug_ids = $forum_ids = array();  		// We need to go through the auth settings @@ -794,13 +805,13 @@ class acp_permissions  		// Do we need to recache the moderator lists?  		if ($permission_type == 'm_')  		{ -			cache_moderators(); +			phpbb_cache_moderators($db, $cache, $auth);  		}  		// Remove users who are now moderators or admins from everyones foes list  		if ($permission_type == 'm_' || $permission_type == 'a_')  		{ -			update_foes($group_id, $user_id); +			phpbb_update_foes($db, $auth, $group_id, $user_id);  		}  		$this->log_action($mode, 'add', $permission_type, $ug_type, $ug_ids, $forum_ids); @@ -858,7 +869,7 @@ class acp_permissions  	*/  	function remove_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id, &$forum_id)  	{ -		global $user, $db, $auth; +		global $user, $db, $cache, $auth;  		// User or group to be set?  		$ug_type = (sizeof($user_id)) ? 'user' : 'group'; @@ -874,7 +885,7 @@ class acp_permissions  		// Do we need to recache the moderator lists?  		if ($permission_type == 'm_')  		{ -			cache_moderators(); +			phpbb_cache_moderators($db, $cache, $auth);  		}  		$this->log_action($mode, 'del', $permission_type, $ug_type, (($ug_type == 'user') ? $user_id : $group_id), (sizeof($forum_id) ? $forum_id : array(0 => 0))); @@ -952,12 +963,7 @@ class acp_permissions  		if ($user_id != $user->data['user_id'])  		{ -			$sql = 'SELECT user_id, username, user_permissions, user_type -				FROM ' . USERS_TABLE . ' -				WHERE user_id = ' . $user_id; -			$result = $db->sql_query($sql); -			$userdata = $db->sql_fetchrow($result); -			$db->sql_freeresult($result); +			$userdata = $auth->obtain_user_data($user_id);  		}  		else  		{ @@ -984,7 +990,7 @@ class acp_permissions  		$back = request_var('back', 0);  		$template->assign_vars(array( -			'PERMISSION'			=> $user->lang['acl_' . $permission]['lang'], +			'PERMISSION'			=> $this->permissions->get_permission_lang($permission),  			'PERMISSION_USERNAME'	=> $userdata['username'],  			'FORUM_NAME'			=> $forum_name, @@ -1105,7 +1111,7 @@ class acp_permissions  		{  			if ($user_id != $user->data['user_id'])  			{ -				$auth2 = new auth(); +				$auth2 = new \phpbb\auth\auth();  				$auth2->acl($userdata);  				$auth_setting = $auth2->acl_get($permission);  			} @@ -1172,7 +1178,7 @@ class acp_permissions  	*/  	function copy_forum_permissions()  	{ -		global $auth, $cache, $template, $user; +		global $db, $auth, $cache, $template, $user;  		$user->add_lang('acp/forums'); @@ -1187,7 +1193,7 @@ class acp_permissions  			{  				if (copy_forum_permissions($src, $dest))  				{ -					cache_moderators(); +					phpbb_cache_moderators($db, $cache, $auth);  					$auth->acl_clear_prefetch();  					$cache->destroy('sql', FORUMS_TABLE); @@ -1232,7 +1238,7 @@ class acp_permissions  		$sql = 'SELECT auth_option_id  			FROM ' . ACL_OPTIONS_TABLE . ' -			WHERE auth_option ' . $db->sql_like_expression($permission_type . $db->any_char); +			WHERE auth_option ' . $db->sql_like_expression($permission_type . $db->get_any_char());  		$result = $db->sql_query($sql);  		while ($row = $db->sql_fetchrow($result)) @@ -1311,5 +1317,3 @@ class acp_permissions  		);  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_php_info.php b/phpBB/includes/acp/acp_php_info.php index 88e2ac3f8d..810a111edb 100644 --- a/phpBB/includes/acp/acp_php_info.php +++ b/phpBB/includes/acp/acp_php_info.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_php_info  {  	var $u_action; @@ -82,11 +82,9 @@ class acp_php_info  		$template->assign_var('PHPINFO', $output);  	} -	 +  	function remove_spaces($matches)  	{  		return '<a name="' . str_replace(' ', '_', $matches[1]) . '">';  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index 19223847f0..046281596c 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,45 +19,40 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_profile  {  	var $u_action;  	var $edit_lang_id;  	var $lang_defs; +	protected $type_collection;  	function main($id, $mode)  	{  		global $config, $db, $user, $auth, $template, $cache;  		global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; +		global $request, $phpbb_container;  		include($phpbb_root_path . 'includes/functions_posting.' . $phpEx);  		include($phpbb_root_path . 'includes/functions_user.' . $phpEx); -		include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx);  		$user->add_lang(array('ucp', 'acp/profile'));  		$this->tpl_name = 'acp_profile';  		$this->page_title = 'ACP_CUSTOM_PROFILE_FIELDS'; +		$field_id = $request->variable('field_id', 0);  		$action = (isset($_POST['create'])) ? 'create' : request_var('action', '');  		$error = array();  		$s_hidden_fields = ''; -		// Define some default values for each field type -		$default_values = array( -			FIELD_STRING	=> array('field_length' => 10, 'field_minlen' => 0, 'field_maxlen' => 20, 'field_validation' => '.*', 'field_novalue' => '', 'field_default_value' => ''), -			FIELD_TEXT		=> array('field_length' => '5|80', 'field_minlen' => 0, 'field_maxlen' => 1000, 'field_validation' => '.*', 'field_novalue' => '', 'field_default_value' => ''), -			FIELD_INT		=> array('field_length' => 5, 'field_minlen' => 0, 'field_maxlen' => 100, 'field_validation' => '', 'field_novalue' => 0, 'field_default_value' => 0), -			FIELD_DATE		=> array('field_length' => 10, 'field_minlen' => 10, 'field_maxlen' => 10, 'field_validation' => '', 'field_novalue' => ' 0- 0-   0', 'field_default_value' => ' 0- 0-   0'), -			FIELD_BOOL		=> array('field_length' => 1, 'field_minlen' => 0, 'field_maxlen' => 0, 'field_validation' => '', 'field_novalue' => 0, 'field_default_value' => 0), -			FIELD_DROPDOWN	=> array('field_length' => 0, 'field_minlen' => 0, 'field_maxlen' => 5, 'field_validation' => '', 'field_novalue' => 0, 'field_default_value' => 0), -		); +		if (!$field_id && in_array($action, array('delete','activate', 'deactivate', 'move_up', 'move_down', 'edit'))) +		{ +			trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); +		} -		$cp = new custom_profile_admin(); +		$cp = $phpbb_container->get('profilefields.manager'); +		$this->type_collection = $phpbb_container->get('profilefields.type_collection');  		// Build Language array  		// Based on this, we decide which elements need to be edited later and which language items are missing @@ -88,22 +86,16 @@ class acp_profile  		// Have some fields been defined?  		if (isset($this->lang_defs['entry']))  		{ -			foreach ($this->lang_defs['entry'] as $field_id => $field_ary) +			foreach ($this->lang_defs['entry'] as $field_ident => $field_ary)  			{  				// Fill an array with the languages that are missing for each field -				$this->lang_defs['diff'][$field_id] = array_diff(array_values($this->lang_defs['iso']), $field_ary); +				$this->lang_defs['diff'][$field_ident] = array_diff(array_values($this->lang_defs['iso']), $field_ary);  			}  		}  		switch ($action)  		{  			case 'delete': -				$field_id = request_var('field_id', 0); - -				if (!$field_id) -				{ -					trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); -				}  				if (confirm_box(true))  				{ @@ -120,57 +112,8 @@ class acp_profile  					$db->sql_query('DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " WHERE field_id = $field_id");  					$db->sql_query('DELETE FROM ' . PROFILE_LANG_TABLE . " WHERE field_id = $field_id"); -					switch ($db->sql_layer) -					{ -						case 'sqlite': -							$sql = "SELECT sql -								FROM sqlite_master -								WHERE type = 'table' -									AND name = '" . PROFILE_FIELDS_DATA_TABLE . "' -								ORDER BY type DESC, name;"; -							$result = $db->sql_query($sql); -							$row = $db->sql_fetchrow($result); -							$db->sql_freeresult($result); - -							// Create a temp table and populate it, destroy the existing one -							$db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . PROFILE_FIELDS_DATA_TABLE . '"?#i', 'CREATE TEMPORARY TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp', $row['sql'])); -							$db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . '_temp SELECT * FROM ' . PROFILE_FIELDS_DATA_TABLE); -							$db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE); - -							preg_match('#\((.*)\)#s', $row['sql'], $matches); - -							$new_table_cols = trim($matches[1]); -							$old_table_cols = preg_split('/,(?=[\\sa-z])/im', $new_table_cols); -							$column_list = array(); - -							foreach ($old_table_cols as $declaration) -							{ -								$entities = preg_split('#\s+#', trim($declaration)); - -								if ($entities[0] == 'PRIMARY') -								{ -									continue; -								} - -								if ($entities[0] !== 'pf_' . $field_ident) -								{ -									$column_list[] = $entities[0]; -								} -							} - -							$columns = implode(',', $column_list); - -							$new_table_cols = preg_replace('/' . 'pf_' . $field_ident . '[^,]+,/', '', $new_table_cols); - -							// create a new table and fill it up. destroy the temp one -							$db->sql_query('CREATE TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $new_table_cols . ');'); -							$db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . PROFILE_FIELDS_DATA_TABLE . '_temp;'); -							$db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp'); -						break; - -						default: -							$db->sql_query('ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " DROP COLUMN pf_$field_ident"); -					} +					$db_tools = $phpbb_container->get('dbal.tools'); +					$db_tools->sql_column_remove(PROFILE_FIELDS_DATA_TABLE, 'pf_' . $field_ident);  					$order = 0; @@ -210,12 +153,6 @@ class acp_profile  			break;  			case 'activate': -				$field_id = request_var('field_id', 0); - -				if (!$field_id) -				{ -					trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); -				}  				$sql = 'SELECT lang_id  					FROM ' . LANG_TABLE . " @@ -242,17 +179,20 @@ class acp_profile  				$db->sql_freeresult($result);  				add_log('admin', 'LOG_PROFILE_FIELD_ACTIVATE', $field_ident); + +				if ($request->is_ajax()) +				{ +					$json_response = new \phpbb\json_response(); +					$json_response->send(array( +						'text'	=> $user->lang('DEACTIVATE'), +					)); +				} +  				trigger_error($user->lang['PROFILE_FIELD_ACTIVATED'] . adm_back_link($this->u_action));  			break;  			case 'deactivate': -				$field_id = request_var('field_id', 0); - -				if (!$field_id) -				{ -					trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); -				}  				$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . "  					SET field_active = 0 @@ -266,14 +206,35 @@ class acp_profile  				$field_ident = (string) $db->sql_fetchfield('field_ident');  				$db->sql_freeresult($result); +				if ($request->is_ajax()) +				{ +					$json_response = new \phpbb\json_response(); +					$json_response->send(array( +						'text'	=> $user->lang('ACTIVATE'), +					)); +				} +  				add_log('admin', 'LOG_PROFILE_FIELD_DEACTIVATE', $field_ident); +  				trigger_error($user->lang['PROFILE_FIELD_DEACTIVATED'] . adm_back_link($this->u_action));  			break;  			case 'move_up':  			case 'move_down': -				$field_order = request_var('order', 0); + +				$sql = 'SELECT field_order +					FROM ' . PROFILE_FIELDS_TABLE . " +					WHERE field_id = $field_id"; +				$result = $db->sql_query($sql); +				$field_order = $db->sql_fetchfield('field_order'); +				$db->sql_freeresult($result); + +				if ($field_order === false || ($field_order == 0 && $action == 'move_up')) +				{ +					break; +				} +				$field_order = (int) $field_order;  				$order_total = $field_order * 2 + (($action == 'move_up') ? -1 : 1);  				$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . " @@ -281,12 +242,19 @@ class acp_profile  					WHERE field_order IN ($field_order, " . (($action == 'move_up') ? $field_order - 1 : $field_order + 1) . ')';  				$db->sql_query($sql); +				if ($request->is_ajax()) +				{ +					$json_response = new \phpbb\json_response; +					$json_response->send(array( +						'success'	=> (bool) $db->sql_affectedrows(), +					)); +				} +  			break;  			case 'create':  			case 'edit': -				$field_id = request_var('field_id', 0);  				$step = request_var('step', 1);  				$submit = (isset($_REQUEST['next']) || isset($_REQUEST['prev'])) ? true : false; @@ -298,11 +266,6 @@ class acp_profile  				// We are editing... we need to grab basic things  				if ($action == 'edit')  				{ -					if (!$field_id) -					{ -						trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); -					} -  					$sql = 'SELECT l.*, f.*  						FROM ' . PROFILE_LANG_TABLE . ' l, ' . PROFILE_FIELDS_TABLE . ' f  						WHERE l.lang_id = ' . $this->edit_lang_id . " @@ -332,6 +295,7 @@ class acp_profile  						$this->edit_lang_id = $field_row['lang_id'];  					}  					$field_type = $field_row['field_type']; +					$profile_field = $this->type_collection[$field_type];  					// Get language entries  					$sql = 'SELECT * @@ -355,14 +319,15 @@ class acp_profile  					// We are adding a new field, define basic params  					$lang_options = $field_row = array(); -					$field_type = request_var('field_type', 0); +					$field_type = request_var('field_type', ''); -					if (!$field_type) +					if (!isset($this->type_collection[$field_type]))  					{  						trigger_error($user->lang['NO_FIELD_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING);  					} -					$field_row = array_merge($default_values[$field_type], array( +					$profile_field = $this->type_collection[$field_type]; +					$field_row = array_merge($profile_field->get_default_option_values(), array(  						'field_ident'		=> str_replace(' ', '_', utf8_clean_string(request_var('field_ident', '', true))),  						'field_required'	=> 0,  						'field_show_novalue'=> 0, @@ -370,7 +335,12 @@ class acp_profile  						'field_show_profile'=> 0,  						'field_no_view'		=> 0,  						'field_show_on_reg'	=> 0, +						'field_show_on_pm'	=> 0,  						'field_show_on_vt'	=> 0, +						'field_show_on_ml'	=> 0, +						'field_is_contact'	=> 0, +						'field_contact_desc'=> '', +						'field_contact_url'	=> '',  						'lang_name'			=> utf8_normalize_nfc(request_var('field_ident', '', true)),  						'lang_explain'		=> '',  						'lang_default_value'=> '') @@ -381,55 +351,40 @@ class acp_profile  				// $exclude contains the data we gather in each step  				$exclude = array( -					1	=> array('field_ident', 'lang_name', 'lang_explain', 'field_option_none', 'field_show_on_reg', 'field_show_on_vt', 'field_required', 'field_show_novalue', 'field_hide', 'field_show_profile', 'field_no_view'), +					1	=> array('field_ident', 'lang_name', 'lang_explain', 'field_option_none', 'field_show_on_reg', 'field_show_on_pm', 'field_show_on_vt', 'field_show_on_ml', 'field_required', 'field_show_novalue', 'field_hide', 'field_show_profile', 'field_no_view', 'field_is_contact', 'field_contact_desc', 'field_contact_url'),  					2	=> array('field_length', 'field_maxlen', 'field_minlen', 'field_validation', 'field_novalue', 'field_default_value'),  					3	=> array('l_lang_name', 'l_lang_explain', 'l_lang_default_value', 'l_lang_options')  				); -				// Text-based fields require the lang_default_value to be excluded -				if ($field_type == FIELD_STRING || $field_type == FIELD_TEXT) -				{ -					$exclude[1][] = 'lang_default_value'; -				} - -				// option-specific fields require lang_options to be excluded -				if ($field_type == FIELD_BOOL || $field_type == FIELD_DROPDOWN) -				{ -					$exclude[1][] = 'lang_options'; -				} - -				$cp->vars['field_ident']		= ($action == 'create' && $step == 1) ? utf8_clean_string(request_var('field_ident', $field_row['field_ident'], true)) : request_var('field_ident', $field_row['field_ident']); -				$cp->vars['lang_name']			= utf8_normalize_nfc(request_var('lang_name', $field_row['lang_name'], true)); -				$cp->vars['lang_explain']		= utf8_normalize_nfc(request_var('lang_explain', $field_row['lang_explain'], true)); -				$cp->vars['lang_default_value']	= utf8_normalize_nfc(request_var('lang_default_value', $field_row['lang_default_value'], true)); -  				// Visibility Options...  				$visibility_ary = array(  					'field_required',  					'field_show_novalue',  					'field_show_on_reg', +					'field_show_on_pm',  					'field_show_on_vt', +					'field_show_on_ml',  					'field_show_profile',  					'field_hide', +					'field_is_contact',  				); -				foreach ($visibility_ary as $val) -				{ -					$cp->vars[$val] = ($submit || $save) ? request_var($val, 0) : $field_row[$val]; -				} +				$options = $profile_field->prepare_options_form($exclude, $visibility_ary); -				$cp->vars['field_no_view'] = request_var('field_no_view', (int) $field_row['field_no_view']); +				$cp->vars['field_ident']		= ($action == 'create' && $step == 1) ? utf8_clean_string(request_var('field_ident', $field_row['field_ident'], true)) : request_var('field_ident', $field_row['field_ident']); +				$cp->vars['lang_name']			= $request->variable('lang_name', $field_row['lang_name'], true); +				$cp->vars['lang_explain']		= $request->variable('lang_explain', $field_row['lang_explain'], true); +				$cp->vars['lang_default_value']	= $request->variable('lang_default_value', $field_row['lang_default_value'], true); +				$cp->vars['field_contact_desc']	= $request->variable('field_contact_desc', $field_row['field_contact_desc'], true); +				$cp->vars['field_contact_url']	= $request->variable('field_contact_url', $field_row['field_contact_url'], true); -				// A boolean field expects an array as the lang options -				if ($field_type == FIELD_BOOL) -				{ -					$options = utf8_normalize_nfc(request_var('lang_options', array(''), true)); -				} -				else +				foreach ($visibility_ary as $val)  				{ -					$options = utf8_normalize_nfc(request_var('lang_options', '', true)); +					$cp->vars[$val] = ($submit || $save) ? $request->variable($val, 0) : $field_row[$val];  				} +				$cp->vars['field_no_view'] = $request->variable('field_no_view', (int) $field_row['field_no_view']); +  				// If the user has submitted a form with options (i.e. dropdown field)  				if ($options)  				{ @@ -457,91 +412,9 @@ class acp_profile  				{  					$var = utf8_normalize_nfc(request_var($key, $field_row[$key], true)); -					// Manipulate the intended variables a little bit if needed -					if ($field_type == FIELD_DROPDOWN && $key == 'field_maxlen') -					{ -						// Get the number of options if this key is 'field_maxlen' -						$var = sizeof(explode("\n", utf8_normalize_nfc(request_var('lang_options', '', true)))); -					} -					else if ($field_type == FIELD_TEXT && $key == 'field_length') -					{ -						if (isset($_REQUEST['rows'])) -						{ -							$cp->vars['rows'] = request_var('rows', 0); -							$cp->vars['columns'] = request_var('columns', 0); -							$var = $cp->vars['rows'] . '|' . $cp->vars['columns']; -						} -						else -						{ -							$row_col = explode('|', $var); -							$cp->vars['rows'] = $row_col[0]; -							$cp->vars['columns'] = $row_col[1]; -						} -					} -					else if ($field_type == FIELD_DATE && $key == 'field_default_value') -					{ -						$always_now = request_var('always_now', -1); - -						if ($always_now == 1 || ($always_now === -1 && $var == 'now')) -						{ -							$now = getdate(); - -							$cp->vars['field_default_value_day'] = $now['mday']; -							$cp->vars['field_default_value_month'] = $now['mon']; -							$cp->vars['field_default_value_year'] = $now['year']; -							$var = $_POST['field_default_value'] = 'now'; -						} -						else -						{ -							if (isset($_REQUEST['field_default_value_day'])) -							{ -								$cp->vars['field_default_value_day'] = request_var('field_default_value_day', 0); -								$cp->vars['field_default_value_month'] = request_var('field_default_value_month', 0); -								$cp->vars['field_default_value_year'] = request_var('field_default_value_year', 0); -								$var = $_POST['field_default_value'] = sprintf('%2d-%2d-%4d', $cp->vars['field_default_value_day'], $cp->vars['field_default_value_month'], $cp->vars['field_default_value_year']); -							} -							else -							{ -								list($cp->vars['field_default_value_day'], $cp->vars['field_default_value_month'], $cp->vars['field_default_value_year']) = explode('-', $var); -							} -						} -					} -					else if ($field_type == FIELD_BOOL && $key == 'field_default_value') -					{ -						// 'field_length' == 1 defines radio buttons. Possible values are 1 or 2 only. -						// 'field_length' == 2 defines checkbox. Possible values are 0 or 1 only. -						// If we switch the type on step 2, we have to adjust field value. -						// 1 is a common value for the checkbox and radio buttons. - -						// Adjust unchecked checkbox value. -						// If we return or save settings from 2nd/3rd page -						// and the checkbox is unchecked, set the value to 0. -						if (isset($_REQUEST['step']) && !isset($_REQUEST[$key])) -						{ -							$var = 0; -						} - -						// If we switch to the checkbox type but former radio buttons value was 2, -						// which is not the case for the checkbox, set it to 0 (unchecked). -						if ($cp->vars['field_length'] == 2 && $var == 2) -						{ -							$var = 0; -						} -						// If we switch to the radio buttons but the former checkbox value was 0, -						// which is not the case for the radio buttons, set it to 0. -						else if ($cp->vars['field_length'] == 1 && $var == 0) -						{ -							$var = 2; -						} -					} -					else if ($field_type == FIELD_INT && $key == 'field_default_value') -					{ -						// Permit an empty string -						if ($action == 'create' && request_var('field_default_value', '') === '') -						{ -							$var = ''; -						} -					} +					$field_data = $cp->vars; +					$var = $profile_field->get_excluded_options($key, $action, $var, $field_data, 2); +					$cp->vars = $field_data;  					$cp->vars[$key] = $var;  				} @@ -564,7 +437,6 @@ class acp_profile  					}  					$db->sql_freeresult($result); -  					$sql = 'SELECT lang_id, lang_name, lang_explain, lang_default_value  						FROM ' . PROFILE_LANG_TABLE . '  						WHERE lang_id <> ' . $this->edit_lang_id . " @@ -590,18 +462,10 @@ class acp_profile  					{  						$cp->vars[$key] = $$key;  					} -					else if ($key == 'l_lang_options' && $field_type == FIELD_BOOL) -					{ -						$cp->vars[$key] = utf8_normalize_nfc(request_var($key, array(0 => array('')), true)); -					} -					else if ($key == 'l_lang_options' && is_array($cp->vars[$key])) -					{ -						foreach ($cp->vars[$key] as $lang_id => $options) -						{ -							$cp->vars[$key][$lang_id] = explode("\n", $options); -						} -					} +					$field_data = $cp->vars; +					$var = $profile_field->get_excluded_options($key, $action, $var, $field_data, 3); +					$cp->vars = $field_data;  				}  				// Check for general issues in every step @@ -628,15 +492,7 @@ class acp_profile  						$error[] = $user->lang['EMPTY_USER_FIELD_NAME'];  					} -					if ($field_type == FIELD_DROPDOWN && !sizeof($cp->vars['lang_options'])) -					{ -						$error[] = $user->lang['NO_FIELD_ENTRIES']; -					} - -					if ($field_type == FIELD_BOOL && (empty($cp->vars['lang_options'][0]) || empty($cp->vars['lang_options'][1]))) -					{ -						$error[] = $user->lang['NO_FIELD_ENTRIES']; -					} +					$error = $profile_field->validate_options_on_submit($error, $cp->vars);  					// Check for already existing field ident  					if ($action != 'edit') @@ -673,54 +529,16 @@ class acp_profile  					$_new_key_ary = array(); +					$field_data = $cp->vars;  					foreach ($key_ary as $key)  					{ -						if ($field_type == FIELD_TEXT && $key == 'field_length' && isset($_REQUEST['rows'])) +						$var = $profile_field->prepare_hidden_fields($step, $key, $action, $field_data); +						if ($var !== null)  						{ -							$cp->vars['rows'] = request_var('rows', 0); -							$cp->vars['columns'] = request_var('columns', 0); -							$_new_key_ary[$key] = $cp->vars['rows'] . '|' . $cp->vars['columns']; -						} -						else if ($field_type == FIELD_DATE && $key == 'field_default_value') -						{ -							$always_now = request_var('always_now', 0); - -							if ($always_now) -							{ -								$_new_key_ary[$key] = 'now'; -							} -							else if (isset($_REQUEST['field_default_value_day'])) -							{ -								$cp->vars['field_default_value_day'] = request_var('field_default_value_day', 0); -								$cp->vars['field_default_value_month'] = request_var('field_default_value_month', 0); -								$cp->vars['field_default_value_year'] = request_var('field_default_value_year', 0); -								$_new_key_ary[$key]  = sprintf('%2d-%2d-%4d', $cp->vars['field_default_value_day'], $cp->vars['field_default_value_month'], $cp->vars['field_default_value_year']); -							} -						} -						else if ($field_type == FIELD_BOOL && $key == 'l_lang_options' && isset($_REQUEST['l_lang_options'])) -						{ -							$_new_key_ary[$key] = utf8_normalize_nfc(request_var($key, array(array('')), true)); -						} -						else if ($field_type == FIELD_BOOL && $key == 'field_default_value') -						{ -							$_new_key_ary[$key] =  request_var($key, $cp->vars[$key]); -						} -						else -						{ -							if (!isset($_REQUEST[$key])) -							{ -								$var = false; -							} -							else if ($key == 'field_ident' && isset($cp->vars[$key])) -							{ -								$_new_key_ary[$key]= $cp->vars[$key]; -							} -							else -							{ -								$_new_key_ary[$key] = (is_array($_REQUEST[$key])) ? utf8_normalize_nfc(request_var($key, array(''), true)) : utf8_normalize_nfc(request_var($key, '', true)); -							} +							$_new_key_ary[$key] = $profile_field->prepare_hidden_fields($step, $key, $action, $field_data);  						}  					} +					$cp->vars = $field_data;  					$s_hidden_fields .= build_hidden_fields($_new_key_ary);  				} @@ -754,66 +572,34 @@ class acp_profile  				{  					// Create basic options - only small differences between field types  					case 1: - -						// Build common create options -						$template->assign_vars(array( +						$template_vars = array(  							'S_STEP_ONE'		=> true,  							'S_FIELD_REQUIRED'	=> ($cp->vars['field_required']) ? true : false,  							'S_FIELD_SHOW_NOVALUE'=> ($cp->vars['field_show_novalue']) ? true : false,  							'S_SHOW_ON_REG'		=> ($cp->vars['field_show_on_reg']) ? true : false, +							'S_SHOW_ON_PM'		=> ($cp->vars['field_show_on_pm']) ? true : false,  							'S_SHOW_ON_VT'		=> ($cp->vars['field_show_on_vt']) ? true : false, +							'S_SHOW_ON_MEMBERLIST'=> ($cp->vars['field_show_on_ml']) ? true : false,  							'S_FIELD_HIDE'		=> ($cp->vars['field_hide']) ? true : false,  							'S_SHOW_PROFILE'	=> ($cp->vars['field_show_profile']) ? true : false,  							'S_FIELD_NO_VIEW'	=> ($cp->vars['field_no_view']) ? true : false, +							'S_FIELD_CONTACT'	=> $cp->vars['field_is_contact'], +							'FIELD_CONTACT_DESC'=> $cp->vars['field_contact_desc'], +							'FIELD_CONTACT_URL'	=> $cp->vars['field_contact_url'],  							'L_LANG_SPECIFIC'	=> sprintf($user->lang['LANG_SPECIFIC_OPTIONS'], $config['default_lang']), -							'FIELD_TYPE'		=> $user->lang['FIELD_' . strtoupper($cp->profile_types[$field_type])], +							'FIELD_TYPE'		=> $profile_field->get_name(),  							'FIELD_IDENT'		=> $cp->vars['field_ident'],  							'LANG_NAME'			=> $cp->vars['lang_name'], -							'LANG_EXPLAIN'		=> $cp->vars['lang_explain']) +							'LANG_EXPLAIN'		=> $cp->vars['lang_explain'],  						); -						// String and Text needs to set default values here... -						if ($field_type == FIELD_STRING || $field_type == FIELD_TEXT) -						{ -							$template->assign_vars(array( -								'S_TEXT'		=> ($field_type == FIELD_TEXT) ? true : false, -								'S_STRING'		=> ($field_type == FIELD_STRING) ? true : false, - -								'L_DEFAULT_VALUE_EXPLAIN'	=> $user->lang[strtoupper($cp->profile_types[$field_type]) . '_DEFAULT_VALUE_EXPLAIN'], -								'LANG_DEFAULT_VALUE'		=> $cp->vars['lang_default_value']) -							); -						} - -						if ($field_type == FIELD_BOOL || $field_type == FIELD_DROPDOWN) -						{ -							// Initialize these array elements if we are creating a new field -							if (!sizeof($cp->vars['lang_options'])) -							{ -								if ($field_type == FIELD_BOOL) -								{ -									// No options have been defined for a boolean field. -									$cp->vars['lang_options'][0] = ''; -									$cp->vars['lang_options'][1] = ''; -								} -								else -								{ -									// No options have been defined for the dropdown menu -									$cp->vars['lang_options'] = array(); -								} -							} - -							$template->assign_vars(array( -								'S_BOOL'		=> ($field_type == FIELD_BOOL) ? true : false, -								'S_DROPDOWN'	=> ($field_type == FIELD_DROPDOWN) ? true : false, - -								'L_LANG_OPTIONS_EXPLAIN'	=> $user->lang[strtoupper($cp->profile_types[$field_type]) . '_ENTRIES_EXPLAIN'], -								'LANG_OPTIONS'				=> ($field_type == FIELD_DROPDOWN) ? implode("\n", $cp->vars['lang_options']) : '', -								'FIRST_LANG_OPTION'			=> ($field_type == FIELD_BOOL) ? $cp->vars['lang_options'][0] : '', -								'SECOND_LANG_OPTION'		=> ($field_type == FIELD_BOOL) ? $cp->vars['lang_options'][1] : '') -							); -						} +						$field_data = $cp->vars; +						$profile_field->display_options($template_vars, $field_data); +						$cp->vars = $field_data; +						// Build common create options +						$template->assign_vars($template_vars);  					break;  					case 2: @@ -824,8 +610,7 @@ class acp_profile  						);  						// Build options based on profile type -						$function = 'get_' . $cp->profile_types[$field_type] . '_options'; -						$options = $cp->$function(); +						$options = $profile_field->get_options($this->lang_defs['iso'][$config['default_lang']], $cp->vars);  						foreach ($options as $num => $option_ary)  						{ @@ -887,17 +672,18 @@ class acp_profile  				$s_one_need_edit = true;  			} +			$profile_field = $this->type_collection[$row['field_type']];  			$template->assign_block_vars('fields', array(  				'FIELD_IDENT'		=> $row['field_ident'], -				'FIELD_TYPE'		=> $user->lang['FIELD_' . strtoupper($cp->profile_types[$row['field_type']])], +				'FIELD_TYPE'		=> $profile_field->get_name(),  				'L_ACTIVATE_DEACTIVATE'		=> $user->lang[$active_lang],  				'U_ACTIVATE_DEACTIVATE'		=> $this->u_action . "&action=$active_value&field_id=$id",  				'U_EDIT'					=> $this->u_action . "&action=edit&field_id=$id",  				'U_TRANSLATE'				=> $this->u_action . "&action=edit&field_id=$id&step=3",  				'U_DELETE'					=> $this->u_action . "&action=delete&field_id=$id", -				'U_MOVE_UP'					=> $this->u_action . "&action=move_up&order={$row['field_order']}", -				'U_MOVE_DOWN'				=> $this->u_action . "&action=move_down&order={$row['field_order']}", +				'U_MOVE_UP'					=> $this->u_action . "&action=move_up&field_id=$id", +				'U_MOVE_DOWN'				=> $this->u_action . "&action=move_down&field_id=$id",  				'S_NEED_EDIT'				=> $s_need_edit)  			); @@ -911,15 +697,15 @@ class acp_profile  		}  		$s_select_type = ''; -		foreach ($cp->profile_types as $key => $value) +		foreach ($this->type_collection as $key => $profile_field)  		{ -			$s_select_type .= '<option value="' . $key . '">' . $user->lang['FIELD_' . strtoupper($value)] . '</option>'; +			$s_select_type .= '<option value="' . $key . '">' . $profile_field->get_name() . '</option>';  		}  		$template->assign_vars(array(  			'U_ACTION'			=> $this->u_action, -			'S_TYPE_OPTIONS'	=> $s_select_type) -		); +			'S_TYPE_OPTIONS'	=> $s_select_type, +		));  	}  	/** @@ -927,7 +713,7 @@ class acp_profile  	*/  	function build_language_options(&$cp, $field_type, $action = 'create')  	{ -		global $user, $config, $db; +		global $user, $config, $db, $phpbb_container;  		$default_lang_id = (!empty($this->edit_lang_id)) ? $this->edit_lang_id : $this->lang_defs['iso'][$config['default_lang']]; @@ -944,31 +730,8 @@ class acp_profile  		}  		$db->sql_freeresult($result); -		$options = array(); -		$options['lang_name'] = 'string'; -		if ($cp->vars['lang_explain']) -		{ -			$options['lang_explain'] = 'text'; -		} - -		switch ($field_type) -		{ -			case FIELD_BOOL: -				$options['lang_options'] = 'two_options'; -			break; - -			case FIELD_DROPDOWN: -				$options['lang_options'] = 'optionfield'; -			break; - -			case FIELD_TEXT: -			case FIELD_STRING: -				if (strlen($cp->vars['lang_default_value'])) -				{ -					$options['lang_default_value'] = ($field_type == FIELD_STRING) ? 'string' : 'text'; -				} -			break; -		} +		$profile_field = $this->type_collection[$field_type]; +		$options = $profile_field->get_language_options($cp->vars);  		$lang_options = array(); @@ -1047,7 +810,7 @@ class acp_profile  	*/  	function save_profile_field(&$cp, $field_type, $action = 'create')  	{ -		global $db, $config, $user; +		global $db, $config, $user, $phpbb_container;  		$field_id = request_var('field_id', 0); @@ -1078,10 +841,15 @@ class acp_profile  			'field_required'		=> $cp->vars['field_required'],  			'field_show_novalue'	=> $cp->vars['field_show_novalue'],  			'field_show_on_reg'		=> $cp->vars['field_show_on_reg'], +			'field_show_on_pm'		=> $cp->vars['field_show_on_pm'],  			'field_show_on_vt'		=> $cp->vars['field_show_on_vt'], +			'field_show_on_ml'		=> $cp->vars['field_show_on_ml'],  			'field_hide'			=> $cp->vars['field_hide'],  			'field_show_profile'	=> $cp->vars['field_show_profile'], -			'field_no_view'			=> $cp->vars['field_no_view'] +			'field_no_view'			=> $cp->vars['field_no_view'], +			'field_is_contact'		=> $cp->vars['field_is_contact'], +			'field_contact_desc'	=> $cp->vars['field_contact_desc'], +			'field_contact_url'		=> $cp->vars['field_contact_url'],  		);  		if ($action == 'create') @@ -1107,10 +875,14 @@ class acp_profile  			$db->sql_query($sql);  		} +		$profile_field = $this->type_collection[$field_type]; +  		if ($action == 'create')  		{  			$field_ident = 'pf_' . $field_ident; -			$profile_sql[] = $this->add_field_ident($field_ident, $field_type); + +			$db_tools = $phpbb_container->get('dbal.tools'); +			$db_tools->sql_column_add(PROFILE_FIELDS_DATA_TABLE, $field_ident, array($profile_field->get_database_column_type(), null));  		}  		$sql_ary = array( @@ -1164,23 +936,7 @@ class acp_profile  			}  		} -		// These are always arrays because the key is the language id... -		$cp->vars['l_lang_name']			= utf8_normalize_nfc(request_var('l_lang_name', array(0 => ''), true)); -		$cp->vars['l_lang_explain']			= utf8_normalize_nfc(request_var('l_lang_explain', array(0 => ''), true)); -		$cp->vars['l_lang_default_value']	= utf8_normalize_nfc(request_var('l_lang_default_value', array(0 => ''), true)); - -		if ($field_type != FIELD_BOOL) -		{ -			$cp->vars['l_lang_options']			= utf8_normalize_nfc(request_var('l_lang_options', array(0 => ''), true)); -		} -		else -		{ -			/** -			* @todo check if this line is correct... -			$cp->vars['l_lang_default_value']	= request_var('l_lang_default_value', array(0 => array('')), true); -			*/ -			$cp->vars['l_lang_options']	= utf8_normalize_nfc(request_var('l_lang_options', array(0 => array('')), true)); -		} +		$cp->vars = $profile_field->get_language_options_input($cp->vars);  		if ($cp->vars['lang_options'])  		{ @@ -1200,7 +956,7 @@ class acp_profile  			foreach ($cp->vars['lang_options'] as $option_id => $value)  			{  				$sql_ary = array( -					'field_type'	=> (int) $field_type, +					'field_type'	=> $field_type,  					'lang_value'	=> $value  				); @@ -1255,7 +1011,7 @@ class acp_profile  							'field_id'		=> (int) $field_id,  							'lang_id'		=> (int) $lang_id,  							'option_id'		=> (int) $option_id, -							'field_type'	=> (int) $field_type, +							'field_type'	=> $field_type,  							'lang_value'	=> $value  						);  					} @@ -1309,7 +1065,6 @@ class acp_profile  			}  		} -  		$db->sql_transaction('begin');  		if ($action == 'create') @@ -1381,277 +1136,4 @@ class acp_profile  			}  		}  	} - -	/** -	* Return sql statement for adding a new field ident (profile field) to the profile fields data table -	*/ -	function add_field_ident($field_ident, $field_type) -	{ -		global $db; - -		switch ($db->sql_layer) -		{ -			case 'mysql': -			case 'mysql4': -			case 'mysqli': - -				// We are defining the biggest common value, because of the possibility to edit the min/max values of each field. -				$sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD `$field_ident` "; - -				switch ($field_type) -				{ -					case FIELD_STRING: -						$sql .= ' VARCHAR(255) '; -					break; - -					case FIELD_DATE: -						$sql .= 'VARCHAR(10) '; -					break; - -					case FIELD_TEXT: -						$sql .= "TEXT"; -		//						ADD {$field_ident}_bbcode_uid VARCHAR(5) NOT NULL, -		//						ADD {$field_ident}_bbcode_bitfield INT(11) UNSIGNED"; -					break; - -					case FIELD_BOOL: -						$sql .= 'TINYINT(2) '; -					break; - -					case FIELD_DROPDOWN: -						$sql .= 'MEDIUMINT(8) '; -					break; - -					case FIELD_INT: -						$sql .= 'BIGINT(20) '; -					break; -				} - -			break; - -			case 'sqlite': - -				switch ($field_type) -				{ -					case FIELD_STRING: -						$type = ' VARCHAR(255) '; -					break; - -					case FIELD_DATE: -						$type = 'VARCHAR(10) '; -					break; - -					case FIELD_TEXT: -						$type = "TEXT(65535)"; -		//						ADD {$field_ident}_bbcode_uid VARCHAR(5) NOT NULL, -		//						ADD {$field_ident}_bbcode_bitfield INT(11) UNSIGNED"; -					break; - -					case FIELD_BOOL: -						$type = 'TINYINT(2) '; -					break; - -					case FIELD_DROPDOWN: -						$type = 'MEDIUMINT(8) '; -					break; - -					case FIELD_INT: -						$type = 'BIGINT(20) '; -					break; -				} - -				// We are defining the biggest common value, because of the possibility to edit the min/max values of each field. -				if (version_compare(sqlite_libversion(), '3.0') == -1) -				{ -					$sql = "SELECT sql -						FROM sqlite_master -						WHERE type = 'table' -							AND name = '" . PROFILE_FIELDS_DATA_TABLE . "' -						ORDER BY type DESC, name;"; -					$result = $db->sql_query($sql); -					$row = $db->sql_fetchrow($result); -					$db->sql_freeresult($result); - -					// Create a temp table and populate it, destroy the existing one -					$db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . PROFILE_FIELDS_DATA_TABLE . '"?#i', 'CREATE TEMPORARY TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp', $row['sql'])); -					$db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . '_temp SELECT * FROM ' . PROFILE_FIELDS_DATA_TABLE); -					$db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE); - -					preg_match('#\((.*)\)#s', $row['sql'], $matches); - -					$new_table_cols = trim($matches[1]); -					$old_table_cols = explode(',', $new_table_cols); -					$column_list = array(); - -					foreach ($old_table_cols as $declaration) -					{ -						$entities = preg_split('#\s+#', trim($declaration)); -						if ($entities[0] == 'PRIMARY') -						{ -							continue; -						} -						$column_list[] = $entities[0]; -					} - -					$columns = implode(',', $column_list); - -					$new_table_cols = $field_ident . ' ' . $type . ',' . $new_table_cols; - -					// create a new table and fill it up. destroy the temp one -					$db->sql_query('CREATE TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $new_table_cols . ');'); -					$db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . PROFILE_FIELDS_DATA_TABLE . '_temp;'); -					$db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp'); -				} -				else -				{ -					$sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD $field_ident [$type]"; -				} - -			break; - -			case 'mssql': -			case 'mssql_odbc': -			case 'mssqlnative': - -				// We are defining the biggest common value, because of the possibility to edit the min/max values of each field. -				$sql = 'ALTER TABLE [' . PROFILE_FIELDS_DATA_TABLE . "] ADD [$field_ident] "; - -				switch ($field_type) -				{ -					case FIELD_STRING: -						$sql .= ' [VARCHAR] (255) '; -					break; - -					case FIELD_DATE: -						$sql .= '[VARCHAR] (10) '; -					break; - -					case FIELD_TEXT: -						$sql .= "[TEXT]"; -		//						ADD {$field_ident}_bbcode_uid [VARCHAR] (5) NOT NULL, -		//						ADD {$field_ident}_bbcode_bitfield [INT] UNSIGNED"; -					break; - -					case FIELD_BOOL: -					case FIELD_DROPDOWN: -						$sql .= '[INT] '; -					break; - -					case FIELD_INT: -						$sql .= '[FLOAT] '; -					break; -				} - -			break; - -			case 'postgres': - -				// We are defining the biggest common value, because of the possibility to edit the min/max values of each field. -				$sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD COLUMN \"$field_ident\" "; - -				switch ($field_type) -				{ -					case FIELD_STRING: -						$sql .= ' VARCHAR(255) '; -					break; - -					case FIELD_DATE: -						$sql .= 'VARCHAR(10) '; -					break; - -					case FIELD_TEXT: -						$sql .= "TEXT"; -		//						ADD {$field_ident}_bbcode_uid VARCHAR(5) NOT NULL, -		//						ADD {$field_ident}_bbcode_bitfield INT4 UNSIGNED"; -					break; - -					case FIELD_BOOL: -						$sql .= 'INT2 '; -					break; - -					case FIELD_DROPDOWN: -						$sql .= 'INT4 '; -					break; - -					case FIELD_INT: -						$sql .= 'INT8 '; -					break; -				} - -			break; - -			case 'firebird': - -				// We are defining the biggest common value, because of the possibility to edit the min/max values of each field. -				$sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' ADD "' . strtoupper($field_ident) . '" '; - -				switch ($field_type) -				{ -					case FIELD_STRING: -						$sql .= ' VARCHAR(255) '; -					break; - -					case FIELD_DATE: -						$sql .= 'VARCHAR(10) '; -					break; - -					case FIELD_TEXT: -						$sql .= "BLOB SUB_TYPE TEXT"; -		//						ADD {$field_ident}_bbcode_uid VARCHAR(5) NOT NULL, -		//						ADD {$field_ident}_bbcode_bitfield INTEGER UNSIGNED"; -					break; - -					case FIELD_BOOL: -					case FIELD_DROPDOWN: -						$sql .= 'INTEGER '; -					break; - -					case FIELD_INT: -						$sql .= 'DOUBLE PRECISION '; -					break; -				} - -			break; - -			case 'oracle': - -				// We are defining the biggest common value, because of the possibility to edit the min/max values of each field. -				$sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD $field_ident "; - -				switch ($field_type) -				{ -					case FIELD_STRING: -						$sql .= ' VARCHAR2(255) '; -					break; - -					case FIELD_DATE: -						$sql .= 'VARCHAR2(10) '; -					break; - -					case FIELD_TEXT: -						$sql .= "CLOB"; -		//						ADD {$field_ident}_bbcode_uid VARCHAR2(5) NOT NULL, -		//						ADD {$field_ident}_bbcode_bitfield NUMBER(11) UNSIGNED"; -					break; - -					case FIELD_BOOL: -						$sql .= 'NUMBER(2) '; -					break; - -					case FIELD_DROPDOWN: -						$sql .= 'NUMBER(8) '; -					break; - -					case FIELD_INT: -						$sql .= 'NUMBER(20) '; -					break; -				} - -			break; -		} - -		return $sql; -	}  } - -?> diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php index ffe20f86f5..a10b248324 100644 --- a/phpBB/includes/acp/acp_prune.php +++ b/phpBB/includes/acp/acp_prune.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_prune  {  	var $u_action; @@ -80,7 +80,7 @@ class acp_prune  				$prune_posted = request_var('prune_days', 0);  				$prune_viewed = request_var('prune_vieweddays', 0);  				$prune_all = (!$prune_posted && !$prune_viewed) ? true : false; -		 +  				$prune_flags = 0;  				$prune_flags += (request_var('prune_old_polls', 0)) ? 2 : 0;  				$prune_flags += (request_var('prune_announce', 0)) ? 4 : 0; @@ -110,7 +110,7 @@ class acp_prune  					$p_result['topics'] = 0;  					$p_result['posts'] = 0;  					$log_data = ''; -			 +  					do  					{  						if (!$auth->acl_get('f_list', $row['forum_id'])) @@ -130,7 +130,7 @@ class acp_prune  								$p_result['topics'] += $return['topics'];  								$p_result['posts'] += $return['posts'];  							} -			 +  							if ($prune_viewed)  							{  								$return = prune($row['forum_id'], 'viewed', $prunedate_viewed, $prune_flags, false); @@ -146,11 +146,11 @@ class acp_prune  							'NUM_TOPICS'	=> $p_result['topics'],  							'NUM_POSTS'		=> $p_result['posts'])  						); -		 +  						$log_data .= (($log_data != '') ? ', ' : '') . $row['forum_name'];  					}  					while ($row = $db->sql_fetchrow($result)); -		 +  					// Sync all pruned forums at once  					sync('forum', 'forum_id', $prune_ids, true, true);  					add_log('admin', 'LOG_PRUNE', $log_data); @@ -243,8 +243,8 @@ class acp_prune  			if (confirm_box(true))  			{  				$user_ids = $usernames = array(); -				$this->get_prune_users($user_ids, $usernames); +				$this->get_prune_users($user_ids, $usernames);  				if (sizeof($user_ids))  				{  					if ($action == 'deactivate') @@ -256,19 +256,13 @@ class acp_prune  					{  						if ($deleteposts)  						{ -							foreach ($user_ids as $user_id) -							{ -								user_delete('remove', $user_id); -							} -							 +							user_delete('remove', $user_ids); +  							$l_log = 'LOG_PRUNE_USER_DEL_DEL';  						}  						else  						{ -							foreach ($user_ids as $user_id) -							{ -								user_delete('retain', $user_id, $usernames[$user_id]); -							} +							user_delete('retain', $user_ids, true);  							$l_log = 'LOG_PRUNE_USER_DEL_ANON';  						} @@ -300,7 +294,8 @@ class acp_prune  				{  					$template->assign_block_vars('users', array(  						'USERNAME'			=> $usernames[$user_id], -						'U_PROFILE'			=> append_sid($phpbb_root_path . 'memberlist.' . $phpEx, 'mode=viewprofile&u=' . $user_id), +						'USER_ID'           => $user_id, +						'U_PROFILE'			=> get_username_string('profile', $user_id, $usernames[$user_id]),  						'U_USER_ADMIN'		=> ($auth->acl_get('a_user')) ? append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview&u=' . $user_id, true, $user->session_id) : '',  					));  				} @@ -315,17 +310,7 @@ class acp_prune  					'mode'			=> $mode,  					'prune'			=> 1, -					'users'			=> utf8_normalize_nfc(request_var('users', '', true)), -					'username'		=> utf8_normalize_nfc(request_var('username', '', true)), -					'email'			=> request_var('email', ''), -					'joined_select'	=> request_var('joined_select', ''), -					'joined'		=> request_var('joined', ''), -					'active_select'	=> request_var('active_select', ''), -					'active'		=> request_var('active', ''), -					'count_select'	=> request_var('count_select', ''), -					'count'			=> request_var('count', ''),  					'deleteposts'	=> request_var('deleteposts', 0), -  					'action'		=> request_var('action', ''),  				)), 'confirm_body_prune.html');  			} @@ -341,22 +326,36 @@ class acp_prune  		}  		$find_time = array('lt' => $user->lang['BEFORE'], 'gt' => $user->lang['AFTER']); -		$s_find_join_time = ''; -		foreach ($find_time as $key => $value) -		{ -			$s_find_join_time .= '<option value="' . $key . '">' . $value . '</option>'; -		} -		  		$s_find_active_time = '';  		foreach ($find_time as $key => $value)  		{  			$s_find_active_time .= '<option value="' . $key . '">' . $value . '</option>';  		} +		$sql = 'SELECT group_id, group_name +			FROM ' . GROUPS_TABLE . ' +			WHERE group_type <> ' . GROUP_SPECIAL . ' +			ORDER BY group_name ASC'; +		$result = $db->sql_query($sql); + +		$s_group_list = ''; +		while ($row = $db->sql_fetchrow($result)) +		{ +			$s_group_list .= '<option value="' . $row['group_id'] . '">' . $row['group_name'] . '</option>'; +		} +		$db->sql_freeresult($result); + +		if ($s_group_list) +		{ +			// Only prepend the "All groups" option if there are groups, +			// otherwise we don't want to display this option at all. +			$s_group_list = '<option value="0">' . $user->lang['PRUNE_USERS_GROUP_NONE'] . '</option>' . $s_group_list; +		} +  		$template->assign_vars(array(  			'U_ACTION'			=> $this->u_action, -			'S_JOINED_OPTIONS'	=> $s_find_join_time,  			'S_ACTIVE_OPTIONS'	=> $s_find_active_time, +			'S_GROUP_LIST'		=> $s_group_list,  			'S_COUNT_OPTIONS'	=> $s_find_count,  			'U_FIND_USERNAME'	=> append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=acp_prune&field=users'),  		)); @@ -367,50 +366,86 @@ class acp_prune  	*/  	function get_prune_users(&$user_ids, &$usernames)  	{ -		global $user, $db; +		global $user, $db, $request; -		$users = utf8_normalize_nfc(request_var('users', '', true)); -		 -		if ($users) +		$users_by_name = request_var('users', '', true); +		$users_by_id = request_var('user_ids', array(0)); +		$group_id = request_var('group_id', 0); +		$posts_on_queue = (trim($request->variable('posts_on_queue', '')) === '') ? false : $request->variable('posts_on_queue', 0); + +		if ($users_by_name)  		{ -			$users = explode("\n", $users); +			$users = explode("\n", $users_by_name);  			$where_sql = ' AND ' . $db->sql_in_set('username_clean', array_map('utf8_clean_string', $users));  		} +		else if (!empty($users_by_id)) +		{ +			$user_ids = $users_by_id; +			user_get_id_name($user_ids, $usernames); + +			$where_sql = ' AND ' . $db->sql_in_set('user_id', $user_ids); +		}  		else  		{ -			$username = utf8_normalize_nfc(request_var('username', '', true)); +			$username = request_var('username', '', true);  			$email = request_var('email', ''); -			$joined_select = request_var('joined_select', 'lt');  			$active_select = request_var('active_select', 'lt');  			$count_select = request_var('count_select', 'eq'); -			$joined = request_var('joined', ''); +			$queue_select = request_var('queue_select', 'gt'); +			$joined_before = request_var('joined_before', ''); +			$joined_after = request_var('joined_after', '');  			$active = request_var('active', ''); +			$count = request_var('count', 0); +  			$active = ($active) ? explode('-', $active) : array(); -			$joined = ($joined) ? explode('-', $joined) : array(); +			$joined_before = ($joined_before) ? explode('-', $joined_before) : array(); +			$joined_after = ($joined_after) ? explode('-', $joined_after) : array(); -			if ((sizeof($active) && sizeof($active) != 3) || (sizeof($joined) && sizeof($joined) != 3)) +			// calculate the conditions required by the join time criteria +			$joined_sql = ''; +			if (!empty($joined_before) && !empty($joined_after))  			{ -				trigger_error($user->lang['WRONG_ACTIVE_JOINED_DATE'] . adm_back_link($this->u_action), E_USER_WARNING); +				// if the two entered dates are equal, we need to adjust +				// so that our time range is a full day instead of 1 second +				if ($joined_after == $joined_before) +				{ +					$joined_after[2] += 1; +				} + +				$joined_sql = ' AND user_regdate BETWEEN ' . gmmktime(0, 0, 0, (int) $joined_after[1], (int) $joined_after[2], (int) $joined_after[0]) . +					' AND ' . gmmktime(0, 0, 0, (int) $joined_before[1], (int) $joined_before[2], (int) $joined_before[0]); +			} +			else if (empty($joined_before) && !empty($joined_after)) +			{ +				$joined_sql = ' AND user_regdate > ' . gmmktime(0, 0, 0, (int) $joined_after[1], (int) $joined_after[2], (int) $joined_after[0]); +			} +			else if (empty($joined_after) && !empty($joined_before)) +			{ +				$joined_sql = ' AND user_regdate < ' . gmmktime(0, 0, 0, (int) $joined_before[1], (int) $joined_before[2], (int) $joined_before[0]);  			} +			// implicit else when both arrays are empty do nothing -			$count = request_var('count', ''); +			if ((sizeof($active) && sizeof($active) != 3) || (sizeof($joined_before) && sizeof($joined_before) != 3) || (sizeof($joined_after) && sizeof($joined_after) != 3)) +			{ +				trigger_error($user->lang['WRONG_ACTIVE_JOINED_DATE'] . adm_back_link($this->u_action), E_USER_WARNING); +			}  			$key_match = array('lt' => '<', 'gt' => '>', 'eq' => '=');  			$sort_by_types = array('username', 'user_email', 'user_posts', 'user_regdate', 'user_lastvisit');  			$where_sql = ''; -			$where_sql .= ($username) ? ' AND username_clean ' . $db->sql_like_expression(str_replace('*', $db->any_char, utf8_clean_string($username))) : ''; -			$where_sql .= ($email) ? ' AND user_email ' . $db->sql_like_expression(str_replace('*', $db->any_char, $email)) . ' ' : ''; -			$where_sql .= (sizeof($joined)) ? " AND user_regdate " . $key_match[$joined_select] . ' ' . gmmktime(0, 0, 0, (int) $joined[1], (int) $joined[2], (int) $joined[0]) : ''; -			$where_sql .= ($count !== '') ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : ''; +			$where_sql .= ($username) ? ' AND username_clean ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), utf8_clean_string($username))) : ''; +			$where_sql .= ($email) ? ' AND user_email ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), $email)) . ' ' : ''; +			$where_sql .= $joined_sql; +			$where_sql .= ($count) ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : '';  			// First handle pruning of users who never logged in, last active date is 0000-00-00  			if (sizeof($active) && (int) $active[0] == 0 && (int) $active[1] == 0 && (int) $active[2] == 0)  			{  				$where_sql .= ' AND user_lastvisit = 0'; -			}			 +			}  			else if (sizeof($active) && $active_select != 'lt')  			{  				$where_sql .= ' AND user_lastvisit ' . $key_match[$active_select] . ' ' . gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]); @@ -421,8 +456,8 @@ class acp_prune  			}  		} -		// Protect the admin, do not prune if no options are given... -		if (!$where_sql) +		// If no search criteria were provided, go no further. +		if (!$where_sql && !$group_id && $posts_on_queue === false)  		{  			return;  		} @@ -439,28 +474,84 @@ class acp_prune  		}  		$db->sql_freeresult($result); -		// Do not prune founder members -		$sql = 'SELECT user_id, username -			FROM ' . USERS_TABLE . ' -			WHERE user_id <> ' . ANONYMOUS . ' -				AND user_type <> ' . USER_FOUNDER . " -			$where_sql"; -		$result = $db->sql_query($sql); +		// Protect the admin, do not prune if no options are given... +		if ($where_sql) +		{ +			// Do not prune founder members +			$sql = 'SELECT user_id, username +				FROM ' . USERS_TABLE . ' +				WHERE user_id <> ' . ANONYMOUS . ' +					AND user_type <> ' . USER_FOUNDER . " +				$where_sql"; +			$result = $db->sql_query($sql); -		$where_sql = ''; -		$user_ids = $usernames = array(); +			$user_ids = $usernames = array(); -		while ($row = $db->sql_fetchrow($result)) +			while ($row = $db->sql_fetchrow($result)) +			{ +				// Do not prune bots and the user currently pruning. +				if ($row['user_id'] != $user->data['user_id'] && !in_array($row['user_id'], $bot_ids)) +				{ +					$user_ids[] = $row['user_id']; +					$usernames[$row['user_id']] = $row['username']; +				} +			} +			$db->sql_freeresult($result); +		} + +		if ($group_id)  		{ -			// Do not prune bots and the user currently pruning. -			if ($row['user_id'] != $user->data['user_id'] && !in_array($row['user_id'], $bot_ids)) +			$sql = 'SELECT u.user_id, u.username +				FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u +				WHERE ug.group_id = ' . (int) $group_id . ' +					AND ug.user_id <> ' . ANONYMOUS . ' +					AND u.user_type <> ' . USER_FOUNDER . ' +					AND ug.user_pending = 0 ' . +					((!empty($user_ids)) ? 'AND ' . $db->sql_in_set('ug.user_id', $user_ids) : '') . ' +					AND u.user_id = ug.user_id'; +			$result = $db->sql_query($sql); + +			// we're performing an intersection operation, so all the relevant users +			// come from this most recent query (which was limited to the results of the +			// previous query) +			$user_ids = $usernames = array(); +			while ($row = $db->sql_fetchrow($result))  			{ -				$user_ids[] = $row['user_id']; -				$usernames[$row['user_id']] = $row['username']; +				// Do not prune bots and the user currently pruning. +				if ($row['user_id'] != $user->data['user_id'] && !in_array($row['user_id'], $bot_ids)) +				{ +					$user_ids[] = $row['user_id']; +					$usernames[$row['user_id']] = $row['username']; +				}  			} +			$db->sql_freeresult($result); +		} + +		if ($posts_on_queue !== false) +		{ +			$sql = 'SELECT u.user_id, u.username, COUNT(p.post_id) AS queue_posts +				FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u +				WHERE u.user_id <> ' . ANONYMOUS . ' +					AND u.user_type <> ' . USER_FOUNDER . +					((!empty($user_ids)) ? 'AND ' . $db->sql_in_set('p.poster_id', $user_ids) : '') . ' +					AND ' . $db->sql_in_set('p.post_visibility', array(ITEM_UNAPPROVED, ITEM_REAPPROVE)) . ' +					AND u.user_id = p.poster_id +				GROUP BY p.poster_id +				HAVING queue_posts ' . $key_match[$queue_select] . ' ' . $posts_on_queue; +			$result = $db->sql_query($sql); + +			// same intersection logic as the above group ID portion +			$user_ids = $usernames = array(); +			while ($row = $db->sql_fetchrow($result)) +			{ +				// Do not prune bots and the user currently pruning. +				if ($row['user_id'] != $user->data['user_id'] && !in_array($row['user_id'], $bot_ids)) +				{ +					$user_ids[] = $row['user_id']; +					$usernames[$row['user_id']] = $row['username']; +				} +			} +			$db->sql_freeresult($result);  		} -		$db->sql_freeresult($result);  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_ranks.php b/phpBB/includes/acp/acp_ranks.php index ea057cd84c..5885de57ec 100644 --- a/phpBB/includes/acp/acp_ranks.php +++ b/phpBB/includes/acp/acp_ranks.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,16 +19,13 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_ranks  {  	var $u_action;  	function main($id, $mode)  	{ -		global $db, $user, $auth, $template, $cache; +		global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher;  		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;  		$user->add_lang('acp/posting'); @@ -72,7 +72,18 @@ class acp_ranks  					'rank_min'			=> $min_posts,  					'rank_image'		=> htmlspecialchars_decode($rank_image)  				); -				 + +				/** +				* Modify the SQL array when saving a rank +				* +				* @event core.acp_ranks_save_modify_sql_ary +				* @var	int		rank_id		The ID of the rank (if available) +				* @var	array	sql_ary		Array with the rank's data +				* @since 3.1.0-RC3 +				*/ +				$vars = array('rank_id', 'sql_ary'); +				extract($phpbb_dispatcher->trigger_event('core.acp_ranks_save_modify_sql_ary', compact($vars))); +  				if ($rank_id)  				{  					$sql = 'UPDATE ' . RANKS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE rank_id = $rank_id"; @@ -123,6 +134,18 @@ class acp_ranks  					$cache->destroy('_ranks');  					add_log('admin', 'LOG_RANK_REMOVED', $rank_title); + +					if ($request->is_ajax()) +					{ +						$json_response = new \phpbb\json_response; +						$json_response->send(array( +							'MESSAGE_TITLE'	=> $user->lang['INFORMATION'], +							'MESSAGE_TEXT'	=> $user->lang['RANK_REMOVED'], +							'REFRESH_DATA'	=> array( +								'time'	=> 3 +							) +						)); +					}  				}  				else  				{ @@ -140,7 +163,7 @@ class acp_ranks  			case 'add':  				$data = $ranks = $existing_imgs = array(); -				 +  				$sql = 'SELECT *  					FROM ' . RANKS_TABLE . '  					ORDER BY rank_min ASC, rank_special ASC'; @@ -190,7 +213,7 @@ class acp_ranks  				$filename_list = '<option value=""' . (($edit_img == '') ? ' selected="selected"' : '') . '>----------</option>' . $filename_list;  				unset($existing_imgs, $imglist); -				$template->assign_vars(array( +				$tpl_ary = array(  					'S_EDIT'			=> true,  					'U_BACK'			=> $this->u_action,  					'RANKS_PATH'		=> $phpbb_root_path . $config['ranks_path'], @@ -198,17 +221,28 @@ class acp_ranks  					'RANK_TITLE'		=> (isset($ranks['rank_title'])) ? $ranks['rank_title'] : '',  					'S_FILENAME_LIST'	=> $filename_list, -					'RANK_IMAGE'		=> ($edit_img) ? $phpbb_root_path . $config['ranks_path'] . '/' . $edit_img : $phpbb_admin_path . 'images/spacer.gif', +					'RANK_IMAGE'		=> ($edit_img) ? $phpbb_root_path . $config['ranks_path'] . '/' . $edit_img : htmlspecialchars($phpbb_admin_path) . 'images/spacer.gif',  					'S_SPECIAL_RANK'	=> (isset($ranks['rank_special']) && $ranks['rank_special']) ? true : false, -					'MIN_POSTS'			=> (isset($ranks['rank_min']) && !$ranks['rank_special']) ? $ranks['rank_min'] : 0) +					'MIN_POSTS'			=> (isset($ranks['rank_min']) && !$ranks['rank_special']) ? $ranks['rank_min'] : 0,  				); -						 +				/** +				* Modify the template output array for editing/adding ranks +				* +				* @event core.acp_ranks_edit_modify_tpl_ary +				* @var	array	ranks		Array with the rank's data +				* @var	array	tpl_ary		Array with the rank's template data +				* @since 3.1.0-RC3 +				*/ +				$vars = array('ranks', 'tpl_ary'); +				extract($phpbb_dispatcher->trigger_event('core.acp_ranks_edit_modify_tpl_ary', compact($vars))); + +				$template->assign_vars($tpl_ary);  				return;  			break;  		} -	 +  		$template->assign_vars(array(  			'U_ACTION'		=> $this->u_action)  		); @@ -220,7 +254,7 @@ class acp_ranks  		while ($row = $db->sql_fetchrow($result))  		{ -			$template->assign_block_vars('ranks', array( +			$rank_row = array(  				'S_RANK_IMAGE'		=> ($row['rank_image']) ? true : false,  				'S_SPECIAL_RANK'	=> ($row['rank_special']) ? true : false, @@ -229,12 +263,23 @@ class acp_ranks  				'MIN_POSTS'			=> $row['rank_min'],  				'U_EDIT'			=> $this->u_action . '&action=edit&id=' . $row['rank_id'], -				'U_DELETE'			=> $this->u_action . '&action=delete&id=' . $row['rank_id']) -			);	 +				'U_DELETE'			=> $this->u_action . '&action=delete&id=' . $row['rank_id'], +			); + +			/** +			* Modify the template output array for each listed rank +			* +			* @event core.acp_ranks_list_modify_rank_row +			* @var	array	row			Array with the rank's data +			* @var	array	rank_row	Array with the rank's template data +			* @since 3.1.0-RC3 +			*/ +			$vars = array('row', 'rank_row'); +			extract($phpbb_dispatcher->trigger_event('core.acp_ranks_list_modify_rank_row', compact($vars))); + +			$template->assign_block_vars('ranks', $rank_row);  		}  		$db->sql_freeresult($result);  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_reasons.php b/phpBB/includes/acp/acp_reasons.php index dbc9fcb6cc..3d7ccf422c 100644 --- a/phpBB/includes/acp/acp_reasons.php +++ b/phpBB/includes/acp/acp_reasons.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_reasons  {  	var $u_action; @@ -27,6 +27,7 @@ class acp_reasons  	{  		global $db, $user, $auth, $template, $cache;  		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; +		global $request;  		$user->add_lang(array('mcp', 'acp/posting')); @@ -114,7 +115,7 @@ class acp_reasons  							$result = $db->sql_query($sql);  							$max_order = (int) $db->sql_fetchfield('max_reason_order');  							$db->sql_freeresult($result); -							 +  							$sql_ary = array(  								'reason_title'			=> (string) $reason_row['reason_title'],  								'reason_description'	=> (string) $reason_row['reason_description'], @@ -172,14 +173,14 @@ class acp_reasons  					'U_ACTION'		=> $this->u_action . "&id=$reason_id&action=$action",  					'U_BACK'		=> $this->u_action,  					'ERROR_MSG'		=> (sizeof($error)) ? implode('<br />', $error) : '', -					 +  					'REASON_TITLE'			=> $reason_row['reason_title'],  					'REASON_DESCRIPTION'	=> $reason_row['reason_description'],  					'TRANSLATED_TITLE'		=> ($translated) ? $user->lang['report_reasons']['TITLE'][strtoupper($reason_row['reason_title'])] : '',  					'TRANSLATED_DESCRIPTION'=> ($translated) ? $user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason_row['reason_title'])] : '', -					'S_AVAILABLE_TITLES'	=> implode(', ', array_map('htmlspecialchars', array_keys($user->lang['report_reasons']['TITLE']))), +					'S_AVAILABLE_TITLES'	=> implode($user->lang['COMMA_SEPARATOR'], array_map('htmlspecialchars', array_keys($user->lang['report_reasons']['TITLE']))),  					'S_EDIT_REASON'			=> true,  					'S_TRANSLATED'			=> $translated,  					'S_ERROR'				=> (sizeof($error)) ? true : false, @@ -218,7 +219,7 @@ class acp_reasons  					$other_reason_id = (int) $db->sql_fetchfield('reason_id');  					$db->sql_freeresult($result); -					switch ($db->sql_layer) +					switch ($db->get_sql_layer())  					{  						// The ugly one!  						case 'mysqli': @@ -251,8 +252,8 @@ class acp_reasons  						// Teh standard  						case 'postgres':  						case 'oracle': -						case 'firebird':  						case 'sqlite': +						case 'sqlite3':  							// Change the reports using this reason to 'other'  							$sql = 'UPDATE ' . REPORTS_TABLE . '  								SET reason_id = ' . $other_reason_id . ", report_text = '" . $db->sql_escape($reason_row['reason_description']) . "\n\n' || report_text @@ -281,7 +282,18 @@ class acp_reasons  			case 'move_up':  			case 'move_down': -				$order = request_var('order', 0); +				$sql = 'SELECT reason_order +					FROM ' . REPORTS_REASONS_TABLE . " +					WHERE reason_id = $reason_id"; +				$result = $db->sql_query($sql); +				$order = $db->sql_fetchfield('reason_order'); +				$db->sql_freeresult($result); + +				if ($order === false || ($order == 0 && $action == 'move_up')) +				{ +					break; +				} +				$order = (int) $order;  				$order_total = $order * 2 + (($action == 'move_up') ? -1 : 1);  				$sql = 'UPDATE ' . REPORTS_REASONS_TABLE . ' @@ -289,6 +301,13 @@ class acp_reasons  					WHERE reason_order IN (' . $order . ', ' . (($action == 'move_up') ? $order - 1 : $order + 1) . ')';  				$db->sql_query($sql); +				if ($request->is_ajax()) +				{ +					$json_response = new \phpbb\json_response; +					$json_response->send(array( +						'success'	=> (bool) $db->sql_affectedrows(), +					)); +				}  			break;  		} @@ -304,7 +323,7 @@ class acp_reasons  			do  			{  				++$order; -				 +  				if ($row['reason_order'] != $order)  				{  					$sql = 'UPDATE ' . REPORTS_REASONS_TABLE . " @@ -364,12 +383,10 @@ class acp_reasons  				'U_EDIT'		=> $this->u_action . '&action=edit&id=' . $row['reason_id'],  				'U_DELETE'		=> (!$other_reason) ? $this->u_action . '&action=delete&id=' . $row['reason_id'] : '', -				'U_MOVE_UP'		=> $this->u_action . '&action=move_up&order=' . $row['reason_order'], -				'U_MOVE_DOWN'	=> $this->u_action . '&action=move_down&order=' . $row['reason_order']) +				'U_MOVE_UP'		=> $this->u_action . '&action=move_up&id=' . $row['reason_id'], +				'U_MOVE_DOWN'	=> $this->u_action . '&action=move_down&id=' . $row['reason_id'])  			);  		}  		$db->sql_freeresult($result);  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index 0cd67b1c34..eddc6871f8 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_search  {  	var $u_action; @@ -77,9 +77,11 @@ class acp_search  				continue;  			} -			$name = ucfirst(strtolower(str_replace('_', ' ', $type))); +			$name = $search->get_name(); +  			$selected = ($config['search_type'] == $type) ? ' selected="selected"' : ''; -			$search_options .= '<option value="' . $type . '"' . $selected . '>' . $name . '</option>'; +			$identifier = substr($type, strrpos($type, '\\') + 1); +			$search_options .= "<option value=\"$type\"$selected data-toggle-setting=\"#search_{$identifier}_settings\">$name</option>";  			if (method_exists($search, 'acp'))  			{ @@ -88,9 +90,10 @@ class acp_search  				if (!$submit)  				{  					$template->assign_block_vars('backend', array( -						'NAME'		=> $name, -						'SETTINGS'	=> $vars['tpl']) -					); +						'NAME'			=> $name, +						'SETTINGS'		=> $vars['tpl'], +						'IDENTIFIER'	=> $identifier, +					));  				}  				else if (is_array($vars['config']))  				{ @@ -232,15 +235,7 @@ class acp_search  		global $db, $user, $auth, $template, $cache;  		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; -		if (isset($_REQUEST['action']) && is_array($_REQUEST['action'])) -		{ -			$action = request_var('action', array('' => false)); -			$action = key($action); -		} -		else -		{ -			$action = request_var('action', ''); -		} +		$action = request_var('action', '');  		$this->state = explode(',', $config['search_indexing_state']);  		if (isset($_POST['cancel'])) @@ -283,7 +278,7 @@ class acp_search  			{  				trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING);  			} -			$name = ucfirst(strtolower(str_replace('_', ' ', $this->state[0]))); +			$name = $this->search->get_name();  			$action = &$this->state[1]; @@ -345,7 +340,7 @@ class acp_search  							$totaltime = $mtime[0] + $mtime[1] - $starttime;  							$rows_per_second = $row_count / $totaltime;  							meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter)); -							trigger_error(sprintf($user->lang['SEARCH_INDEX_DELETE_REDIRECT'], $post_counter, $row_count, $rows_per_second)); +							trigger_error($user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $row_count, $post_counter, $rows_per_second));  						}  					} @@ -405,9 +400,8 @@ class acp_search  							$i = 0;  							while ($row = ($buffer ? $rows[$i++] : $db->sql_fetchrow($result)))  							{ -								// Indexing enabled for this forum or global announcement? -								// Global announcements get indexed by default. -								if (!$row['forum_id'] || (isset($forums[$row['forum_id']]) && $forums[$row['forum_id']])) +								// Indexing enabled for this forum +								if (isset($forums[$row['forum_id']]) && $forums[$row['forum_id']])  								{  									$this->search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']);  								} @@ -436,7 +430,7 @@ class acp_search  							$totaltime = $mtime[0] + $mtime[1] - $starttime;  							$rows_per_second = $row_count / $totaltime;  							meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter)); -							trigger_error(sprintf($user->lang['SEARCH_INDEX_CREATE_REDIRECT'], $post_counter, $row_count, $rows_per_second)); +							trigger_error($user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second));  						}  					} @@ -463,7 +457,7 @@ class acp_search  				continue;  			} -			$name = ucfirst(strtolower(str_replace('_', ' ', $type))); +			$name = $search->get_name();  			$data = array();  			if (method_exists($search, 'index_stats')) @@ -562,27 +556,15 @@ class acp_search  	function get_search_types()  	{ -		global $phpbb_root_path, $phpEx; - -		$search_types = array(); +		global $phpbb_root_path, $phpEx, $phpbb_extension_manager; -		$dp = @opendir($phpbb_root_path . 'includes/search'); +		$finder = $phpbb_extension_manager->get_finder(); -		if ($dp) -		{ -			while (($file = readdir($dp)) !== false) -			{ -				if ((preg_match('#\.' . $phpEx . '$#', $file)) && ($file != "search.$phpEx")) -				{ -					$search_types[] = preg_replace('#^(.*?)\.' . $phpEx . '$#', '\1', $file); -				} -			} -			closedir($dp); - -			sort($search_types); -		} - -		return $search_types; +		return $finder +			->extension_suffix('_backend') +			->extension_directory('/search') +			->core_path('phpbb/search/') +			->get_classes();  	}  	function get_max_post_id() @@ -617,27 +599,17 @@ class acp_search  	*/  	function init_search($type, &$search, &$error)  	{ -		global $phpbb_root_path, $phpEx, $user; - -		if (!preg_match('#^\w+$#', $type) || !file_exists("{$phpbb_root_path}includes/search/$type.$phpEx")) -		{ -			$error = $user->lang['NO_SUCH_SEARCH_MODULE']; -			return $error; -		} - -		include_once("{$phpbb_root_path}includes/search/$type.$phpEx"); +		global $phpbb_root_path, $phpEx, $user, $auth, $config, $db; -		if (!class_exists($type)) +		if (!class_exists($type) || !method_exists($type, 'keyword_search'))  		{  			$error = $user->lang['NO_SUCH_SEARCH_MODULE'];  			return $error;  		}  		$error = false; -		$search = new $type($error); +		$search = new $type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);  		return $error;  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_send_statistics.php b/phpBB/includes/acp/acp_send_statistics.php index b8fc2d2c45..d178be2fb0 100644 --- a/phpBB/includes/acp/acp_send_statistics.php +++ b/phpBB/includes/acp/acp_send_statistics.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,18 +19,15 @@ if (!defined('IN_PHPBB'))  	exit;  } -include($phpbb_root_path . 'includes/questionnaire/questionnaire.' . $phpEx); - -/** -* @package acp -*/  class acp_send_statistics  {  	var $u_action;  	function main($id, $mode)  	{ -		global $config, $template, $phpbb_admin_path, $phpEx; +		global $config, $template, $phpbb_admin_path, $phpbb_root_path, $phpEx; + +		include($phpbb_root_path . 'includes/questionnaire/questionnaire.' . $phpEx);  		$collect_url = "https://www.phpbb.com/stats/receive_stats.php"; @@ -86,5 +86,3 @@ class acp_send_statistics  		}  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 47cd02bca7..6bd27a8bca 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,3961 +19,1316 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_styles  { -	var $u_action; - -	var $style_cfg; -	var $template_cfg; -	var $theme_cfg; -	var $imageset_cfg; -	var $imageset_keys; - -	function main($id, $mode) -	{ -		global $db, $user, $auth, $template, $cache; -		global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; - -		// Hardcoded template bitfield to add for new templates -		$bitfield = new bitfield(); -		$bitfield->set(0); -		$bitfield->set(1); -		$bitfield->set(2); -		$bitfield->set(3); -		$bitfield->set(4); -		$bitfield->set(8); -		$bitfield->set(9); -		$bitfield->set(11); -		$bitfield->set(12); -		define('TEMPLATE_BITFIELD', $bitfield->get_base64()); -		unset($bitfield); +	public $u_action; -		$user->add_lang('acp/styles'); +	protected $u_base_action; +	protected $s_hidden_fields; +	protected $mode; +	protected $styles_path; +	protected $styles_path_absolute = 'styles'; +	protected $default_style = 0; +	protected $styles_list_cols = 0; +	protected $reserved_style_names = array('adm', 'admin', 'all'); -		$this->tpl_name = 'acp_styles'; -		$this->page_title = 'ACP_CAT_STYLES'; +	/** @var \phpbb\db\driver\driver_interface */ +	protected $db; -		$action = request_var('action', ''); -		$action = (isset($_POST['add'])) ? 'add' : $action; -		$style_id = request_var('id', 0); - -		// Fill the configuration variables -		$this->style_cfg = $this->template_cfg = $this->theme_cfg = $this->imageset_cfg = ' -# -# phpBB {MODE} configuration file -# -# @package phpBB3 -# @copyright (c) 2005 phpBB Group -# @license http://opensource.org/licenses/gpl-license.php GNU Public License -# -# -# At the left is the name, please do not change this -# At the right the value is entered -# For on/off options the valid values are on, off, 1, 0, true and false -# -# Values get trimmed, if you want to add a space in front or at the end of -# the value, then enclose the value with single or double quotes. -# Single and double quotes do not need to be escaped. -# -# - -# General Information about this {MODE} -name = {NAME} -copyright = {COPYRIGHT} -version = {VERSION} -'; - -		$this->theme_cfg .= ' -# Some configuration options - -# -# You have to turn this option on if you want to use the -# path template variables ({T_IMAGESET_PATH} for example) within -# your css file. -# This is mostly the case if you want to use language specific -# images within your css file. -# -parse_css_file = {PARSE_CSS_FILE} -'; - -		$this->template_cfg .= ' -# Some configuration options - -# Template inheritance -# See http://blog.phpbb.com/2008/07/31/templating-just-got-easier/ -# Set value to empty or this template name to ignore template inheritance. -inherit_from = {INHERIT_FROM} -'; - -		$this->imageset_keys = array( -			'logos' => array( -				'site_logo', -			), -			'buttons'	=> array( -				'icon_back_top', 'icon_contact_aim', 'icon_contact_email', 'icon_contact_icq', 'icon_contact_jabber', 'icon_contact_msnm', 'icon_contact_pm', 'icon_contact_yahoo', 'icon_contact_www', 'icon_post_delete', 'icon_post_edit', 'icon_post_info', 'icon_post_quote', 'icon_post_report', 'icon_user_online', 'icon_user_offline', 'icon_user_profile', 'icon_user_search', 'icon_user_warn', 'button_pm_forward', 'button_pm_new', 'button_pm_reply', 'button_topic_locked', 'button_topic_new', 'button_topic_reply', -			), -			'icons'		=> array( -				'icon_post_target', 'icon_post_target_unread', 'icon_topic_attach', 'icon_topic_latest', 'icon_topic_newest', 'icon_topic_reported', 'icon_topic_unapproved', 'icon_friend', 'icon_foe', -			), -			'forums'	=> array( -				'forum_link', 'forum_read', 'forum_read_locked', 'forum_read_subforum', 'forum_unread', 'forum_unread_locked', 'forum_unread_subforum', 'subforum_read', 'subforum_unread' -			), -			'folders'	=> array( -				'topic_moved', 'topic_read', 'topic_read_mine', 'topic_read_hot', 'topic_read_hot_mine', 'topic_read_locked', 'topic_read_locked_mine', 'topic_unread', 'topic_unread_mine', 'topic_unread_hot', 'topic_unread_hot_mine', 'topic_unread_locked', 'topic_unread_locked_mine', 'sticky_read', 'sticky_read_mine', 'sticky_read_locked', 'sticky_read_locked_mine', 'sticky_unread', 'sticky_unread_mine', 'sticky_unread_locked', 'sticky_unread_locked_mine', 'announce_read', 'announce_read_mine', 'announce_read_locked', 'announce_read_locked_mine', 'announce_unread', 'announce_unread_mine', 'announce_unread_locked', 'announce_unread_locked_mine', 'global_read', 'global_read_mine', 'global_read_locked', 'global_read_locked_mine', 'global_unread', 'global_unread_mine', 'global_unread_locked', 'global_unread_locked_mine', 'pm_read', 'pm_unread', -			), -			'polls'		=> array( -				'poll_left', 'poll_center', 'poll_right', -			), -			'ui'		=> array( -				'upload_bar', -			), -			'user'		=> array( -				'user_icon1', 'user_icon2', 'user_icon3', 'user_icon4', 'user_icon5', 'user_icon6', 'user_icon7', 'user_icon8', 'user_icon9', 'user_icon10', -			), -		); +	/** @var \phpbb\user */ +	protected $user; -		// Execute overall actions -		switch ($action) -		{ -			case 'delete': -				if ($style_id) -				{ -					$this->remove($mode, $style_id); -					return; -				} -			break; +	/** @var \phpbb\template\template */ +	protected $template; -			case 'export': -				if ($style_id) -				{ -					$this->export($mode, $style_id); -					return; -				} -			break; +	/** @var \phpbb\request\request_interface */ +	protected $request; -			case 'install': -				$this->install($mode); -				return; -			break; +	/** @var \phpbb\cache\driver\driver_interface */ +	protected $cache; -			case 'add': -				$this->add($mode); -				return; -			break; +	/** @var \phpbb\auth\auth */ +	protected $auth; -			case 'details': -				if ($style_id) -				{ -					$this->details($mode, $style_id); -					return; -				} -			break; +	/** @var string */ +	protected $phpbb_root_path; -			case 'edit': -				if ($style_id) -				{ -					switch ($mode) -					{ -						case 'imageset': -							return $this->edit_imageset($style_id); -						case 'template': -							return $this->edit_template($style_id); -						case 'theme': -							return $this->edit_theme($style_id); -					} -				} -			break; +	/** @var string */ +	protected $php_ext; -			case 'cache': -				if ($style_id) -				{ -					switch ($mode) -					{ -						case 'template': -							return $this->template_cache($style_id); -					} -				} -			break; -		} - -		switch ($mode) -		{ -			case 'style': - -				switch ($action) -				{ -					case 'activate': -					case 'deactivate': - -						if ($style_id == $config['default_style']) -						{ -							trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING); -						} - -						if (($action == 'deactivate' && confirm_box(true)) || $action == 'activate') -						{ -							$sql = 'UPDATE ' . STYLES_TABLE . ' -								SET style_active = ' . (($action == 'activate') ? 1 : 0) . ' -								WHERE style_id = ' . $style_id; -							$db->sql_query($sql); - -							// Set style to default for any member using deactivated style -							if ($action == 'deactivate') -							{ -								$sql = 'UPDATE ' . USERS_TABLE . ' -									SET user_style = ' . $config['default_style'] . " -									WHERE user_style = $style_id"; -								$db->sql_query($sql); - -								$sql = 'UPDATE ' . FORUMS_TABLE . ' -									SET forum_style = 0 -									WHERE forum_style = ' . $style_id; -								$db->sql_query($sql); -							} -						} -						else if ($action == 'deactivate') -						{ -							$s_hidden_fields = array( -								'i'			=> $id, -								'mode'		=> $mode, -								'action'	=> $action, -								'style_id'	=> $style_id, -							); -							confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields)); -						} -					break; -				} - -				$this->frontend('style', array('details'), array('export', 'delete')); -			break; - -			case 'template': - -				switch ($action) -				{ -					// Refresh template data stored in db and clear cache -					case 'refresh': - -						$sql = 'SELECT * -							FROM ' . STYLES_TEMPLATE_TABLE . " -							WHERE template_id = $style_id"; -						$result = $db->sql_query($sql); -						$template_row = $db->sql_fetchrow($result); -						$db->sql_freeresult($result); - -						if (!$template_row) -						{ -							trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); -						} - -						if (confirm_box(true)) -						{ -							$template_refreshed = ''; - -							// Only refresh database if the template is stored in the database -							if ($template_row['template_storedb'] && file_exists("{$phpbb_root_path}styles/{$template_row['template_path']}/template/")) -							{ -								$filelist = array('' => array()); - -								$sql = 'SELECT template_filename, template_mtime -									FROM ' . STYLES_TEMPLATE_DATA_TABLE . " -									WHERE template_id = $style_id"; -								$result = $db->sql_query($sql); - -								while ($row = $db->sql_fetchrow($result)) -								{ -//									if (@filemtime("{$phpbb_root_path}styles/{$template_row['template_path']}/template/" . $row['template_filename']) > $row['template_mtime']) -//									{ -										// get folder info from the filename -										if (($slash_pos = strrpos($row['template_filename'], '/')) === false) -										{ -											$filelist[''][] = $row['template_filename']; -										} -										else -										{ -											$filelist[substr($row['template_filename'], 0, $slash_pos + 1)][] = substr($row['template_filename'], $slash_pos + 1, strlen($row['template_filename']) - $slash_pos - 1); -										} -//									} -								} -								$db->sql_freeresult($result); - -								$this->store_templates('update', $style_id, $template_row['template_path'], $filelist); -								unset($filelist); - -								$template_refreshed = $user->lang['TEMPLATE_REFRESHED'] . '<br />'; -								add_log('admin', 'LOG_TEMPLATE_REFRESHED', $template_row['template_name']); -							} - -							$this->clear_template_cache($template_row); - -							trigger_error($template_refreshed . $user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action)); -						} -						else -						{ -							confirm_box(false, ($template_row['template_storedb']) ? $user->lang['CONFIRM_TEMPLATE_REFRESH'] : $user->lang['CONFIRM_TEMPLATE_CLEAR_CACHE'], build_hidden_fields(array( -								'i'			=> $id, -								'mode'		=> $mode, -								'action'	=> $action, -								'id'		=> $style_id -							))); -						} - -					break; -				} - -				$this->frontend('template', array('edit', 'cache', 'details'), array('refresh', 'export', 'delete')); -			break; - -			case 'theme': - -				switch ($action) -				{ -					// Refresh theme data stored in the database -					case 'refresh': - -						$sql = 'SELECT * -							FROM ' . STYLES_THEME_TABLE . " -							WHERE theme_id = $style_id"; -						$result = $db->sql_query($sql); -						$theme_row = $db->sql_fetchrow($result); -						$db->sql_freeresult($result); - -						if (!$theme_row) -						{ -							trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); -						} - -						if (!$theme_row['theme_storedb']) -						{ -							trigger_error($user->lang['THEME_ERR_REFRESH_FS'] . adm_back_link($this->u_action), E_USER_WARNING); -						} - -						if (confirm_box(true)) -						{ -							if ($theme_row['theme_storedb'] && file_exists("{$phpbb_root_path}styles/{$theme_row['theme_path']}/theme/stylesheet.css")) -							{ -								// Save CSS contents -								$sql_ary = array( -									'theme_mtime'	=> (int) filemtime("{$phpbb_root_path}styles/{$theme_row['theme_path']}/theme/stylesheet.css"), -									'theme_data'	=> $this->db_theme_data($theme_row) -								); - -								$sql = 'UPDATE ' . STYLES_THEME_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " -									WHERE theme_id = $style_id"; -								$db->sql_query($sql); - -								$cache->destroy('sql', STYLES_THEME_TABLE); - -								add_log('admin', 'LOG_THEME_REFRESHED', $theme_row['theme_name']); -								trigger_error($user->lang['THEME_REFRESHED'] . adm_back_link($this->u_action)); -							} -						} -						else -						{ -							confirm_box(false, $user->lang['CONFIRM_THEME_REFRESH'], build_hidden_fields(array( -								'i'			=> $id, -								'mode'		=> $mode, -								'action'	=> $action, -								'id'		=> $style_id -							))); -						} -					break; -				} - -				$this->frontend('theme', array('edit', 'details'), array('refresh', 'export', 'delete')); -			break; - -			case 'imageset': - -				switch ($action) -				{ -					case 'refresh': - -						$sql = 'SELECT * -							FROM ' . STYLES_IMAGESET_TABLE . " -							WHERE imageset_id = $style_id"; -						$result = $db->sql_query($sql); -						$imageset_row = $db->sql_fetchrow($result); -						$db->sql_freeresult($result); - -						if (!$imageset_row) -						{ -							trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); -						} - -						if (confirm_box(true)) -						{ -							$sql_ary = array(); - -							$imageset_definitions = array(); -							foreach ($this->imageset_keys as $topic => $key_array) -							{ -								$imageset_definitions = array_merge($imageset_definitions, $key_array); -							} - -							$cfg_data_imageset = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/imageset.cfg"); - -							$db->sql_transaction('begin'); - -							$sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . ' -								WHERE imageset_id = ' . $style_id; -							$result = $db->sql_query($sql); - -							foreach ($cfg_data_imageset as $image_name => $value) -							{ -								if (strpos($value, '*') !== false) -								{ -									if (substr($value, -1, 1) === '*') -									{ -										list($image_filename, $image_height) = explode('*', $value); -										$image_width = 0; -									} -									else -									{ -										list($image_filename, $image_height, $image_width) = explode('*', $value); -									} -								} -								else -								{ -									$image_filename = $value; -									$image_height = $image_width = 0; -								} - -								if (strpos($image_name, 'img_') === 0 && $image_filename) -								{ -									$image_name = substr($image_name, 4); -									if (in_array($image_name, $imageset_definitions)) -									{ -										$sql_ary[] = array( -											'image_name'		=> (string) $image_name, -											'image_filename'	=> (string) $image_filename, -											'image_height'		=> (int) $image_height, -											'image_width'		=> (int) $image_width, -											'imageset_id'		=> (int) $style_id, -											'image_lang'		=> '', -										); -									} -								} -							} - -							$sql = 'SELECT lang_dir -								FROM ' . LANG_TABLE; -							$result = $db->sql_query($sql); - -							while ($row = $db->sql_fetchrow($result)) -							{ -								if (@file_exists("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$row['lang_dir']}/imageset.cfg")) -								{ -									$cfg_data_imageset_data = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$row['lang_dir']}/imageset.cfg"); -									foreach ($cfg_data_imageset_data as $image_name => $value) -									{ -										if (strpos($value, '*') !== false) -										{ -											if (substr($value, -1, 1) === '*') -											{ -												list($image_filename, $image_height) = explode('*', $value); -												$image_width = 0; -											} -											else -											{ -												list($image_filename, $image_height, $image_width) = explode('*', $value); -											} -										} -										else -										{ -											$image_filename = $value; -											$image_height = $image_width = 0; -										} - -										if (strpos($image_name, 'img_') === 0 && $image_filename) -										{ -											$image_name = substr($image_name, 4); -											if (in_array($image_name, $imageset_definitions)) -											{ -												$sql_ary[] = array( -													'image_name'		=> (string) $image_name, -													'image_filename'	=> (string) $image_filename, -													'image_height'		=> (int) $image_height, -													'image_width'		=> (int) $image_width, -													'imageset_id'		=> (int) $style_id, -													'image_lang'		=> (string) $row['lang_dir'], -												); -											} -										} -									} -								} -							} -							$db->sql_freeresult($result); - -							$db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); - -							$db->sql_transaction('commit'); - -							$cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); -							$cache->destroy('imageset_site_logo_md5'); - -							add_log('admin', 'LOG_IMAGESET_REFRESHED', $imageset_row['imageset_name']); -							trigger_error($user->lang['IMAGESET_REFRESHED'] . adm_back_link($this->u_action)); -						} -						else -						{ -							confirm_box(false, $user->lang['CONFIRM_IMAGESET_REFRESH'], build_hidden_fields(array( -								'i'			=> $id, -								'mode'		=> $mode, -								'action'	=> $action, -								'id'		=> $style_id -							))); -						} -					break; -				} - -				$this->frontend('imageset', array('edit', 'details'), array('refresh', 'export', 'delete')); -			break; -		} -	} - -	/** -	* Build Frontend with supplied options -	*/ -	function frontend($mode, $options, $actions) +	public function main($id, $mode)  	{ -		global $user, $template, $db, $config, $phpbb_root_path, $phpEx; - -		$sql_from = ''; -		$sql_sort = 'LOWER(' . $mode . '_name)'; -		$style_count = array(); - -		switch ($mode) -		{ -			case 'style': -				$sql_from = STYLES_TABLE; -				$sql_sort = 'style_active DESC, ' . $sql_sort; - -				$sql = 'SELECT user_style, COUNT(user_style) AS style_count -					FROM ' . USERS_TABLE . ' -					GROUP BY user_style'; -				$result = $db->sql_query($sql); - -				while ($row = $db->sql_fetchrow($result)) -				{ -					$style_count[$row['user_style']] = $row['style_count']; -				} -				$db->sql_freeresult($result); - -			break; - -			case 'template': -				$sql_from = STYLES_TEMPLATE_TABLE; -			break; - -			case 'theme': -				$sql_from = STYLES_THEME_TABLE; -			break; - -			case 'imageset': -				$sql_from = STYLES_IMAGESET_TABLE; -			break; -			 -			default: -				trigger_error($user->lang['NO_MODE'] . adm_back_link($this->u_action), E_USER_WARNING); -		} - -		$l_prefix = strtoupper($mode); - -		$this->page_title = 'ACP_' . $l_prefix . 'S'; - -		$template->assign_vars(array( -			'S_FRONTEND'		=> true, -			'S_STYLE'			=> ($mode == 'style') ? true : false, - -			'L_TITLE'			=> $user->lang[$this->page_title], -			'L_EXPLAIN'			=> $user->lang[$this->page_title . '_EXPLAIN'], -			'L_NAME'			=> $user->lang[$l_prefix . '_NAME'], -			'L_INSTALLED'		=> $user->lang['INSTALLED_' . $l_prefix], -			'L_UNINSTALLED'		=> $user->lang['UNINSTALLED_' . $l_prefix], -			'L_NO_UNINSTALLED'	=> $user->lang['NO_UNINSTALLED_' . $l_prefix], -			'L_CREATE'			=> $user->lang['CREATE_' . $l_prefix], - -			'U_ACTION'			=> $this->u_action, -			) +		global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config; + +		$this->db = $db; +		$this->user = $user; +		$this->template = $template; +		$this->request = $request; +		$this->cache = $cache; +		$this->auth = $auth; +		$this->config = $config; +		$this->phpbb_root_path = $phpbb_root_path; +		$this->php_ext = $phpEx; + +		$this->default_style = $config['default_style']; +		$this->styles_path = $this->phpbb_root_path . $this->styles_path_absolute . '/'; + +		$this->u_base_action = append_sid("{$phpbb_admin_path}index.{$this->php_ext}", "i={$id}"); +		$this->s_hidden_fields = array( +			'mode'		=> $mode,  		); -		$sql = "SELECT * -			FROM $sql_from -			ORDER BY $sql_sort ASC"; -		$result = $db->sql_query($sql); - -		$installed = array(); - -		$basis_options = '<option class="sep" value="">' . $user->lang['OPTIONAL_BASIS'] . '</option>'; -		while ($row = $db->sql_fetchrow($result)) -		{ -			$installed[] = $row[$mode . '_name']; -			$basis_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>'; +		$this->user->add_lang('acp/styles'); -			$stylevis = ($mode == 'style' && !$row['style_active']) ? 'activate' : 'deactivate'; +		$this->tpl_name = 'acp_styles'; +		$this->page_title = 'ACP_CAT_STYLES'; +		$this->mode = $mode; -			$s_options = array(); -			foreach ($options as $option) -			{ -				$s_options[] = '<a href="' . $this->u_action . "&action=$option&id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>'; -			} +		$action = $this->request->variable('action', ''); +		$post_actions = array('install', 'activate', 'deactivate', 'uninstall'); -			$s_actions = array(); -			foreach ($actions as $option) +		foreach ($post_actions as $key) +		{ +			if ($this->request->is_set_post($key))  			{ -				$s_actions[] = '<a href="' . $this->u_action . "&action=$option&id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>'; +				$action = $key;  			} - -			$template->assign_block_vars('installed', array( -				'S_DEFAULT_STYLE'		=> ($mode == 'style' && $row['style_id'] == $config['default_style']) ? true : false, -				'U_EDIT'				=> $this->u_action . '&action=' . (($mode == 'style') ? 'details' : 'edit') . '&id=' . $row[$mode . '_id'], -				'U_STYLE_ACT_DEACT'		=> $this->u_action . '&action=' . $stylevis . '&id=' . $row[$mode . '_id'], -				'L_STYLE_ACT_DEACT'		=> $user->lang['STYLE_' . strtoupper($stylevis)], -				'S_OPTIONS'				=> implode(' | ', $s_options), -				'S_ACTIONS'				=> implode(' | ', $s_actions), -				'U_PREVIEW'				=> ($mode == 'style') ? append_sid("{$phpbb_root_path}index.$phpEx", "$mode=" . $row[$mode . '_id']) : '', - -				'NAME'					=> $row[$mode . '_name'], -				'STYLE_COUNT'			=> ($mode == 'style' && isset($style_count[$row['style_id']])) ? $style_count[$row['style_id']] : 0, - -				'S_INACTIVE'			=> ($mode == 'style' && !$row['style_active']) ? true : false, -				) -			);  		} -		$db->sql_freeresult($result); -		// Grab uninstalled items -		$new_ary = $cfg = array(); - -		$dp = @opendir("{$phpbb_root_path}styles"); - -		if ($dp) +		// The uninstall action uses confirm_box() to verify the validity of the request, +		// so there is no need to check for a valid token here. +		if (in_array($action, $post_actions) && $action != 'uninstall')  		{ -			while (($file = readdir($dp)) !== false) -			{ -				if ($file[0] == '.' || !is_dir($phpbb_root_path . 'styles/' . $file)) -				{ -					continue; -				} +			$is_valid_request = check_link_hash($request->variable('hash', ''), $action) || check_form_key('styles_management'); -				$subpath = ($mode != 'style') ? "$mode/" : ''; -				if (file_exists("{$phpbb_root_path}styles/$file/$subpath$mode.cfg")) -				{ -					if ($cfg = file("{$phpbb_root_path}styles/$file/$subpath$mode.cfg")) -					{ -						$items = parse_cfg_file('', $cfg); -						$name = (isset($items['name'])) ? trim($items['name']) : false; - -						if ($name && !in_array($name, $installed)) -						{ -							// The array key is used for sorting later on. -							// $file is appended because $name doesn't have to be unique. -							$new_ary[$name . $file] = array( -								'path'		=> $file, -								'name'		=> $name, -								'copyright'	=> $items['copyright'], -							); -						} -					} -				} +			if (!$is_valid_request) +			{ +				trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);  			} -			closedir($dp);  		} -		unset($installed); - -		if (sizeof($new_ary)) +		if ($action != '')  		{ -			ksort($new_ary); - -			foreach ($new_ary as $cfg) -			{ -				$template->assign_block_vars('uninstalled', array( -					'NAME'			=> $cfg['name'], -					'COPYRIGHT'		=> $cfg['copyright'], -					'U_INSTALL'		=> $this->u_action . '&action=install&path=' . urlencode($cfg['path'])) -				); -			} +			$this->s_hidden_fields['action'] = $action;  		} -		unset($new_ary); -		$template->assign_vars(array( -			'S_BASIS_OPTIONS'		=> $basis_options) +		$this->template->assign_vars(array( +			'U_ACTION'			=> $this->u_base_action, +			'S_HIDDEN_FIELDS'	=> build_hidden_fields($this->s_hidden_fields) +			)  		); +		// Execute actions +		switch ($action) +		{ +			case 'install': +				$this->action_install(); +				return; +			case 'uninstall': +				$this->action_uninstall(); +				return; +			case 'activate': +				$this->action_activate(); +				return; +			case 'deactivate': +				$this->action_deactivate(); +				return; +			case 'details': +				$this->action_details(); +				return; +			default: +				$this->frontend(); +		}  	}  	/** -	* Provides a template editor which allows saving changes to template files on the filesystem or in the database. -	* -	* @param int $template_id specifies which template set is being edited +	* Main page  	*/ -	function edit_template($template_id) +	protected function frontend()  	{ -		global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode; +		add_form_key('styles_management'); -		if (defined('PHPBB_DISABLE_ACP_EDITOR')) +		// Check mode +		switch ($this->mode)  		{ -			trigger_error($user->lang['EDITOR_DISABLED'] . adm_back_link($this->u_action)); +			case 'style': +				$this->welcome_message('ACP_STYLES', 'ACP_STYLES_EXPLAIN'); +				$this->show_installed(); +				return; +			case 'install': +				$this->welcome_message('INSTALL_STYLES', 'INSTALL_STYLES_EXPLAIN'); +				$this->show_available(); +				return;  		} +		trigger_error($this->user->lang['NO_MODE'] . adm_back_link($this->u_action), E_USER_WARNING); +	} -		$this->page_title = 'EDIT_TEMPLATE'; - -		$filelist = $filelist_cats = array(); - -		$template_data	= utf8_normalize_nfc(request_var('template_data', '', true)); -		$template_data	= htmlspecialchars_decode($template_data); -		$template_file	= utf8_normalize_nfc(request_var('template_file', '', true)); -		$text_rows		= max(5, min(999, request_var('text_rows', 20))); -		$save_changes	= (isset($_POST['save'])) ? true : false; - -		// make sure template_file path doesn't go upwards -		$template_file = preg_replace('#\.{2,}#', '.', $template_file); - -		// Retrieve some information about the template -		$sql = 'SELECT template_storedb, template_path, template_name -			FROM ' . STYLES_TEMPLATE_TABLE . " -			WHERE template_id = $template_id"; -		$result = $db->sql_query($sql); -		$template_info = $db->sql_fetchrow($result); -		$db->sql_freeresult($result); - -		if (!$template_info) -		{ -			trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); -		} +	/** +	* Install style(s) +	*/ +	protected function action_install() +	{ +		// Get list of styles to install +		$dirs = $this->request_vars('dir', '', true); -		if ($save_changes && !check_form_key('acp_styles')) -		{ -			trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); -		} -		else if (!$save_changes) -		{ -			add_form_key('acp_styles'); -		} +		// Get list of styles that can be installed +		$styles = $this->find_available(false); -		// save changes to the template if the user submitted any -		if ($save_changes && $template_file) +		// Install each style +		$messages = array(); +		$installed_names = array(); +		$installed_dirs = array(); +		$last_installed = false; +		foreach ($dirs as $dir)  		{ -			// Get the filesystem location of the current file -			$file = "{$phpbb_root_path}styles/{$template_info['template_path']}/template/$template_file"; -			$additional = ''; - -			// If the template is stored on the filesystem try to write the file else store it in the database -			if (!$safe_mode && !$template_info['template_storedb'] && file_exists($file) && phpbb_is_writable($file)) -			{ -				if (!($fp = @fopen($file, 'wb'))) -				{ -					// File exists and is writeable, but still not able to be written to -					trigger_error(sprintf($user->lang['TEMPLATE_FILE_NOT_WRITABLE'], htmlspecialchars($template_file)) . adm_back_link($this->u_action), E_USER_WARNING); -				} -				fwrite($fp, $template_data); -				fclose($fp); -			} -			else +			if (in_array($dir, $this->reserved_style_names))  			{ -				$db->sql_transaction('begin'); - -				// If it's not stored in the db yet, then update the template setting and store all template files in the db -				if (!$template_info['template_storedb']) -				{ -					if ($super = $this->get_super('template', $template_id)) -					{ -						$this->store_in_db('template', $super['template_id']); -					} -					else -					{ -						$this->store_in_db('template', $template_id); -					} - -					add_log('admin', 'LOG_TEMPLATE_EDIT_DETAILS', $template_info['template_name']); -					$additional .= '<br />' . $user->lang['EDIT_TEMPLATE_STORED_DB']; -				} - -				// Update the template_data table entry for this template file -				$sql = 'UPDATE ' . STYLES_TEMPLATE_DATA_TABLE . " -					SET template_data = '" . $db->sql_escape($template_data) . "', template_mtime = " . time() . " -					WHERE template_id = $template_id -						AND template_filename = '" . $db->sql_escape($template_file) . "'"; -				$db->sql_query($sql); - -				$db->sql_transaction('commit'); +				$messages[] = $this->user->lang('STYLE_NAME_RESERVED', htmlspecialchars($dir)); +				continue;  			} -			// destroy the cached version of the template (filename without extension) -			$this->clear_template_cache($template_info, array(substr($template_file, 0, -5))); - -			$cache->destroy('sql', STYLES_TABLE); - -			add_log('admin', 'LOG_TEMPLATE_EDIT', $template_info['template_name'], $template_file); -			trigger_error($user->lang['TEMPLATE_FILE_UPDATED'] . $additional . adm_back_link($this->u_action . "&action=edit&id=$template_id&text_rows=$text_rows&template_file=$template_file")); -		} - -		// Generate a category array containing template filenames -		if (!$template_info['template_storedb']) -		{ -			$template_path = "{$phpbb_root_path}styles/{$template_info['template_path']}/template"; - -			$filelist = filelist($template_path, '', 'html'); -			$filelist[''] = array_diff($filelist[''], array('bbcode.html')); - -			if ($template_file) +			$found = false; +			foreach ($styles as &$style)  			{ -				if (!file_exists($template_path . "/$template_file") || !($template_data = file_get_contents($template_path . "/$template_file"))) +				// Check if: +				// 1. Directory matches directory we are looking for +				// 2. Style is not installed yet +				// 3. Style with same name or directory hasn't been installed already within this function +				if ($style['style_path'] == $dir && empty($style['_installed']) && !in_array($style['style_path'], $installed_dirs) && !in_array($style['style_name'], $installed_names))  				{ -					trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); +					// Install style +					$style['style_active'] = 1; +					$style['style_id'] = $this->install_style($style); +					$style['_installed'] = true; +					$found = true; +					$last_installed = $style['style_id']; +					$installed_names[] = $style['style_name']; +					$installed_dirs[] = $style['style_path']; +					$messages[] = sprintf($this->user->lang['STYLE_INSTALLED'], htmlspecialchars($style['style_name']));  				}  			} -		} -		else -		{ -			$sql = 'SELECT * -				FROM ' . STYLES_TEMPLATE_DATA_TABLE . " -				WHERE template_id = $template_id"; -			$result = $db->sql_query($sql); - -			$filelist = array('' => array()); -			while ($row = $db->sql_fetchrow($result)) +			if (!$found)  			{ -				$file_info = pathinfo($row['template_filename']); - -				if (($file_info['basename'] != 'bbcode') && ($file_info['extension'] == 'html')) -				{ -					if (($file_info['dirname'] == '.') || empty($file_info['dirname'])) -					{ -						$filelist[''][] = $row['template_filename']; -					} -					else -					{ -						$filelist[$file_info['dirname'] . '/'][] = $file_info['basename']; -					} -				} - -				if ($row['template_filename'] == $template_file) -				{ -					$template_data = $row['template_data']; -				} +				$messages[] = sprintf($this->user->lang['STYLE_NOT_INSTALLED'], htmlspecialchars($dir));  			} -			$db->sql_freeresult($result); -			unset($file_info);  		} -		if (empty($filelist[''])) +		// Show message +		if (!count($messages))  		{ -			trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); +			trigger_error($this->user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);  		} +		$message = implode('<br />', $messages); +		$message .= '<br /><br /><a href="' . $this->u_base_action . '&mode=style' . '">« ' . $this->user->lang('STYLE_INSTALLED_RETURN_INSTALLED_STYLES') . '</a>'; +		$message .= '<br /><br /><a href="' . $this->u_base_action . '&mode=install' . '">» ' . $this->user->lang('STYLE_INSTALLED_RETURN_UNINSTALLED_STYLES') . '</a>'; +		trigger_error($message, E_USER_NOTICE); +	} -		// Now create the categories -		$filelist_cats[''] = array(); -		foreach ($filelist as $pathfile => $file_ary) -		{ -			// Use the directory name as category name -			if (!empty($pathfile)) -			{ -				$filelist_cats[$pathfile] = array(); -				foreach ($file_ary as $file) -				{ -					$filelist_cats[$pathfile][$pathfile . $file] = $file; -				} -			} -			// or if it's in the main category use the word before the first underscore to group files -			else -			{ -				$cats = array(); -				foreach ($file_ary as $file) -				{ -					$cats[] = substr($file, 0, strpos($file, '_')); -					$filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file; -				} - -				$cats = array_values(array_unique($cats)); - -				// we don't need any single element categories so put them into the misc '' category -				for ($i = 0, $n = sizeof($cats); $i < $n; $i++) -				{ -					if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '') -					{ -						$filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]); -						unset($filelist_cats[$cats[$i]]); -					} -				} -				unset($cats); -			} -		} -		unset($filelist); +	/** +	* Confirm styles removal +	*/ +	protected function action_uninstall() +	{ +		// Get list of styles to uninstall +		$ids = $this->request_vars('id', 0, true); -		// Generate list of categorised template files -		$tpl_options = ''; -		ksort($filelist_cats); -		foreach ($filelist_cats as $category => $tpl_ary) +		// Check if confirmation box was submitted +		if (confirm_box(true))  		{ -			ksort($tpl_ary); - -			if (!empty($category)) -			{ -				$tpl_options .= '<option class="sep" value="">' . $category . '</option>'; -			} - -			foreach ($tpl_ary as $filename => $file) -			{ -				$selected = ($template_file == $filename) ? ' selected="selected"' : ''; -				$tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>'; -			} +			// Uninstall +			$this->action_uninstall_confirmed($ids, $this->request->variable('confirm_delete_files', false)); +			return;  		} -		$template->assign_vars(array( -			'S_EDIT_TEMPLATE'	=> true, -			'S_HIDDEN_FIELDS'	=> build_hidden_fields(array('template_file' => $template_file)), -			'S_TEMPLATES'		=> $tpl_options, - -			'U_ACTION'			=> $this->u_action . "&action=edit&id=$template_id&text_rows=$text_rows", -			'U_BACK'			=> $this->u_action, - -			'L_EDIT'			=> $user->lang['EDIT_TEMPLATE'], -			'L_EDIT_EXPLAIN'	=> $user->lang['EDIT_TEMPLATE_EXPLAIN'], -			'L_EDITOR'			=> $user->lang['TEMPLATE_EDITOR'], -			'L_EDITOR_HEIGHT'	=> $user->lang['TEMPLATE_EDITOR_HEIGHT'], -			'L_FILE'			=> $user->lang['TEMPLATE_FILE'], -			'L_SELECT'			=> $user->lang['SELECT_TEMPLATE'], -			'L_SELECTED'		=> $user->lang['SELECTED_TEMPLATE'], -			'L_SELECTED_FILE'	=> $user->lang['SELECTED_TEMPLATE_FILE'], - -			'SELECTED_TEMPLATE'	=> $template_info['template_name'], -			'TEMPLATE_FILE'		=> $template_file, -			'TEMPLATE_DATA'		=> utf8_htmlspecialchars($template_data), -			'TEXT_ROWS'			=> $text_rows) -		); +		// Confirm box +		$s_hidden = build_hidden_fields(array( +			'action'	=> 'uninstall', +			'ids'		=> $ids +		)); +		$this->template->assign_var('S_CONFIRM_DELETE', true); +		confirm_box(false, $this->user->lang['CONFIRM_UNINSTALL_STYLES'], $s_hidden, 'acp_styles.html'); + +		// Canceled - show styles list +		$this->frontend();  	}  	/** -	* Allows the admin to view cached versions of template files and clear single template cache files +	* Uninstall styles(s)  	* -	* @param int $template_id specifies which template's cache is shown +	* @param array $ids List of style IDs +	* @param bool $delete_files If true, script will attempt to remove files for selected styles  	*/ -	function template_cache($template_id) +	protected function action_uninstall_confirmed($ids, $delete_files)  	{ -		global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template; - -		$source		= str_replace('/', '.', request_var('source', '')); -		$file_ary	= array_diff(request_var('delete', array('')), array('')); -		$submit		= isset($_POST['submit']) ? true : false; - -		$sql = 'SELECT * -			FROM ' . STYLES_TEMPLATE_TABLE . " -			WHERE template_id = $template_id"; -		$result = $db->sql_query($sql); -		$template_row = $db->sql_fetchrow($result); -		$db->sql_freeresult($result); - -		if (!$template_row) -		{ -			trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); -		} - -		// User wants to delete one or more files ... -		if ($submit && $file_ary) -		{ -			$this->clear_template_cache($template_row, $file_ary); -			trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action . "&action=cache&id=$template_id")); -		} +		$default = $this->default_style; +		$uninstalled = array(); +		$messages = array(); -		$cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']); - -		// Someone wants to see the cached source ... so we'll highlight it, -		// add line numbers and indent it appropriately. This could be nasty -		// on larger source files ... -		if ($source && file_exists("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx")) +		// Check styles list +		foreach ($ids as $id)  		{ -			adm_page_header($user->lang['TEMPLATE_CACHE']); - -			$template->set_filenames(array( -				'body'	=> 'viewsource.html') -			); - -			$template->assign_vars(array( -				'FILENAME'	=> str_replace('.', '/', $source) . '.html') -			); - -			$code = str_replace(array("\r\n", "\r"), array("\n", "\n"), file_get_contents("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx")); - -			$conf = array('highlight.bg', 'highlight.comment', 'highlight.default', 'highlight.html', 'highlight.keyword', 'highlight.string'); -			foreach ($conf as $ini_var) +			if (!$id)  			{ -				@ini_set($ini_var, str_replace('highlight.', 'syntax', $ini_var)); +				trigger_error($this->user->lang['INVALID_STYLE_ID'] . adm_back_link($this->u_action), E_USER_WARNING);  			} - -			$marker = 'MARKER' . time(); -			$code = highlight_string(str_replace("\n", $marker, $code), true); -			$code = str_replace($marker, "\n", $code); -			$str_from = array('<span style="color: ', '<font color="syntax', '</font>', '<code>', '</code>','[', ']', '.', ':'); -			$str_to = array('<span class="', '<span class="syntax', '</span>', '', '', '[', ']', '.', ':'); - -			$code = str_replace($str_from, $str_to, $code); -			$code = preg_replace('#^(<span class="[a-z_]+">)\n?(.*?)\n?(</span>)$#ism', '$1$2$3', $code); -			$code = substr($code, strlen('<span class="syntaxhtml">')); -			$code = substr($code, 0, -1 * strlen('</ span>')); -			$code = explode("\n", $code); - -			foreach ($code as $key => $line) +			if ($id == $default)  			{ -				$template->assign_block_vars('source', array( -					'LINENUM'	=> $key + 1, -					'LINE'		=> preg_replace('#([^ ;]) ([^ &])#', '$1 $2', $line)) -				); -				unset($code[$key]); +				trigger_error($this->user->lang['UNINSTALL_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING);  			} - -			adm_page_footer(); +			$uninstalled[$id] = false;  		} -		$filemtime = array(); -		if ($template_row['template_storedb']) -		{ -			$ids = array(); -			if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id']) -			{ -				$ids[] = $template_row['template_inherits_id']; -			} -			$ids[] = $template_row['template_id']; - -			$filemtime 			= array(); -			$file_template_db	= array(); - -			foreach ($ids as $id) -			{ -				$sql = 'SELECT template_filename, template_mtime -					FROM ' . STYLES_TEMPLATE_DATA_TABLE . " -					WHERE template_id = $id"; -				$result = $db->sql_query($sql); - -				while ($row = $db->sql_fetchrow($result)) -				{ -					$filemtime[$row['template_filename']] = $row['template_mtime']; -					$file_template_db[$row['template_filename']] = $id; -				} -				$db->sql_freeresult($result); -			} -		} +		// Order by reversed style_id, so parent styles would be removed after child styles +		// This way parent and child styles can be removed in same function call +		$sql = 'SELECT * +			FROM ' . STYLES_TABLE . ' +			WHERE style_id IN (' . implode(', ', $ids) . ') +			ORDER BY style_id DESC'; +		$result = $this->db->sql_query($sql); -		// Get a list of cached template files and then retrieve additional information about them -		$file_ary = $this->template_cache_filelist($template_row['template_path']); +		$rows = $this->db->sql_fetchrowset($result); +		$this->db->sql_freeresult($result); -		foreach ($file_ary as $file) +		// Uinstall each style +		$uninstalled = array(); +		foreach ($rows as $style)  		{ -			$file		= str_replace('/', '.', $file); - -			// perform some dirty guessing to get the path right. -			// We assume that three dots in a row were '../' -			$tpl_file	= str_replace('.', '/', $file); -			$tpl_file	= str_replace('///', '../', $tpl_file); +			$result = $this->uninstall_style($style, $delete_files); -			$filename = "{$cache_prefix}_$file.html.$phpEx"; - -			if (!file_exists("{$phpbb_root_path}cache/$filename")) +			if (is_string($result))  			{ +				$messages[] = $result;  				continue;  			} +			$messages[] = sprintf($this->user->lang['STYLE_UNINSTALLED'], $style['style_name']); +			$uninstalled[] = $style['style_name']; -			$file_tpl = "{$phpbb_root_path}styles/{$template_row['template_path']}/template/$tpl_file.html"; -			$inherited = false; - -			if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id']) -			{ -				if (!$template_row['template_storedb']) -				{ -					if (!file_exists($file_tpl)) -					{ -						$file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html"; -						$inherited = true; -					} -				} -				else -				{ -					if ($file_template_db[$file . '.html'] == $template_row['template_inherits_id']) -					{ -						$file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html"; -						$inherited = true; -					} -				} -			} - -			// Correct the filename if it is stored in database and the file is in a subfolder. -			if ($template_row['template_storedb']) +			// Attempt to delete files +			if ($delete_files)  			{ -				$file = str_replace('.', '/', $file); +				$messages[] = sprintf($this->user->lang[$this->delete_style_files($style['style_path']) ? 'DELETE_STYLE_FILES_SUCCESS' : 'DELETE_STYLE_FILES_FAILED'], $style['style_name']);  			} +		} -			$template->assign_block_vars('file', array( -				'U_VIEWSOURCE'	=> $this->u_action . "&action=cache&id=$template_id&source=$file", +		if (empty($messages)) +		{ +			// Nothing to uninstall? +			trigger_error($this->user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); +		} -				'CACHED'		=> $user->format_date(filemtime("{$phpbb_root_path}cache/$filename")), -				'FILENAME'		=> $file, -				'FILENAME_PATH'	=> $file_tpl, -				'FILESIZE'		=> get_formatted_filesize(filesize("{$phpbb_root_path}cache/$filename")), -				'MODIFIED'		=> $user->format_date((!$template_row['template_storedb']) ? filemtime($file_tpl) : $filemtime[$file . '.html'])) -			); +		// Log action +		if (count($uninstalled)) +		{ +			add_log('admin', 'LOG_STYLE_DELETE', implode(', ', $uninstalled));  		} -		unset($filemtime); -		$template->assign_vars(array( -			'S_CACHE'			=> true, -			'S_TEMPLATE'		=> true, +		// Clear cache +		$this->cache->purge(); -			'U_ACTION'			=> $this->u_action . "&action=cache&id=$template_id", -			'U_BACK'			=> $this->u_action) -		); +		// Show message +		trigger_error(implode('<br />', $messages) . adm_back_link($this->u_action), E_USER_NOTICE);  	}  	/** -	* Provides a css editor and a basic easier to use stylesheet editing tool for less experienced (or lazy) users -	* -	* @param int $theme_id specifies which theme is being edited +	* Activate styles  	*/ -	function edit_theme($theme_id) +	protected function action_activate()  	{ -		global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode; - -		$this->page_title = 'EDIT_THEME'; - -		$filelist = $filelist_cats = array(); - -		$theme_data		= utf8_normalize_nfc(request_var('template_data', '', true)); -		$theme_data		= htmlspecialchars_decode($theme_data); -		$theme_file		= utf8_normalize_nfc(request_var('template_file', '', true)); -		$text_rows		= max(5, min(999, request_var('text_rows', 20))); -		$save_changes	= (isset($_POST['save'])) ? true : false; - -		// make sure theme_file path doesn't go upwards -		$theme_file = str_replace('..', '.', $theme_file); - -		// Retrieve some information about the theme -		$sql = 'SELECT theme_storedb, theme_path, theme_name, theme_data -			FROM ' . STYLES_THEME_TABLE . " -			WHERE theme_id = $theme_id"; -		$result = $db->sql_query($sql); - -		if (!($theme_info = $db->sql_fetchrow($result))) -		{ -			trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); -		} -		$db->sql_freeresult($result); - -		// save changes to the theme if the user submitted any -		if ($save_changes) -		{ -			// Get the filesystem location of the current file -			$file = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme/$theme_file"; -			$additional = ''; -			$message = $user->lang['THEME_UPDATED']; - -			// If the theme is stored on the filesystem try to write the file else store it in the database -			if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($file) && phpbb_is_writable($file)) -			{ -				if (!($fp = @fopen($file, 'wb'))) -				{ -					trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); -				} -				fwrite($fp, $theme_data); -				fclose($fp); -			} -			else -			{ -				// Write stylesheet to db -				$sql_ary = array( -					'theme_mtime'		=> time(), -					'theme_storedb'		=> 1, -					'theme_data'		=> $this->db_theme_data($theme_info, $theme_data), -				); -				$sql = 'UPDATE ' . STYLES_THEME_TABLE . ' -					SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' -					WHERE theme_id = ' . $theme_id; -				$db->sql_query($sql); - -				$cache->destroy('sql', STYLES_THEME_TABLE); - -				// notify the user if the theme was not stored in the db before his modification -				if (!$theme_info['theme_storedb']) -				{ -					add_log('admin', 'LOG_THEME_EDIT_DETAILS', $theme_info['theme_name']); -					$message .= '<br />' . $user->lang['EDIT_THEME_STORED_DB']; -				} -			} -			$cache->destroy('sql', STYLES_THEME_TABLE); -			add_log('admin', (!$theme_info['theme_storedb']) ? 'LOG_THEME_EDIT_FILE' : 'LOG_THEME_EDIT', $theme_info['theme_name'], (!$theme_info['theme_storedb']) ? $theme_file : ''); +		// Get list of styles to activate +		$ids = $this->request_vars('id', 0, true); -			trigger_error($message . adm_back_link($this->u_action . "&action=edit&id=$theme_id&template_file=$theme_file&text_rows=$text_rows")); -		} +		// Activate styles +		$sql = 'UPDATE ' . STYLES_TABLE . ' +			SET style_active = 1 +			WHERE style_id IN (' . implode(', ', $ids) . ')'; +		$this->db->sql_query($sql); -		// Generate a category array containing theme filenames -		if (!$theme_info['theme_storedb']) -		{ -			$theme_path = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme"; +		// Purge cache +		$this->cache->destroy('sql', STYLES_TABLE); -			$filelist = filelist($theme_path, '', 'css'); +		// Show styles list +		$this->frontend(); +	} -			if ($theme_file) -			{ -				if (!file_exists($theme_path . "/$theme_file") || !($theme_data = file_get_contents($theme_path . "/$theme_file"))) -				{ -					trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); -				} -			} -		} -		else -		{ -			$theme_data = &$theme_info['theme_data']; -		} +	/** +	* Deactivate styles +	*/ +	protected function action_deactivate() +	{ +		// Get list of styles to deactivate +		$ids = $this->request_vars('id', 0, true); -		// Now create the categories -		$filelist_cats[''] = array(); -		foreach ($filelist as $pathfile => $file_ary) +		// Check for default style +		foreach ($ids as $id)  		{ -			// Use the directory name as category name -			if (!empty($pathfile)) -			{ -				$filelist_cats[$pathfile] = array(); -				foreach ($file_ary as $file) -				{ -					$filelist_cats[$pathfile][$pathfile . $file] = $file; -				} -			} -			// or if it's in the main category use the word before the first underscore to group files -			else +			if ($id == $this->default_style)  			{ -				$cats = array(); -				foreach ($file_ary as $file) -				{ -					$cats[] = substr($file, 0, strpos($file, '_')); -					$filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file; -				} - -				$cats = array_values(array_unique($cats)); - -				// we don't need any single element categories so put them into the misc '' category -				for ($i = 0, $n = sizeof($cats); $i < $n; $i++) -				{ -					if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '') -					{ -						$filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]); -						unset($filelist_cats[$cats[$i]]); -					} -				} -				unset($cats); +				trigger_error($this->user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING);  			}  		} -		unset($filelist); -		// Generate list of categorised theme files -		$tpl_options = ''; -		ksort($filelist_cats); -		foreach ($filelist_cats as $category => $tpl_ary) -		{ -			ksort($tpl_ary); +		// Reset default style for users who use selected styles +		$sql = 'UPDATE ' . USERS_TABLE . ' +			SET user_style = 0 +			WHERE user_style IN (' . implode(', ', $ids) . ')'; +		$this->db->sql_query($sql); -			if (!empty($category)) -			{ -				$tpl_options .= '<option class="sep" value="">' . $category . '</option>'; -			} +		// Deactivate styles +		$sql = 'UPDATE ' . STYLES_TABLE . ' +			SET style_active = 0 +			WHERE style_id IN (' . implode(', ', $ids) . ')'; +		$this->db->sql_query($sql); -			foreach ($tpl_ary as $filename => $file) -			{ -				$selected = ($theme_file == $filename) ? ' selected="selected"' : ''; -				$tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>'; -			} -		} +		// Purge cache +		$this->cache->destroy('sql', STYLES_TABLE); -		$template->assign_vars(array( -			'S_EDIT_THEME'		=> true, -			'S_HIDDEN_FIELDS'	=> build_hidden_fields(array('template_file' => $theme_file)), -			'S_THEME_IN_DB'		=> $theme_info['theme_storedb'], -			'S_TEMPLATES'		=> $tpl_options, - -			'U_ACTION'			=> $this->u_action . "&action=edit&id=$theme_id&text_rows=$text_rows", -			'U_BACK'			=> $this->u_action, - -			'L_EDIT'			=> $user->lang['EDIT_THEME'], -			'L_EDIT_EXPLAIN'	=> $user->lang['EDIT_THEME_EXPLAIN'], -			'L_EDITOR'			=> $user->lang['THEME_EDITOR'], -			'L_EDITOR_HEIGHT'	=> $user->lang['THEME_EDITOR_HEIGHT'], -			'L_FILE'			=> $user->lang['THEME_FILE'], -			'L_SELECT'			=> $user->lang['SELECT_THEME'], -			'L_SELECTED'		=> $user->lang['SELECTED_THEME'], -			'L_SELECTED_FILE'	=> $user->lang['SELECTED_THEME_FILE'], - -			'SELECTED_TEMPLATE'	=> $theme_info['theme_name'], -			'TEMPLATE_FILE'		=> $theme_file, -			'TEMPLATE_DATA'		=> utf8_htmlspecialchars($theme_data), -			'TEXT_ROWS'			=> $text_rows) -		); +		// Show styles list +		$this->frontend();  	}  	/** -	* Edit imagesets -	* -	* @param int $imageset_id specifies which imageset is being edited +	* Show style details  	*/ -	function edit_imageset($imageset_id) +	protected function action_details()  	{ -		global $db, $user, $phpbb_root_path, $cache, $template; - -		$this->page_title = 'EDIT_IMAGESET'; - -		if (!$imageset_id) +		$id = $this->request->variable('id', 0); +		if (!$id)  		{ -			trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); +			trigger_error($this->user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);  		} -		$update		= (isset($_POST['update'])) ? true : false; - -		$imgname	= request_var('imgname', 'site_logo'); -		$imgname	= preg_replace('#[^a-z0-9\-+_]#i', '', $imgname); -		$sql_extra = $imgnamelang = ''; +		// Get all styles +		$styles = $this->get_styles(); +		usort($styles, array($this, 'sort_styles')); -		$sql = 'SELECT imageset_path, imageset_name -			FROM ' . STYLES_IMAGESET_TABLE . " -			WHERE imageset_id = $imageset_id"; -		$result = $db->sql_query($sql); -		$imageset_row = $db->sql_fetchrow($result); -		$db->sql_freeresult($result); - -		if (!$imageset_row) +		// Find current style +		$style = false; +		foreach ($styles as $row)  		{ -			trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); -		} - -		$imageset_path		= $imageset_row['imageset_path']; -		$imageset_name		= $imageset_row['imageset_name']; - -		if (strpos($imgname, '-') !== false) -		{ -			list($imgname, $imgnamelang) = explode('-', $imgname); -			$sql_extra = " AND image_lang IN ('" . $db->sql_escape($imgnamelang) . "', '')"; -		} - -		$sql = 'SELECT image_filename, image_width, image_height, image_lang, image_id -			FROM ' . STYLES_IMAGESET_DATA_TABLE . " -			WHERE imageset_id = $imageset_id -				AND image_name = '" . $db->sql_escape($imgname) . "'$sql_extra"; -		$result = $db->sql_query($sql); -		$imageset_data_row = $db->sql_fetchrow($result); -		$db->sql_freeresult($result); - -		$image_filename	= $imageset_data_row['image_filename']; -		$image_width	= $imageset_data_row['image_width']; -		$image_height	= $imageset_data_row['image_height']; -		$image_lang		= $imageset_data_row['image_lang']; -		$image_id		= $imageset_data_row['image_id']; -		$imgsize		= ($imageset_data_row['image_width'] && $imageset_data_row['image_height']) ? 1 : 0; - -		// Check to see whether the selected image exists in the table -		$valid_name = ($update) ? false : true; - -		foreach ($this->imageset_keys as $category => $img_ary) -		{ -			if (in_array($imgname, $img_ary)) +			if ($row['style_id'] == $id)  			{ -				$valid_name = true; +				$style = $row;  				break;  			}  		} -		if ($update && isset($_POST['imgpath']) && $valid_name) +		if ($style === false)  		{ -			// If imgwidth and imgheight are non-zero grab the actual size -			// from the image itself ... we ignore width settings for the poll center image -			$imgwidth	= request_var('imgwidth', 0); -			$imgheight	= request_var('imgheight', 0); -			$imgsize	= request_var('imgsize', 0); -			$imgpath	= request_var('imgpath', ''); -			$imgpath	= str_replace('..', '.', $imgpath); - -			// If no dimensions selected, we reset width and height to 0 ;) -			if (!$imgsize) -			{ -				$imgwidth = $imgheight = 0; -			} - -			$imglang = ''; +			trigger_error($this->user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); +		} -			if ($imgpath && !file_exists("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath")) -			{ -				trigger_error($user->lang['NO_IMAGE_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING); -			} +		// Find all available parent styles +		$list = $this->find_possible_parents($styles, $id); -			// Determine width/height. If dimensions included and no width/height given, we detect them automatically... -			if ($imgsize && $imgpath) -			{ -				if (!$imgwidth || !$imgheight) -				{ -					list($imgwidth_file, $imgheight_file) = getimagesize("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath"); -					$imgwidth = ($imgwidth) ? $imgwidth : $imgwidth_file; -					$imgheight = ($imgheight) ? $imgheight : $imgheight_file; -				} -				$imgwidth	= ($imgname != 'poll_center') ? (int) $imgwidth : 0; -				$imgheight	= (int) $imgheight; -			} +		// Add form key +		$form_key = 'acp_styles'; +		add_form_key($form_key); -			if (strpos($imgpath, '/') !== false) -			{ -				list($imglang, $imgfilename) = explode('/', $imgpath); -			} -			else +		// Change data +		if ($this->request->variable('update', false)) +		{ +			if (!check_form_key($form_key))  			{ -				$imgfilename = $imgpath; +				trigger_error($this->user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);  			} -			$sql_ary = array( -				'image_filename'	=> (string) $imgfilename, -				'image_width'		=> (int) $imgwidth, -				'image_height'		=> (int) $imgheight, -				'image_lang'		=> (string) $imglang, +			$update = array( +				'style_name'		=> trim($this->request->variable('style_name', $style['style_name'])), +				'style_parent_id'	=> $this->request->variable('style_parent', (int) $style['style_parent_id']), +				'style_active'		=> $this->request->variable('style_active', (int) $style['style_active']),  			); +			$update_action = $this->u_action . '&action=details&id=' . $id; -			// already exists -			if ($imageset_data_row) -			{ -				$sql = 'UPDATE ' . STYLES_IMAGESET_DATA_TABLE . ' -					SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " -					WHERE image_id = $image_id"; -				$db->sql_query($sql); -			} -			// does not exist -			else if (!$imageset_data_row) +			// Check style name +			if ($update['style_name'] != $style['style_name'])  			{ -				$sql_ary['image_name']	= $imgname; -				$sql_ary['imageset_id']	= (int) $imageset_id; -				$db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); -			} - -			$cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); - -			add_log('admin', 'LOG_IMAGESET_EDIT', $imageset_name); - -			$template->assign_var('SUCCESS', true); - -			$image_filename = $imgfilename; -			$image_width	= $imgwidth; -			$image_height	= $imgheight; -			$image_lang		= $imglang; -		} - -		$imglang = ''; -		$imagesetlist = array('nolang' => array(), 'lang' => array()); -		$langs = array(); - -		$dir = "{$phpbb_root_path}styles/$imageset_path/imageset"; -		$dp = @opendir($dir); - -		if ($dp) -		{ -			while (($file = readdir($dp)) !== false) -			{ -				if ($file[0] != '.' && strtoupper($file) != 'CVS' && !is_file($dir . '/' . $file) && !is_link($dir . '/' . $file)) +				if (!strlen($update['style_name']))  				{ -					$langs[] = $file; +					trigger_error($this->user->lang['STYLE_ERR_STYLE_NAME'] . adm_back_link($update_action), E_USER_WARNING);  				} -				else if (preg_match('#\.(?:gif|jpg|png)$#', $file)) +				foreach ($styles as $row)  				{ -					$imagesetlist['nolang'][] = $file; +					if ($row['style_name'] == $update['style_name']) +					{ +						trigger_error($this->user->lang['STYLE_ERR_NAME_EXIST'] . adm_back_link($update_action), E_USER_WARNING); +					}  				}  			} - -			if ($sql_extra) +			else  			{ -				$dp2 = @opendir("$dir/$imgnamelang"); +				unset($update['style_name']); +			} -				if ($dp2) +			// Check parent style id +			if ($update['style_parent_id'] != $style['style_parent_id']) +			{ +				if ($update['style_parent_id'] != 0)  				{ -					while (($file2 = readdir($dp2)) !== false) +					$found = false; +					foreach ($list as $row)  					{ -						if (preg_match('#\.(?:gif|jpg|png)$#', $file2)) +						if ($row['style_id'] == $update['style_parent_id'])  						{ -							$imagesetlist['lang'][] = "$imgnamelang/$file2"; +							$found = true; +							$update['style_parent_tree'] = ($row['style_parent_tree'] != '' ? $row['style_parent_tree'] . '/' : '') . $row['style_path']; +							break;  						}  					} -					closedir($dp2); -				} -			} -			closedir($dp); -		} - -		// Generate list of image options -		$img_options = ''; -		foreach ($this->imageset_keys as $category => $img_ary) -		{ -			$template->assign_block_vars('category', array( -				'NAME'			=> $user->lang['IMG_CAT_' . strtoupper($category)] -			)); - -			foreach ($img_ary as $img) -			{ -				if ($category == 'buttons') -				{ -					foreach ($langs as $language) +					if (!$found)  					{ -						$template->assign_block_vars('category.images', array( -							'SELECTED'			=> ($img == $imgname && $language == $imgnamelang), -							'VALUE'				=> $img . '-' . $language, -							'TEXT'				=> $user->lang['IMG_' . strtoupper($img)] . ' [ ' . $language . ' ]' -						)); +						trigger_error($this->user->lang['STYLE_ERR_INVALID_PARENT'] . adm_back_link($update_action), E_USER_WARNING);  					}  				}  				else  				{ -					$template->assign_block_vars('category.images', array( -						'SELECTED'			=> ($img == $imgname), -						'VALUE'				=> $img, -						'TEXT'				=> (($category == 'custom') ? $img : $user->lang['IMG_' . strtoupper($img)]) -					)); +					$update['style_parent_tree'] = '';  				}  			} -		} - -		// Make sure the list of possible images is sorted alphabetically -		sort($imagesetlist['lang']); -		sort($imagesetlist['nolang']); - -		$image_found = false; -		$img_val = ''; -		foreach ($imagesetlist as $type => $img_ary) -		{ -			if ($type !== 'lang' || $sql_extra) +			else  			{ -				$template->assign_block_vars('imagesetlist', array( -					'TYPE'	=> ($type == 'lang') -				)); +				unset($update['style_parent_id']);  			} -			foreach ($img_ary as $img) +			// Check style_active +			if ($update['style_active'] != $style['style_active'])  			{ -				$imgtext = preg_replace('/^([^\/]+\/)/', '', $img); -				$selected = (!empty($imgname) && strpos($image_filename, $imgtext) !== false); -				if ($selected) +				if (!$update['style_active'] && $this->default_style == $style['style_id'])  				{ -					$image_found = true; -					$img_val = htmlspecialchars($img); +					trigger_error($this->user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($update_action), E_USER_WARNING);  				} -				$template->assign_block_vars('imagesetlist.images', array( -					'SELECTED'			=> $selected, -					'TEXT'				=> $imgtext, -					'VALUE'				=> htmlspecialchars($img) -				));  			} -		} - -		$imgsize_bool = (!empty($imgname) && $image_width && $image_height) ? true : false; -		$image_request = '../styles/' . $imageset_path . '/imageset/' . ($image_lang ? $imgnamelang . '/' : '') . $image_filename; - -		$template->assign_vars(array( -			'S_EDIT_IMAGESET'	=> true, -			'L_TITLE'			=> $user->lang[$this->page_title], -			'L_EXPLAIN'			=> $user->lang[$this->page_title . '_EXPLAIN'], -			'IMAGE_OPTIONS'		=> $img_options, -			'IMAGE_SIZE'		=> $image_width, -			'IMAGE_HEIGHT'		=> $image_height, -			'IMAGE_REQUEST'		=> (empty($image_filename)) ? 'images/no_image.png' : $image_request, -			'U_ACTION'			=> $this->u_action . "&action=edit&id=$imageset_id", -			'U_BACK'			=> $this->u_action, -			'NAME'				=> $imageset_name, -			'A_NAME'			=> addslashes($imageset_name), -			'PATH'				=> $imageset_path, -			'A_PATH'			=> addslashes($imageset_path), -			'ERROR'				=> !$valid_name, -			'IMG_SRC'			=> ($image_found) ? '../styles/' . $imageset_path . '/imageset/' . $img_val : 'images/no_image.png', -			'IMAGE_SELECT'		=> $image_found -		)); -	} - -	/** -	* Remove style/template/theme/imageset -	*/ -	function remove($mode, $style_id) -	{ -		global $db, $template, $user, $phpbb_root_path, $cache, $config; - -		$new_id = request_var('new_id', 0); -		$update = (isset($_POST['update'])) ? true : false; -		$sql_where = ''; - -		switch ($mode) -		{ -			case 'style': -				$sql_from = STYLES_TABLE; -				$sql_select = 'style_id, style_name, template_id, theme_id, imageset_id'; -				$sql_where = 'AND style_active = 1'; -			break; - -			case 'template': -				$sql_from = STYLES_TEMPLATE_TABLE; -				$sql_select = 'template_id, template_name, template_path, template_storedb'; -			break; - -			case 'theme': -				$sql_from = STYLES_THEME_TABLE; -				$sql_select = 'theme_id, theme_name, theme_path, theme_storedb'; -			break; - -			case 'imageset': -				$sql_from = STYLES_IMAGESET_TABLE; -				$sql_select = 'imageset_id, imageset_name, imageset_path'; -			break; -		} - -		if ($mode === 'template' && ($conflicts = $this->check_inheritance($mode, $style_id))) -		{ -			$l_type = strtoupper($mode); -			$msg = $user->lang[$l_type . '_DELETE_DEPENDENT']; -			foreach ($conflicts as $id => $values) +			else  			{ -				$msg .= '<br />' . $values['template_name']; +				unset($update['style_active']);  			} -			trigger_error($msg . adm_back_link($this->u_action), E_USER_WARNING); -		} - -		$l_prefix = strtoupper($mode); - -		$sql = "SELECT $sql_select -			FROM $sql_from -			WHERE {$mode}_id = $style_id"; -		$result = $db->sql_query($sql); -		$style_row = $db->sql_fetchrow($result); -		$db->sql_freeresult($result); - -		if (!$style_row) -		{ -			trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); -		} - -		$s_only_component = $this->display_component_options($mode, $style_row[$mode . '_id'], $style_row); - -		if ($s_only_component) -		{ -			trigger_error($user->lang['ONLY_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); -		} - -		if ($update) -		{ -			if ($mode == 'style') +			// Update data +			if (count($update))  			{ -				$sql = "DELETE FROM $sql_from -					WHERE {$mode}_id = $style_id"; -				$db->sql_query($sql); - -				$sql = 'UPDATE ' . USERS_TABLE . " -					SET user_style = $new_id -					WHERE user_style = $style_id"; -				$db->sql_query($sql); +				$sql = 'UPDATE ' . STYLES_TABLE . ' +					SET ' . $this->db->sql_build_array('UPDATE', $update) . " +					WHERE style_id = $id"; +				$this->db->sql_query($sql); -				$sql = 'UPDATE ' . FORUMS_TABLE . " -					SET forum_style = $new_id -					WHERE forum_style = $style_id"; -				$db->sql_query($sql); +				$style = array_merge($style, $update); -				if ($style_id == $config['default_style']) +				if (isset($update['style_parent_id']))  				{ -					set_config('default_style', $new_id); +					// Update styles tree +					$styles = $this->get_styles(); +					if ($this->update_styles_tree($styles, $style)) +					{ +						// Something was changed in styles tree, purge all cache +						$this->cache->purge(); +					}  				} +				add_log('admin', 'LOG_STYLE_EDIT_DETAILS', $style['style_name']); +			} -				// Remove the components -				$components = array('template', 'theme', 'imageset'); -				foreach ($components as $component) +			// Update default style +			$default = $this->request->variable('style_default', 0); +			if ($default) +			{ +				if (!$style['style_active'])  				{ -					$new_id = request_var('new_' . $component . '_id', 0); -					$component_id = $style_row[$component . '_id']; -					$this->remove_component($component, $component_id, $new_id, $style_id); +					trigger_error($this->user->lang['STYLE_DEFAULT_CHANGE_INACTIVE'] . adm_back_link($update_action), E_USER_WARNING);  				} -			} -			else -			{ -				$this->remove_component($mode, $style_id, $new_id); +				set_config('default_style', $id); +				$this->cache->purge();  			} -			$cache->destroy('sql', STYLES_TABLE); - -			add_log('admin', 'LOG_' . $l_prefix . '_DELETE', $style_row[$mode . '_name']); -			$message = ($mode != 'style') ? $l_prefix . '_DELETED_FS' : $l_prefix . '_DELETED'; -			trigger_error($user->lang[$message] . adm_back_link($this->u_action)); +			// Show styles list +			$this->frontend(); +			return;  		} -		$this->page_title = 'DELETE_' . $l_prefix; - -		$template->assign_vars(array( -			'S_DELETE'			=> true, +		// Show page title +		$this->welcome_message('ACP_STYLES', null); -			'L_TITLE'			=> $user->lang[$this->page_title], -			'L_EXPLAIN'			=> $user->lang[$this->page_title . '_EXPLAIN'], -			'L_NAME'			=> $user->lang[$l_prefix . '_NAME'], -			'L_REPLACE'			=> $user->lang['REPLACE_' . $l_prefix], -			'L_REPLACE_EXPLAIN'	=> $user->lang['REPLACE_' . $l_prefix . '_EXPLAIN'], - -			'U_ACTION'		=> $this->u_action . "&action=delete&id=$style_id", -			'U_BACK'		=> $this->u_action, +		// Show parent styles +		foreach ($list as $row) +		{ +			$this->template->assign_block_vars('parent_styles', array( +				'STYLE_ID'		=> $row['style_id'], +				'STYLE_NAME'	=> htmlspecialchars($row['style_name']), +				'LEVEL'			=> $row['level'], +				'SPACER'		=> str_repeat('  ', $row['level']), +				) +			); +		} -			'NAME'			=> $style_row[$mode . '_name'], +		// Show style details +		$this->template->assign_vars(array( +			'S_STYLE_DETAILS'	=> true, +			'STYLE_ID'			=> $style['style_id'], +			'STYLE_NAME'		=> htmlspecialchars($style['style_name']), +			'STYLE_PATH'		=> htmlspecialchars($style['style_path']), +			'STYLE_COPYRIGHT'	=> strip_tags($style['style_copyright']), +			'STYLE_PARENT'		=> $style['style_parent_id'], +			'S_STYLE_ACTIVE'	=> $style['style_active'], +			'S_STYLE_DEFAULT'	=> ($style['style_id'] == $this->default_style)  			)  		); - -		if ($mode == 'style') -		{ -			$template->assign_vars(array( -				'S_DELETE_STYLE'		=> true, -			)); -		}  	}  	/** -	* Remove template/theme/imageset entry from the database +	* List installed styles  	*/ -	function remove_component($component, $component_id, $new_id, $style_id = false) +	protected function show_installed()  	{ -		global $db; - -		if (($new_id == 0) || ($component === 'template' && ($conflicts = $this->check_inheritance($component, $component_id)))) -		{ -			// We can not delete the template, as the user wants to keep the component or an other template is inheriting from this one. -			return; -		} +		// Get all installed styles +		$styles = $this->get_styles(); -		$component_in_use = array(); -		if ($component != 'style') +		if (!count($styles))  		{ -			$component_in_use = $this->component_in_use($component, $component_id, $style_id); +			trigger_error($this->user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);  		} -		if (($new_id == -1) && !empty($component_in_use)) -		{ -			// We can not delete the component, as it is still in use -			return; -		} +		usort($styles, array($this, 'sort_styles')); -		if ($component == 'imageset') -		{ -			$sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " -				WHERE imageset_id = $component_id"; -			$db->sql_query($sql); -		} +		// Get users +		$users = $this->get_users(); -		switch ($component) +		// Add users counter to rows +		foreach ($styles as &$style)  		{ -			case 'template': -				$sql_from = STYLES_TEMPLATE_TABLE; -			break; - -			case 'theme': -				$sql_from = STYLES_THEME_TABLE; -			break; - -			case 'imageset': -				$sql_from = STYLES_IMAGESET_TABLE;; -			break; +			$style['_users'] = isset($users[$style['style_id']]) ? $users[$style['style_id']] : 0;  		} -		$sql = "DELETE FROM $sql_from -			WHERE {$component}_id = $component_id"; -		$db->sql_query($sql); - -		$sql = 'UPDATE ' . STYLES_TABLE . " -			SET {$component}_id = $new_id -			WHERE {$component}_id = $component_id"; -		$db->sql_query($sql); -	} - -	/** -	* Display the options which can be used to replace a style/template/theme/imageset -	* -	* @return boolean Returns true if the component is the only component and can not be deleted. -	*/ -	function display_component_options($component, $component_id, $style_row = false, $style_id = false) -	{ -		global $db, $template, $user; - -		$is_only_component = true; -		$component_in_use = array(); -		if ($component != 'style') -		{ -			$component_in_use = $this->component_in_use($component, $component_id, $style_id); -		} +		// Set up styles list variables +		// Addons should increase this number and update template variable +		$this->styles_list_cols = 4; +		$this->template->assign_var('STYLES_LIST_COLS', $this->styles_list_cols); -		$sql_where = ''; -		switch ($component) -		{ -			case 'style': -				$sql_from = STYLES_TABLE; -				$sql_where = 'WHERE style_active = 1'; -			break; - -			case 'template': -				$sql_from = STYLES_TEMPLATE_TABLE; -				$sql_where = 'WHERE template_inherits_id <> ' . $component_id; -			break; - -			case 'theme': -				$sql_from = STYLES_THEME_TABLE; -			break; - -			case 'imageset': -				$sql_from = STYLES_IMAGESET_TABLE; -			break; -		} +		// Show styles list +		$this->show_styles_list($styles, 0, 0); -		$s_options = ''; -		if (($component != 'style') && empty($component_in_use)) +		// Show styles with invalid inherits_id +		foreach ($styles as $style)  		{ -			// If it is not in use, there must be another component -			$is_only_component = false; - -			$sql = "SELECT {$component}_id, {$component}_name -				FROM $sql_from -				WHERE {$component}_id = {$component_id}"; -			$result = $db->sql_query($sql); -			$row = $db->sql_fetchrow($result); -			$db->sql_freeresult($result); - -			$s_options .= '<option value="-1" selected="selected">' . $user->lang['DELETE_' . strtoupper($component)] . '</option>'; -			$s_options .= '<option value="0">' . sprintf($user->lang['KEEP_' . strtoupper($component)], $row[$component . '_name']) . '</option>'; -		} -		else -		{ -			$sql = "SELECT {$component}_id, {$component}_name -				FROM $sql_from -				$sql_where -				ORDER BY {$component}_name ASC"; -			$result = $db->sql_query($sql); - -			$s_keep_option = $s_options = ''; -			while ($row = $db->sql_fetchrow($result)) -			{ -				if ($row[$component . '_id'] != $component_id) -				{ -					$is_only_component = false; -					$s_options .= '<option value="' . $row[$component . '_id'] . '">' . sprintf($user->lang['REPLACE_WITH_OPTION'], $row[$component . '_name']) . '</option>'; -				} -				else if ($component != 'style') -				{ -					$s_keep_option = '<option value="0" selected="selected">' . sprintf($user->lang['KEEP_' . strtoupper($component)], $row[$component . '_name']) . '</option>'; -				} -			} -			$db->sql_freeresult($result); -			$s_options = $s_keep_option . $s_options; -		} - -		if (!$style_row) -		{ -			$template->assign_var('S_REPLACE_' . strtoupper($component) . '_OPTIONS', $s_options); -		} -		else -		{ -			$template->assign_var('S_REPLACE_OPTIONS', $s_options); -			if ($component == 'style') +			if (empty($style['_shown']))  			{ -				$components = array('template', 'theme', 'imageset'); -				foreach ($components as $component) -				{ -					$this->display_component_options($component, $style_row[$component . '_id'], false, $component_id, true); -				} +				$style['_note'] = sprintf($this->user->lang['REQUIRES_STYLE'], htmlspecialchars($style['style_parent_tree'])); +				$this->list_style($style, 0);  			}  		} -		return $is_only_component; -	} - -	/** -	* Check whether the component is still used by another style or component -	*/ -	function component_in_use($component, $component_id, $style_id = false) -	{ -		global $db; - -		$component_in_use = array(); +		// Add buttons +		$this->template->assign_block_vars('extra_actions', array( +				'ACTION_NAME'	=> 'activate', +				'L_ACTION'		=> $this->user->lang['STYLE_ACTIVATE'], +			) +		); -		if ($style_id) -		{ -			$sql = 'SELECT style_id, style_name -				FROM ' . STYLES_TABLE . " -				WHERE {$component}_id = {$component_id} -					AND style_id <> {$style_id} -				ORDER BY style_name ASC"; -		} -		else -		{ -			$sql = 'SELECT style_id, style_name -				FROM ' . STYLES_TABLE . " -				WHERE {$component}_id = {$component_id} -				ORDER BY style_name ASC"; -		} -		$result = $db->sql_query($sql); -		while ($row = $db->sql_fetchrow($result)) -		{ -			$component_in_use[] = $row['style_name']; -		} -		$db->sql_freeresult($result); +		$this->template->assign_block_vars('extra_actions', array( +				'ACTION_NAME'	=> 'deactivate', +				'L_ACTION'		=> $this->user->lang['STYLE_DEACTIVATE'], +			) +		); -		if ($component === 'template' && ($conflicts = $this->check_inheritance($component, $component_id))) +		if (isset($this->style_counters) && $this->style_counters['total'] > 1)  		{ -			foreach ($conflicts as $temp_id => $conflict_data) -			{ -				$component_in_use[] = $conflict_data['template_name']; -			} +			$this->template->assign_block_vars('extra_actions', array( +					'ACTION_NAME'	=> 'uninstall', +					'L_ACTION'		=> $this->user->lang['STYLE_UNINSTALL'], +				) +			);  		} - -		return $component_in_use;  	}  	/** -	* Export style or style elements +	* Show list of styles that can be installed  	*/ -	function export($mode, $style_id) +	protected function show_available()  	{ -		global $db, $template, $user, $phpbb_root_path, $cache, $phpEx, $config; +		// Get list of styles +		$styles = $this->find_available(true); -		$update = (isset($_POST['update'])) ? true : false; - -		$inc_template = request_var('inc_template', 0); -		$inc_theme = request_var('inc_theme', 0); -		$inc_imageset = request_var('inc_imageset', 0); -		$store = request_var('store', 0); -		$format = request_var('format', ''); - -		$error = array(); -		$methods = array('tar'); - -		$available_methods = array('tar.gz' => 'zlib', 'tar.bz2' => 'bz2', 'zip' => 'zlib'); -		foreach ($available_methods as $type => $module) -		{ -			if (!@extension_loaded($module)) -			{ -				continue; -			} - -			$methods[] = $type; -		} - -		if (!in_array($format, $methods)) +		// Show styles +		if (empty($styles))  		{ -			$format = 'tar'; +			trigger_error($this->user->lang['NO_UNINSTALLED_STYLE'] . adm_back_link($this->u_base_action), E_USER_NOTICE);  		} -		switch ($mode) -		{ -			case 'style': -				if ($update && ($inc_template + $inc_theme + $inc_imageset) < 1) -				{ -					$error[] = $user->lang['STYLE_ERR_MORE_ELEMENTS']; -				} - -				$name = 'style_name'; - -				$sql_select = 's.style_id, s.style_name, s.style_copyright'; -				$sql_select .= ($inc_template) ? ', t.*' : ', t.template_name'; -				$sql_select .= ($inc_theme) ? ', c.*' : ', c.theme_name'; -				$sql_select .= ($inc_imageset) ? ', i.*' : ', i.imageset_name'; -				$sql_from = STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . ' i'; -				$sql_where = "s.style_id = $style_id AND t.template_id = s.template_id AND c.theme_id = s.theme_id AND i.imageset_id = s.imageset_id"; - -				$l_prefix = 'STYLE'; -			break; - -			case 'template': -				$name = 'template_name'; - -				$sql_select = '*'; -				$sql_from = STYLES_TEMPLATE_TABLE; -				$sql_where = "template_id = $style_id"; - -				$l_prefix = 'TEMPLATE'; -			break; +		usort($styles, array($this, 'sort_styles')); -			case 'theme': -				$name = 'theme_name'; - -				$sql_select = '*'; -				$sql_from = STYLES_THEME_TABLE; -				$sql_where = "theme_id = $style_id"; - -				$l_prefix = 'THEME'; -			break; - -			case 'imageset': -				$name = 'imageset_name'; - -				$sql_select = '*'; -				$sql_from = STYLES_IMAGESET_TABLE; -				$sql_where = "imageset_id = $style_id"; - -				$l_prefix = 'IMAGESET'; -			break; -		} +		$this->styles_list_cols = 3; +		$this->template->assign_vars(array( +			'STYLES_LIST_COLS'	=> $this->styles_list_cols, +			'STYLES_LIST_HIDE_COUNT'	=> true +			) +		); -		if ($update && !sizeof($error)) +		// Show styles +		foreach ($styles as &$style)  		{ -			$sql = "SELECT $sql_select -				FROM $sql_from -				WHERE $sql_where"; -			$result = $db->sql_query($sql); -			$style_row = $db->sql_fetchrow($result); -			$db->sql_freeresult($result); - -			if (!$style_row) -			{ -				trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); -			} - -			$var_ary = array('style_id', 'style_name', 'style_copyright', 'template_id', 'template_name', 'template_path', 'template_copyright', 'template_storedb', 'template_inherits_id', 'bbcode_bitfield', 'theme_id', 'theme_name', 'theme_path', 'theme_copyright', 'theme_storedb', 'theme_mtime', 'theme_data', 'imageset_id', 'imageset_name', 'imageset_path', 'imageset_copyright'); - -			foreach ($var_ary as $var) -			{ -				if (!isset($style_row[$var])) -				{ -					$style_row[$var] = ''; -				} -			} - -			$files = $data = array(); - -			if ($mode == 'style') -			{ -				$style_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['style_name'], $style_row['style_copyright'], $config['version']), $this->style_cfg); - -				$style_cfg .= (!$inc_template) ? "\nrequired_template = {$style_row['template_name']}" : ''; -				$style_cfg .= (!$inc_theme) ? "\nrequired_theme = {$style_row['theme_name']}" : ''; -				$style_cfg .= (!$inc_imageset) ? "\nrequired_imageset = {$style_row['imageset_name']}" : ''; - -				$data[] = array( -					'src'		=> $style_cfg, -					'prefix'	=> 'style.cfg' -				); - -				unset($style_cfg); -			} - -			// Export template core code -			if ($mode == 'template' || $inc_template) -			{ -				$use_template_name = $style_row['template_name']; - -				// Add the inherit from variable, depending on it's use... -				if ($style_row['template_inherits_id']) -				{ -					// Get the template name -					$sql = 'SELECT template_name -						FROM ' . STYLES_TEMPLATE_TABLE . ' -						WHERE template_id = ' . (int) $style_row['template_inherits_id']; -					$result = $db->sql_query($sql); -					$use_template_name = (string) $db->sql_fetchfield('template_name'); -					$db->sql_freeresult($result); -				} - -				$template_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}', '{INHERIT_FROM}'), array($mode, $style_row['template_name'], $style_row['template_copyright'], $config['version'], $use_template_name), $this->template_cfg); - -				$template_cfg .= "\n\nbbcode_bitfield = {$style_row['bbcode_bitfield']}"; - -				$data[] = array( -					'src'		=> $template_cfg, -					'prefix'	=> 'template/template.cfg' -				); - -				// This is potentially nasty memory-wise ... -				if (!$style_row['template_storedb']) -				{ -					$files[] = array( -						'src'		=> "styles/{$style_row['template_path']}/template/", -						'prefix-'	=> "styles/{$style_row['template_path']}/", -						'prefix+'	=> false, -						'exclude'	=> 'template.cfg' -					); -				} -				else -				{ -					$sql = 'SELECT template_filename, template_data -						FROM ' . STYLES_TEMPLATE_DATA_TABLE . " -						WHERE template_id = {$style_row['template_id']}"; -					$result = $db->sql_query($sql); - -					while ($row = $db->sql_fetchrow($result)) -					{ -						$data[] = array( -							'src' => $row['template_data'], -							'prefix' => 'template/' . $row['template_filename'] -						); -					} -					$db->sql_freeresult($result); -				} -				unset($template_cfg); -			} - -			// Export theme core code -			if ($mode == 'theme' || $inc_theme) -			{ -				$theme_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['theme_name'], $style_row['theme_copyright'], $config['version']), $this->theme_cfg); - -				// Read old cfg file -				$items = $cache->obtain_cfg_items($style_row); -				$items = $items['theme']; - -				if (!isset($items['parse_css_file'])) -				{ -					$items['parse_css_file'] = 'off'; -				} - -				$theme_cfg = str_replace(array('{PARSE_CSS_FILE}'), array($items['parse_css_file']), $theme_cfg); - -				$files[] = array( -					'src'		=> "styles/{$style_row['theme_path']}/theme/", -					'prefix-'	=> "styles/{$style_row['theme_path']}/", -					'prefix+'	=> false, -					'exclude'	=> ($style_row['theme_storedb']) ? 'stylesheet.css,theme.cfg' : 'theme.cfg' -				); - -				$data[] = array( -					'src'		=> $theme_cfg, -					'prefix'	=> 'theme/theme.cfg' -				); - -				if ($style_row['theme_storedb']) -				{ -					$data[] = array( -						'src'		=> $style_row['theme_data'], -						'prefix'	=> 'theme/stylesheet.css' -					); -				} - -				unset($items, $theme_cfg); -			} - -			// Export imageset core code -			if ($mode == 'imageset' || $inc_imageset) +			// Check if style has a parent style in styles list +			$has_parent = false; +			if ($style['_inherit_name'] != '')  			{ -				$imageset_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['imageset_name'], $style_row['imageset_copyright'], $config['version']), $this->imageset_cfg); - -				$imageset_main = array(); - -				$sql = 'SELECT image_filename, image_name, image_height, image_width -					FROM ' . STYLES_IMAGESET_DATA_TABLE . " -					WHERE imageset_id = $style_id -						AND image_lang = ''"; -				$result = $db->sql_query($sql); -				while ($row = $db->sql_fetchrow($result)) -				{ -					$imageset_main[$row['image_name']] = $row['image_filename'] . ($row['image_height'] ? '*' . $row['image_height']: '') . ($row['image_width'] ? '*' . $row['image_width']: ''); -				} -				$db->sql_freeresult($result); - -				foreach ($this->imageset_keys as $topic => $key_array) -				{ -					foreach ($key_array as $key) -					{ -						if (isset($imageset_main[$key])) -						{ -							$imageset_cfg .= "\nimg_" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $imageset_main[$key]); -						} -					} -				} - -				$files[] = array( -					'src'		=> "styles/{$style_row['imageset_path']}/imageset/", -					'prefix-'	=> "styles/{$style_row['imageset_path']}/", -					'prefix+'	=> false, -					'exclude'	=> 'imageset.cfg' -				); - -				$data[] = array( -					'src'		=> trim($imageset_cfg), -					'prefix'	=> 'imageset/imageset.cfg' -				); - -				end($data); - -				$imageset_root = "{$phpbb_root_path}styles/{$style_row['imageset_path']}/imageset/"; - -				if ($dh = @opendir($imageset_root)) +				foreach ($styles as $parent_style)  				{ -					while (($fname = readdir($dh)) !== false) +					if ($parent_style['style_name'] == $style['_inherit_name'] && empty($parent_style['_shown']))  					{ -						if ($fname[0] != '.' && $fname != 'CVS' && is_dir("$imageset_root$fname")) -						{ -							$files[key($files)]['exclude'] .= ',' . $fname . '/imageset.cfg'; -						} -					} -					closedir($dh); -				} - -				$imageset_lang = array(); - -				$sql = 'SELECT image_filename, image_name, image_height, image_width, image_lang -					FROM ' . STYLES_IMAGESET_DATA_TABLE . " -					WHERE imageset_id = $style_id -						AND image_lang <> ''"; -				$result = $db->sql_query($sql); -				while ($row = $db->sql_fetchrow($result)) -				{ -					$imageset_lang[$row['image_lang']][$row['image_name']] = $row['image_filename'] . ($row['image_height'] ? '*' . $row['image_height']: '') . ($row['image_width'] ? '*' . $row['image_width']: ''); -				} -				$db->sql_freeresult($result); - -				foreach ($imageset_lang as $lang => $imageset_localized) -				{ -					$imageset_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['imageset_name'], $style_row['imageset_copyright'], $config['version']), $this->imageset_cfg); - -					foreach ($this->imageset_keys as $topic => $key_array) -					{ -						foreach ($key_array as $key) -						{ -							if (isset($imageset_localized[$key])) -							{ -								$imageset_cfg .= "\nimg_" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $imageset_localized[$key]); -							} -						} +						// Show parent style first +						$has_parent = true;  					} - -					$data[] = array( -						'src'		=> trim($imageset_cfg), -						'prefix'	=> 'imageset/' . $lang . '/imageset.cfg' -					);  				} - -				unset($imageset_cfg);  			} - -			switch ($format) +			if (!$has_parent)  			{ -				case 'tar': -					$ext = '.tar'; -				break; - -				case 'zip': -					$ext = '.zip'; -				break; - -				case 'tar.gz': -					$ext = '.tar.gz'; -				break; - -				case 'tar.bz2': -					$ext = '.tar.bz2'; -				break; - -				default: -					$error[] = $user->lang[$l_prefix . '_ERR_ARCHIVE']; +				$this->list_style($style, 0); +				$this->show_available_child_styles($styles, $style['style_name'], 1);  			} +		} -			if (!sizeof($error)) +		// Show styles that do not have parent style in styles list +		foreach ($styles as $style) +		{ +			if (empty($style['_shown']))  			{ -				include($phpbb_root_path . 'includes/functions_compress.' . $phpEx); - -				if ($mode == 'style') -				{ -					$path = preg_replace('#[^\w-]+#', '_', $style_row['style_name']); -				} -				else -				{ -					$path = $style_row[$mode . '_path']; -				} - -				if ($format == 'zip') -				{ -					$compress = new compress_zip('w', $phpbb_root_path . "store/$path$ext"); -				} -				else -				{ -					$compress = new compress_tar('w', $phpbb_root_path . "store/$path$ext", $ext); -				} - -				if (sizeof($files)) -				{ -					foreach ($files as $file_ary) -					{ -						$compress->add_file($file_ary['src'], $file_ary['prefix-'], $file_ary['prefix+'], $file_ary['exclude']); -					} -				} - -				if (sizeof($data)) -				{ -					foreach ($data as $data_ary) -					{ -						$compress->add_data($data_ary['src'], $data_ary['prefix']); -					} -				} - -				$compress->close(); - -				add_log('admin', 'LOG_' . $l_prefix . '_EXPORT', $style_row[$mode . '_name']); - -				if (!$store) -				{ -					$compress->download($path); -					@unlink("{$phpbb_root_path}store/$path$ext"); -					exit; -				} - -				trigger_error(sprintf($user->lang[$l_prefix . '_EXPORTED'], "store/$path$ext") . adm_back_link($this->u_action)); +				$this->list_style($style, 0);  			}  		} -		$sql = "SELECT {$mode}_id, {$mode}_name -			FROM " . (($mode == 'style') ? STYLES_TABLE : $sql_from) . " -			WHERE {$mode}_id = $style_id"; -		$result = $db->sql_query($sql); -		$style_row = $db->sql_fetchrow($result); -		$db->sql_freeresult($result); - -		if (!$style_row) +		// Add button +		if (isset($this->style_counters) && $this->style_counters['caninstall'] > 0)  		{ -			trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); -		} - -		$this->page_title = $l_prefix . '_EXPORT'; - -		$format_buttons = ''; -		foreach ($methods as $method) -		{ -			$format_buttons .= '<label><input type="radio"' . ((!$format_buttons) ? ' id="format"' : '') . ' class="radio" value="' . $method . '" name="format"' . (($method == $format) ? ' checked="checked"' : '') . ' /> ' . $method . '</label>'; +			$this->template->assign_block_vars('extra_actions', array( +					'ACTION_NAME'	=> 'install', +					'L_ACTION'		=> $this->user->lang['INSTALL_STYLES'], +				) +			);  		} - -		$template->assign_vars(array( -			'S_EXPORT'		=> true, -			'S_ERROR_MSG'	=> (sizeof($error)) ? true : false, -			'S_STYLE'		=> ($mode == 'style') ? true : false, - -			'L_TITLE'		=> $user->lang[$this->page_title], -			'L_EXPLAIN'		=> $user->lang[$this->page_title . '_EXPLAIN'], -			'L_NAME'		=> $user->lang[$l_prefix . '_NAME'], - -			'U_ACTION'		=> $this->u_action . '&action=export&id=' . $style_id, -			'U_BACK'		=> $this->u_action, - -			'ERROR_MSG'			=> (sizeof($error)) ? implode('<br />', $error) : '', -			'NAME'				=> $style_row[$mode . '_name'], -			'FORMAT_BUTTONS'	=> $format_buttons) -		);  	}  	/** -	* Display details +	* Find styles available for installation +	* +	* @param bool $all if true, function will return all installable styles. if false, function will return only styles that can be installed +	* @return array List of styles  	*/ -	function details($mode, $style_id) +	protected function find_available($all)  	{ -		global $template, $db, $config, $user, $safe_mode, $cache, $phpbb_root_path; - -		$update = (isset($_POST['update'])) ? true : false; -		$l_type = strtoupper($mode); - -		$error = array(); -		$element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE); - -		switch ($mode) -		{ -			case 'style': -				$sql_from = STYLES_TABLE; -			break; - -			case 'template': -				$sql_from = STYLES_TEMPLATE_TABLE; -			break; - -			case 'theme': -				$sql_from = STYLES_THEME_TABLE; -			break; - -			case 'imageset': -				$sql_from = STYLES_IMAGESET_TABLE; -			break; -		} - -		$sql = "SELECT * -			FROM $sql_from -			WHERE {$mode}_id = $style_id"; -		$result = $db->sql_query($sql); -		$style_row = $db->sql_fetchrow($result); -		$db->sql_freeresult($result); - -		if (!$style_row) -		{ -			trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING); +		// Get list of installed styles +		$installed = $this->get_styles(); + +		$installed_dirs = array(); +		$installed_names = array(); +		foreach ($installed as $style) +		{ +			$installed_dirs[] = $style['style_path']; +			$installed_names[$style['style_name']] = array( +				'path'		=> $style['style_path'], +				'id'		=> $style['style_id'], +				'parent'	=> $style['style_parent_id'], +				'tree'		=> (strlen($style['style_parent_tree']) ? $style['style_parent_tree'] . '/' : '') . $style['style_path'], +			);  		} -		$style_row['style_default'] = ($mode == 'style' && $config['default_style'] == $style_id) ? 1 : 0; +		// Get list of directories +		$dirs = $this->find_style_dirs(); -		if ($update) +		// Find styles that can be installed +		$styles = array(); +		foreach ($dirs as $dir)  		{ -			$name = utf8_normalize_nfc(request_var('name', '', true)); -			$copyright = utf8_normalize_nfc(request_var('copyright', '', true)); - -			$template_id = request_var('template_id', 0); -			$theme_id = request_var('theme_id', 0); -			$imageset_id = request_var('imageset_id', 0); - -			$style_active = request_var('style_active', 0); -			$style_default = request_var('style_default', 0); -			$store_db = request_var('store_db', 0); - -			// If the admin selected the style to be the default style, but forgot to activate it... we will do it for him -			if ($style_default) -			{ -				$style_active = 1; -			} - -			$sql = "SELECT {$mode}_id, {$mode}_name -				FROM $sql_from -				WHERE {$mode}_id <> $style_id -				AND LOWER({$mode}_name) = '" . $db->sql_escape(strtolower($name)) . "'"; -			$result = $db->sql_query($sql); -			$conflict = $db->sql_fetchrow($result); -			$db->sql_freeresult($result); - -			if ($mode == 'style' && (!$template_id || !$theme_id || !$imageset_id)) -			{ -				$error[] = $user->lang['STYLE_ERR_NO_IDS']; -			} - -			if ($mode == 'style' && $style_row['style_active'] && !$style_active && $config['default_style'] == $style_id) -			{ -				$error[] = $user->lang['DEACTIVATE_DEFAULT']; -			} - -			if (!$name || $conflict) -			{ -				$error[] = $user->lang[$l_type . '_ERR_STYLE_NAME']; -			} - -			if ($mode === 'theme' || $mode === 'template') +			if (in_array($dir, $installed_dirs))  			{ -				// a rather elaborate check we have to do here once to avoid trouble later -				$check = "{$phpbb_root_path}styles/" . $style_row["{$mode}_path"] . (($mode === 'theme') ? '/theme/stylesheet.css' : '/template'); -				if (($style_row["{$mode}_storedb"] != $store_db) && !$store_db && ($safe_mode || !phpbb_is_writable($check))) -				{ -					$error[] = $user->lang['EDIT_' . strtoupper($mode) . '_STORED_DB']; -					$store_db = 1; -				} - -				// themes which have to be parsed have to go into db -				if ($mode == 'theme') -				{ -					$cfg = parse_cfg_file("{$phpbb_root_path}styles/" . $style_row["{$mode}_path"] . "/theme/theme.cfg"); - -					if (isset($cfg['parse_css_file']) && $cfg['parse_css_file'] && !$store_db) -					{ -						$error[] = $user->lang['EDIT_THEME_STORE_PARSED']; -						$store_db = 1; -					} -				} +				// Style is already installed +				continue;  			} - -			if (!sizeof($error)) +			$cfg = $this->read_style_cfg($dir); +			if ($cfg === false)  			{ -				// Check length settings -				if (utf8_strlen($name) > 30) -				{ -					$error[] = $user->lang[$l_type . '_ERR_NAME_LONG']; -				} - -				if (utf8_strlen($copyright) > 60) -				{ -					$error[] = $user->lang[$l_type . '_ERR_COPY_LONG']; -				} +				// Invalid style.cfg +				continue;  			} -		} -		if ($update && sizeof($error)) -		{ -			$style_row = array_merge($style_row, array( -				'template_id'			=> $template_id, -				'theme_id'				=> $theme_id, -				'imageset_id'			=> $imageset_id, -				'style_active'			=> $style_active, -				$mode . '_storedb'		=> $store_db, -				$mode . '_name'			=> $name, -				$mode . '_copyright'	=> $copyright) +			// Style should be available for installation +			$parent = $cfg['parent']; +			$style = array( +				'style_id'			=> 0, +				'style_name'		=> $cfg['name'], +				'style_copyright'	=> $cfg['copyright'], +				'style_active'		=> 0, +				'style_path'		=> $dir, +				'bbcode_bitfield'	=> $cfg['template_bitfield'], +				'style_parent_id'	=> 0, +				'style_parent_tree'	=> '', +				// Extra values for styles list +				// All extra variable start with _ so they won't be confused with data that can be added to styles table +				'_inherit_name'			=> $parent, +				'_available'			=> true, +				'_note'					=> '',  			); -		} - -		// User has submitted form and no errors have occurred -		if ($update && !sizeof($error)) -		{ -			$sql_ary = array( -				$mode . '_name'			=> $name, -				$mode . '_copyright'	=> $copyright -			); - -			switch ($mode) -			{ -				case 'style': - -					$sql_ary += array( -						'template_id'		=> (int) $template_id, -						'theme_id'			=> (int) $theme_id, -						'imageset_id'		=> (int) $imageset_id, -						'style_active'		=> (int) $style_active, -					); -				break; - -				case 'imageset': -				break; - -				case 'theme': - -					if ($style_row['theme_storedb'] != $store_db) -					{ -						$theme_data = ''; - -						if (!$style_row['theme_storedb']) -						{ -							$theme_data = $this->db_theme_data($style_row); -						} -						else if (!$store_db && !$safe_mode && phpbb_is_writable("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css")) -						{ -							$store_db = 1; -							$theme_data = $style_row['theme_data']; - -							if ($fp = @fopen("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css", 'wb')) -							{ -								$store_db = (@fwrite($fp, str_replace("styles/{$style_row['theme_path']}/theme/", './', $theme_data))) ? 0 : 1; -							} -							fclose($fp); -						} - -						$sql_ary += array( -							'theme_mtime'	=> ($store_db) ? filemtime("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css") : 0, -							'theme_storedb'	=> $store_db, -							'theme_data'	=> ($store_db) ? $theme_data : '', -						); -					} -				break; - -				case 'template': -					if ($style_row['template_storedb'] != $store_db) -					{ -						if ($super = $this->get_super($mode, $style_row['template_id'])) -						{ -							$error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name'])); -							$sql_ary = array(); -						} -						else -						{ -							if (!$store_db && !$safe_mode && phpbb_is_writable("{$phpbb_root_path}styles/{$style_row['template_path']}/template")) -							{ -								$err = $this->store_in_fs('template', $style_row['template_id']); -								if ($err) -								{ -									$error += $err; -								} -							} -							else if ($store_db) -							{ -								$this->store_in_db('template', $style_row['template_id']); -							} -							else -							{ -								// We no longer store within the db, but are also not able to update the file structure -								// Since the admin want to switch this, we adhere to his decision. But we also need to remove the cache -								$sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . " -									WHERE template_id = $style_id"; -								$db->sql_query($sql); -							} - -							$sql_ary += array( -								'template_storedb'	=> $store_db, -							); -						} -					} -				break; -			} - -			if (sizeof($sql_ary)) +			// Check style inheritance +			if ($parent != '')  			{ -				$sql = "UPDATE $sql_from -					SET " . $db->sql_build_array('UPDATE', $sql_ary) . " -					WHERE {$mode}_id = $style_id"; -				$db->sql_query($sql); - -				// Making this the default style? -				if ($mode == 'style' && $style_default) +				if (isset($installed_names[$parent]))  				{ -					set_config('default_style', $style_id); +					// Parent style is installed +					$row = $installed_names[$parent]; +					$style['style_parent_id'] = $row['id']; +					$style['style_parent_tree'] = $row['tree'];  				} -			} - -			$cache->destroy('sql', STYLES_TABLE); - -			add_log('admin', 'LOG_' . $l_type . '_EDIT_DETAILS', $name); -			if (sizeof($error)) -			{ -				trigger_error(implode('<br />', $error) . adm_back_link($this->u_action), E_USER_WARNING); -			} -			else -			{ -				trigger_error($user->lang[$l_type . '_DETAILS_UPDATED'] . adm_back_link($this->u_action)); -			} -		} - -		if ($mode == 'style') -		{ -			foreach ($element_ary as $element => $table) -			{ -				$sql = "SELECT {$element}_id, {$element}_name -					FROM $table -					ORDER BY {$element}_id ASC"; -				$result = $db->sql_query($sql); - -				${$element . '_options'} = ''; -				while ($row = $db->sql_fetchrow($result)) +				else  				{ -					$selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : ''; -					${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>'; +					// Parent style is not installed yet +					$style['_available'] = false; +					$style['_note'] = sprintf($this->user->lang['REQUIRES_STYLE'], htmlspecialchars($parent));  				} -				$db->sql_freeresult($result);  			} -		} -		if ($mode == 'template') -		{ -			$super = array(); -			if (isset($style_row[$mode . '_inherits_id']) && $style_row['template_inherits_id']) +			if ($all || $style['_available'])  			{ -				$super = $this->get_super($mode, $style_row['template_id']); +				$styles[] = $style;  			}  		} -		$this->page_title = 'EDIT_DETAILS_' . $l_type; - -		$template->assign_vars(array( -			'S_DETAILS'				=> true, -			'S_ERROR_MSG'			=> (sizeof($error)) ? true : false, -			'S_STYLE'				=> ($mode == 'style') ? true : false, -			'S_TEMPLATE'			=> ($mode == 'template') ? true : false, -			'S_THEME'				=> ($mode == 'theme') ? true : false, -			'S_IMAGESET'			=> ($mode == 'imageset') ? true : false, -			'S_STORE_DB'			=> (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0, -			'S_STORE_DB_DISABLED'	=> (isset($style_row[$mode . '_inherits_id'])) ? $style_row[$mode . '_inherits_id'] : 0, -			'S_STYLE_ACTIVE'		=> (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, -			'S_STYLE_DEFAULT'		=> (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, -			'S_SUPERTEMPLATE'		=> (isset($style_row[$mode . '_inherits_id']) && $style_row[$mode . '_inherits_id']) ? $super['template_name'] : 0, - -			'S_TEMPLATE_OPTIONS'	=> ($mode == 'style') ? $template_options : '', -			'S_THEME_OPTIONS'		=> ($mode == 'style') ? $theme_options : '', -			'S_IMAGESET_OPTIONS'	=> ($mode == 'style') ? $imageset_options : '', - -			'U_ACTION'		=> $this->u_action . '&action=details&id=' . $style_id, -			'U_BACK'		=> $this->u_action, - -			'L_TITLE'				=> $user->lang[$this->page_title], -			'L_EXPLAIN'				=> $user->lang[$this->page_title . '_EXPLAIN'], -			'L_NAME'				=> $user->lang[$l_type . '_NAME'], -			'L_LOCATION'			=> ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '', -			'L_LOCATION_EXPLAIN'	=> ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '', - -			'ERROR_MSG'		=> (sizeof($error)) ? implode('<br />', $error) : '', -			'NAME'			=> $style_row[$mode . '_name'], -			'COPYRIGHT'		=> $style_row[$mode . '_copyright'], -			) -		); +		return $styles;  	}  	/** -	* Load css file contents +	* Show styles list +	* +	* @param array $styles styles list +	* @param int $parent parent style id +	* @param int $level style inheritance level  	*/ -	function load_css_file($path, $filename) +	protected function show_styles_list(&$styles, $parent, $level)  	{ -		global $phpbb_root_path; - -		$file = "{$phpbb_root_path}styles/$path/theme/$filename"; - -		if (file_exists($file) && ($content = file_get_contents($file))) -		{ -			$content = trim($content); -		} -		else -		{ -			$content = ''; -		} -		if (defined('DEBUG')) +		foreach ($styles as &$style)  		{ -			$content = "/* BEGIN @include $filename */ \n $content \n /* END @include $filename */ \n"; +			if (empty($style['_shown']) && $style['style_parent_id'] == $parent) +			{ +				$this->list_style($style, $level); +				$this->show_styles_list($styles, $style['style_id'], $level + 1); +			}  		} - -		return $content;  	}  	/** -	* Returns a string containing the value that should be used for the theme_data column in the theme database table. -	* Includes contents of files loaded via @import -	* -	* @param array $theme_row is an associative array containing the theme's current database entry -	* @param mixed $stylesheet can either be the new content for the stylesheet or false to load from the standard file -	* @param string $root_path should only be used in case you want to use a different root path than "{$phpbb_root_path}styles/{$theme_row['theme_path']}" +	* Show available styles tree  	* -	* @return string Stylesheet data for theme_data column in the theme table +	* @param array $styles Styles list, passed as reference +	* @param string $name Name of parent style +	* @param int $level Styles tree level  	*/ -	function db_theme_data($theme_row, $stylesheet = false, $root_path = '') +	protected function show_available_child_styles(&$styles, $name, $level)  	{ -		global $phpbb_root_path; - -		if (!$root_path) -		{ -			$root_path = $phpbb_root_path . 'styles/' . $theme_row['theme_path']; -		} - -		if (!$stylesheet) -		{ -			$stylesheet = ''; -			if (file_exists($root_path . '/theme/stylesheet.css')) -			{ -				$stylesheet = file_get_contents($root_path . '/theme/stylesheet.css'); -			} -		} - -		// Match CSS imports -		$matches = array(); -		preg_match_all('/@import url\((["\'])(.*)\1\);/i', $stylesheet, $matches); - -		// remove commented stylesheets (very simple parser, allows only whitespace -		// around an @import statement) -		preg_match_all('#/\*\s*@import url\((["\'])(.*)\1\);\s\*/#i', $stylesheet, $commented); -		$matches[2] = array_diff($matches[2], $commented[2]); - -		if (sizeof($matches)) +		foreach ($styles as &$style)  		{ -			foreach ($matches[0] as $idx => $match) +			if (empty($style['_shown']) && $style['_inherit_name'] == $name)  			{ -				if (isset($matches[2][$idx])) -				{ -					$stylesheet = str_replace($match, acp_styles::load_css_file($theme_row['theme_path'], $matches[2][$idx]), $stylesheet); -				} +				$this->list_style($style, $level); +				$this->show_available_child_styles($styles, $style['style_name'], $level + 1);  			}  		} - -		// adjust paths -		return str_replace('./', 'styles/' . $theme_row['theme_path'] . '/theme/', $stylesheet);  	}  	/** -	* Store template files into db +	* Update styles tree +	* +	* @param array $styles Styles list, passed as reference +	* @param array|false $style Current style, false if root +	* @return bool True if something was updated, false if not  	*/ -	function store_templates($mode, $style_id, $template_path, $filelist) +	protected function update_styles_tree(&$styles, $style = false)  	{ -		global $phpbb_root_path, $phpEx, $db; - -		$template_path = $template_path . '/template/'; -		$includes = array(); -		foreach ($filelist as $pathfile => $file_ary) +		$parent_id = ($style === false) ? 0 : $style['style_id']; +		$parent_tree = ($style === false) ? '' : ($style['style_parent_tree'] == '' ? '' : $style['style_parent_tree']) . $style['style_path']; +		$update = false; +		$updated = false; +		foreach ($styles as &$row)  		{ -			foreach ($file_ary as $file) +			if ($row['style_parent_id'] == $parent_id)  			{ -				if (!($fp = @fopen("{$phpbb_root_path}styles/$template_path$pathfile$file", 'r'))) -				{ -					trigger_error("Could not open {$phpbb_root_path}styles/$template_path$pathfile$file", E_USER_ERROR); -				} - -				$filesize = filesize("{$phpbb_root_path}styles/$template_path$pathfile$file"); - -				if ($filesize) +				if ($row['style_parent_tree'] != $parent_tree)  				{ -					$template_data = fread($fp, $filesize); -				} - -				fclose($fp); - -				if (!$filesize) -				{ -					// File is empty -					continue; -				} - -				if (preg_match_all('#<!-- INCLUDE (.*?\.html) -->#is', $template_data, $matches)) -				{ -					foreach ($matches[1] as $match) -					{ -						$includes[trim($match)][] = $file; -					} +					$row['style_parent_tree'] = $parent_tree; +					$update = true;  				} +				$updated |= $this->update_styles_tree($styles, $row);  			}  		} - -		foreach ($filelist as $pathfile => $file_ary) +		if ($update)  		{ -			foreach ($file_ary as $file) -			{ -				// Skip index. -				if (strpos($file, 'index.') === 0) -				{ -					continue; -				} - -				// We could do this using extended inserts ... but that could be one -				// heck of a lot of data ... -				$sql_ary = array( -					'template_id'			=> (int) $style_id, -					'template_filename'		=> "$pathfile$file", -					'template_included'		=> (isset($includes[$file])) ? implode(':', $includes[$file]) . ':' : '', -					'template_mtime'		=> (int) filemtime("{$phpbb_root_path}styles/$template_path$pathfile$file"), -					'template_data'			=> (string) file_get_contents("{$phpbb_root_path}styles/$template_path$pathfile$file"), -				); - -				if ($mode == 'insert') -				{ -					$sql = 'INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); -				} -				else -				{ -					$sql = 'UPDATE ' . STYLES_TEMPLATE_DATA_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " -						WHERE template_id = $style_id -							AND template_filename = '" . $db->sql_escape("$pathfile$file") . "'"; -				} -				$db->sql_query($sql); -			} +			$sql = 'UPDATE ' . STYLES_TABLE . " +				SET style_parent_tree = '" . $this->db->sql_escape($parent_tree) . "' +				WHERE style_parent_id = {$parent_id}"; +			$this->db->sql_query($sql); +			$updated = true;  		} +		return $updated;  	}  	/** -	* Returns an array containing all template filenames for one template that are currently cached. -	* -	* @param string $template_path contains the name of the template's folder in /styles/ +	* Find all possible parent styles for style  	* -	* @return array of filenames that exist in /styles/$template_path/template/ (without extension!) +	* @param array $styles list of styles +	* @param int $id id of style +	* @param int $parent current parent style id +	* @param int $level current tree level +	* @return array Style ids, names and levels  	*/ -	function template_cache_filelist($template_path) +	protected function find_possible_parents($styles, $id = -1, $parent = 0, $level = 0)  	{ -		global $phpbb_root_path, $phpEx, $user; - -		$cache_prefix = 'tpl_' . str_replace('_', '-', $template_path); - -		if (!($dp = @opendir("{$phpbb_root_path}cache"))) -		{ -			trigger_error($user->lang['TEMPLATE_ERR_CACHE_READ'] . adm_back_link($this->u_action), E_USER_WARNING); -		} - -		$file_ary = array(); -		while ($file = readdir($dp)) -		{ -			if ($file[0] == '.') -			{ -				continue; -			} - -			if (is_file($phpbb_root_path . 'cache/' . $file) && (strpos($file, $cache_prefix) === 0)) -			{ -				$file_ary[] = str_replace('.', '/', preg_replace('#^' . preg_quote($cache_prefix, '#') . '_(.*?)\.html\.' . $phpEx . '$#i', '\1', $file)); +		$results = array(); +		foreach ($styles as $style) +		{ +			if ($style['style_id'] != $id && $style['style_parent_id'] == $parent) +			{ +				$results[] = array( +					'style_id'		=> $style['style_id'], +					'style_name'	=> $style['style_name'], +					'style_path'	=> $style['style_path'], +					'style_parent_id'	=> $style['style_parent_id'], +					'style_parent_tree'	=> $style['style_parent_tree'], +					'level'			=> $level +				); +				$results = array_merge($results, $this->find_possible_parents($styles, $id, $style['style_id'], $level + 1));  			}  		} -		closedir($dp); - -		return $file_ary; +		return $results;  	}  	/** -	* Destroys cached versions of template files +	* Show item in styles list  	* -	* @param array $template_row contains the template's row in the STYLES_TEMPLATE_TABLE database table -	* @param mixed $file_ary is optional and may contain an array of template file names which should be refreshed in the cache. -	*	The file names should be the original template file names and not the cache file names. +	* @param array $style style row +	* @param int $level style inheritance level  	*/ -	function clear_template_cache($template_row, $file_ary = false) +	protected function list_style(&$style, $level)  	{ -		global $phpbb_root_path, $phpEx, $user; - -		$cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']); - -		if (!$file_ary || !is_array($file_ary)) -		{ -			$file_ary = $this->template_cache_filelist($template_row['template_path']); -			$log_file_list = $user->lang['ALL_FILES']; -		} -		else +		// Mark row as shown +		if (!empty($style['_shown']))  		{ -			$log_file_list = implode(', ', $file_ary); -		} - -		foreach ($file_ary as $file) -		{ -			$file = str_replace('/', '.', $file); - -			$file = "{$phpbb_root_path}cache/{$cache_prefix}_$file.html.$phpEx"; -			if (file_exists($file) && is_file($file)) -			{ -				@unlink($file); -			} +			return;  		} -		unset($file_ary); - -		add_log('admin', 'LOG_TEMPLATE_CACHE_CLEARED', $template_row['template_name'], $log_file_list); -	} - -	/** -	* Install Style/Template/Theme/Imageset -	*/ -	function install($mode) -	{ -		global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template; - -		$l_type = strtoupper($mode); -		$error = $installcfg = $style_row = array(); -		$root_path = $cfg_file = ''; -		$element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE); - -		$install_path = request_var('path', ''); -		$update = (isset($_POST['update'])) ? true : false; +		$style['_shown'] = true; + +		// Generate template variables +		$actions = array(); +		$row = array( +			// Style data +			'STYLE_ID'		=> $style['style_id'], +			'STYLE_NAME'	=> htmlspecialchars($style['style_name']), +			'STYLE_PATH'	=> htmlspecialchars($style['style_path']), +			'STYLE_COPYRIGHT'	=> strip_tags($style['style_copyright']), +			'STYLE_ACTIVE'	=> $style['style_active'], + +			// Additional data +			'DEFAULT'		=> ($style['style_id'] && $style['style_id'] == $this->default_style), +			'USERS'			=> (isset($style['_users'])) ? $style['_users'] : '', +			'LEVEL'			=> $level, +			'PADDING'		=> (4 + 16 * $level), +			'SHOW_COPYRIGHT'	=> ($style['style_id']) ? false : true, +			'STYLE_PATH_FULL'	=> htmlspecialchars($this->styles_path_absolute . '/' . $style['style_path']) . '/', + +			// Comment to show below style +			'COMMENT'		=> (isset($style['_note'])) ? $style['_note'] : '', + +			// The following variables should be used by hooks to add custom HTML code +			'EXTRA'			=> '', +			'EXTRA_OPTIONS'	=> '' +		); -		// Installing, obtain cfg file contents -		if ($install_path) +		// Status specific data +		if ($style['style_id'])  		{ -			$root_path = $phpbb_root_path . 'styles/' . $install_path . '/'; -			$cfg_file = ($mode == 'style') ? "$root_path$mode.cfg" : "$root_path$mode/$mode.cfg"; - -			if (!file_exists($cfg_file)) -			{ -				$error[] = $user->lang[$l_type . '_ERR_NOT_' . $l_type]; -			} -			else -			{ -				$installcfg = parse_cfg_file($cfg_file); -			} -		} +			// Style is installed -		// Installing -		if (sizeof($installcfg)) -		{ -			$name		= $installcfg['name']; -			$copyright	= $installcfg['copyright']; -			$version	= $installcfg['version']; - -			$style_row = array( -				$mode . '_id'			=> 0, -				$mode . '_name'			=> '', -				$mode . '_copyright'	=> '' +			// Details +			$actions[] = array( +				'U_ACTION'	=> $this->u_action . '&action=details&id=' . $style['style_id'], +				'L_ACTION'	=> $this->user->lang['DETAILS']  			); -			switch ($mode) -			{ -				case 'style': - -					$style_row = array( -						'style_id'			=> 0, -						'style_name'		=> $installcfg['name'], -						'style_copyright'	=> $installcfg['copyright'] -					); - -					$reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false; -					$reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false; -					$reqd_imageset = (isset($installcfg['required_imageset'])) ? $installcfg['required_imageset'] : false; - -					// Check to see if each element is already installed, if it is grab the id -					foreach ($element_ary as $element => $table) -					{ -						$style_row = array_merge($style_row, array( -							$element . '_id'			=> 0, -							$element . '_name'			=> '', -							$element . '_copyright'		=> '') -						); - -			 			$this->test_installed($element, $error, (${'reqd_' . $element}) ? $phpbb_root_path . 'styles/' . $reqd_template . '/' : $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']); - -						if (!$style_row[$element . '_name']) -						{ -							$style_row[$element . '_name'] = $reqd_template; -						} - -						// Merge other information to installcfg... if present -						$cfg_file = $phpbb_root_path . 'styles/' . $install_path . '/' . $element . '/' . $element . '.cfg'; +			// Activate/Deactive +			$action_name = ($style['style_active'] ? 'de' : '') . 'activate'; -						if (file_exists($cfg_file)) -						{ -							$cfg_contents = parse_cfg_file($cfg_file); - -							// Merge only specific things. We may need them later. -							foreach (array('inherit_from', 'parse_css_file') as $key) -							{ -								if (!empty($cfg_contents[$key]) && !isset($installcfg[$key])) -								{ -									$installcfg[$key] = $cfg_contents[$key]; -								} -							} -						} -					} - -				break; +			$actions[] = array( +				'U_ACTION'	=> $this->u_action . '&action=' . $action_name . '&hash=' . generate_link_hash($action_name) . '&id=' . $style['style_id'], +				'L_ACTION'	=> $this->user->lang['STYLE_' . ($style['style_active'] ? 'DE' : '') . 'ACTIVATE'] +			); -				case 'template': -					$this->test_installed('template', $error, $root_path, false, $style_row['template_id'], $style_row['template_name'], $style_row['template_copyright']); -				break; +/*			// Export +			$actions[] = array( +				'U_ACTION'	=> $this->u_action . '&action=export&hash=' . generate_link_hash('export') . '&id=' . $style['style_id'], +				'L_ACTION'	=> $this->user->lang['EXPORT'] +			); */ -				case 'theme': -					$this->test_installed('theme', $error, $root_path, false, $style_row['theme_id'], $style_row['theme_name'], $style_row['theme_copyright']); -				break; +			// Uninstall +			$actions[] = array( +				'U_ACTION'	=> $this->u_action . '&action=uninstall&hash=' . generate_link_hash('uninstall') . '&id=' . $style['style_id'], +				'L_ACTION'	=> $this->user->lang['STYLE_UNINSTALL'] +			); -				case 'imageset': -					$this->test_installed('imageset', $error, $root_path, false, $style_row['imageset_id'], $style_row['imageset_name'], $style_row['imageset_copyright']); -				break; -			} +			// Preview +			$actions[] = array( +				'U_ACTION'	=> append_sid($this->phpbb_root_path . 'index.' . $this->php_ext, 'style=' . $style['style_id']), +				'L_ACTION'	=> $this->user->lang['PREVIEW'] +			);  		}  		else  		{ -			trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING); -		} - -		$style_row['store_db'] = request_var('store_db', 0); -		$style_row['style_active'] = request_var('style_active', 1); -		$style_row['style_default'] = request_var('style_default', 0); - -		// User has submitted form and no errors have occurred -		if ($update && !sizeof($error)) -		{ -			if ($mode == 'style') +			// Style is not installed +			if (empty($style['_available']))  			{ -				foreach ($element_ary as $element => $table) -				{ -					${$element . '_root_path'} = (${'reqd_' . $element}) ? $phpbb_root_path . 'styles/' . ${'reqd_' . $element} . '/' : false; -					${$element . '_path'} = (${'reqd_' . $element}) ? ${'reqd_' . $element} : false; -				} -				$this->install_style($error, 'install', $root_path, $style_row['style_id'], $style_row['style_name'], $install_path, $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row, $template_root_path, $template_path, $theme_root_path, $theme_path, $imageset_root_path, $imageset_path); +				$actions[] = array( +					'HTML'		=> $this->user->lang['CANNOT_BE_INSTALLED'] +				);  			}  			else  			{ -				$style_row['store_db'] = $this->install_element($mode, $error, 'install', $root_path, $style_row[$mode . '_id'], $style_row[$mode . '_name'], $install_path, $style_row[$mode . '_copyright'], $style_row['store_db']); +				$actions[] = array( +					'U_ACTION'	=> $this->u_action . '&action=install&hash=' . generate_link_hash('install') . '&dir=' . urlencode($style['style_path']), +					'L_ACTION'	=> $this->user->lang['INSTALL_STYLE'] +				);  			} +		} -			if (!sizeof($error)) -			{ -				$cache->destroy('sql', STYLES_TABLE); +		// todo: add hook -				$message = ($style_row['store_db']) ? '_ADDED_DB' : '_ADDED'; -				trigger_error($user->lang[$l_type . $message] . adm_back_link($this->u_action)); -			} +		// Assign template variables +		$this->template->assign_block_vars('styles_list', $row); +		foreach($actions as $action) +		{ +			$this->template->assign_block_vars('styles_list.actions', $action);  		} -		$this->page_title = 'INSTALL_' . $l_type; - -		$template->assign_vars(array( -			'S_DETAILS'			=> true, -			'S_INSTALL'			=> true, -			'S_ERROR_MSG'		=> (sizeof($error)) ? true : false, -			'S_LOCATION'		=> (isset($installcfg['inherit_from']) && $installcfg['inherit_from']) ? false : true, -			'S_STYLE'			=> ($mode == 'style') ? true : false, -			'S_TEMPLATE'		=> ($mode == 'template') ? true : false, -			'S_SUPERTEMPLATE'	=> (isset($installcfg['inherit_from'])) ? $installcfg['inherit_from'] : '', -			'S_THEME'			=> ($mode == 'theme') ? true : false, - -			'S_STORE_DB'			=> (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0, -			'S_STYLE_ACTIVE'		=> (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, -			'S_STYLE_DEFAULT'		=> (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, - -			'U_ACTION'			=> $this->u_action . "&action=install&path=" . urlencode($install_path), -			'U_BACK'			=> $this->u_action, - -			'L_TITLE'				=> $user->lang[$this->page_title], -			'L_EXPLAIN'				=> $user->lang[$this->page_title . '_EXPLAIN'], -			'L_NAME'				=> $user->lang[$l_type . '_NAME'], -			'L_LOCATION'			=> ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '', -			'L_LOCATION_EXPLAIN'	=> ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '', - -			'ERROR_MSG'			=> (sizeof($error)) ? implode('<br />', $error) : '', -			'NAME'				=> $style_row[$mode . '_name'], -			'COPYRIGHT'			=> $style_row[$mode . '_copyright'], -			'TEMPLATE_NAME'		=> ($mode == 'style') ? $style_row['template_name'] : '', -			'THEME_NAME'		=> ($mode == 'style') ? $style_row['theme_name'] : '', -			'IMAGESET_NAME'		=> ($mode == 'style') ? $style_row['imageset_name'] : '') -		); +		// Increase counters +		$counter = ($style['style_id']) ? ($style['style_active'] ? 'active' : 'inactive') : (empty($style['_available']) ? 'cannotinstall' : 'caninstall'); +		if (!isset($this->style_counters)) +		{ +			$this->style_counters = array( +				'total'		=> 0, +				'active'	=> 0, +				'inactive'	=> 0, +				'caninstall'	=> 0, +				'cannotinstall'	=> 0 +				); +		} +		$this->style_counters[$counter]++; +		$this->style_counters['total']++;  	}  	/** -	* Add new style +	* Show welcome message +	* +	* @param string $title main title +	* @param string $description page description  	*/ -	function add($mode) +	protected function welcome_message($title, $description)  	{ -		global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template; - -		$l_type = strtoupper($mode); -		$element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE); -		$error = array(); - -		$style_row = array( -			$mode . '_name'			=> utf8_normalize_nfc(request_var('name', '', true)), -			$mode . '_copyright'	=> utf8_normalize_nfc(request_var('copyright', '', true)), -			'template_id'			=> 0, -			'theme_id'				=> 0, -			'imageset_id'			=> 0, -			'store_db'				=> request_var('store_db', 0), -			'style_active'			=> request_var('style_active', 1), -			'style_default'			=> request_var('style_default', 0), +		$this->template->assign_vars(array( +			'L_TITLE'	=> $this->user->lang[$title], +			'L_EXPLAIN'	=> (isset($this->user->lang[$description])) ? $this->user->lang[$description] : '' +			)  		); +	} -		$basis = request_var('basis', 0); -		$update = (isset($_POST['update'])) ? true : false; - -		if ($basis) -		{ -			switch ($mode) -			{ -				case 'style': -					$sql_select = 'template_id, theme_id, imageset_id'; -					$sql_from = STYLES_TABLE; -				break; - -				case 'template': -					$sql_select = 'template_id'; -					$sql_from = STYLES_TEMPLATE_TABLE; -				break; - -				case 'theme': -					$sql_select = 'theme_id'; -					$sql_from = STYLES_THEME_TABLE; -				break; - -				case 'imageset': -					$sql_select = 'imageset_id'; -					$sql_from = STYLES_IMAGESET_TABLE; -				break; -			} - -			$sql = "SELECT $sql_select -				FROM $sql_from -				WHERE {$mode}_id = $basis"; -			$result = $db->sql_query($sql); -			$row = $db->sql_fetchrow($result); -			$db->sql_freeresult($result); - -			if (!$row) -			{ -				$error[] = $user->lang['NO_' . $l_type]; -			} - -			if (!sizeof($error)) -			{ -				$style_row['template_id']	= (isset($row['template_id'])) ? $row['template_id'] : $style_row['template_id']; -				$style_row['theme_id']		= (isset($row['theme_id'])) ? $row['theme_id'] : $style_row['theme_id']; -				$style_row['imageset_id']	= (isset($row['imageset_id'])) ? $row['imageset_id'] : $style_row['imageset_id']; -			} -		} - -		if ($update) -		{ -			$style_row['template_id'] = request_var('template_id', $style_row['template_id']); -			$style_row['theme_id'] = request_var('theme_id', $style_row['theme_id']); -			$style_row['imageset_id'] = request_var('imageset_id', $style_row['imageset_id']); - -			if ($mode == 'style' && (!$style_row['template_id'] || !$style_row['theme_id'] || !$style_row['imageset_id'])) -			{ -				$error[] = $user->lang['STYLE_ERR_NO_IDS']; -			} -		} - -		// User has submitted form and no errors have occurred -		if ($update && !sizeof($error)) -		{ -			if ($mode == 'style') -			{ -				$style_row['style_id'] = 0; - -				$this->install_style($error, 'add', '', $style_row['style_id'], $style_row['style_name'], '', $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row); -			} - -			if (!sizeof($error)) -			{ -				$cache->destroy('sql', STYLES_TABLE); - -				$message = ($style_row['store_db']) ? '_ADDED_DB' : '_ADDED'; -				trigger_error($user->lang[$l_type . $message] . adm_back_link($this->u_action)); -			} -		} +	/** +	* Find all directories that have styles +	* +	* @return array Directory names +	*/ +	protected function find_style_dirs() +	{ +		$styles = array(); -		if ($mode == 'style') +		$dp = @opendir($this->styles_path); +		if ($dp)  		{ -			foreach ($element_ary as $element => $table) +			while (($file = readdir($dp)) !== false)  			{ -				$sql = "SELECT {$element}_id, {$element}_name -					FROM $table -					ORDER BY {$element}_id ASC"; -				$result = $db->sql_query($sql); +				$dir = $this->styles_path . $file; +				if ($file[0] == '.' || !is_dir($dir)) +				{ +					continue; +				} -				${$element . '_options'} = ''; -				while ($row = $db->sql_fetchrow($result)) +				if (file_exists("{$dir}/style.cfg"))  				{ -					$selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : ''; -					${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>'; +					$styles[] = $file;  				} -				$db->sql_freeresult($result);  			} +			closedir($dp);  		} -		$this->page_title = 'ADD_' . $l_type; - -		$template->assign_vars(array( -			'S_DETAILS'			=> true, -			'S_ADD'				=> true, -			'S_ERROR_MSG'		=> (sizeof($error)) ? true : false, -			'S_STYLE'			=> ($mode == 'style') ? true : false, -			'S_TEMPLATE'		=> ($mode == 'template') ? true : false, -			'S_THEME'			=> ($mode == 'theme') ? true : false, -			'S_BASIS'			=> ($basis) ? true : false, - -			'S_STORE_DB'			=> (isset($style_row['storedb'])) ? $style_row['storedb'] : 0, -			'S_STYLE_ACTIVE'		=> (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, -			'S_STYLE_DEFAULT'		=> (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, -			'S_TEMPLATE_OPTIONS'	=> ($mode == 'style') ? $template_options : '', -			'S_THEME_OPTIONS'		=> ($mode == 'style') ? $theme_options : '', -			'S_IMAGESET_OPTIONS'	=> ($mode == 'style') ? $imageset_options : '', - -			'U_ACTION'			=> $this->u_action . '&action=add&basis=' . $basis, -			'U_BACK'			=> $this->u_action, - -			'L_TITLE'				=> $user->lang[$this->page_title], -			'L_EXPLAIN'				=> $user->lang[$this->page_title . '_EXPLAIN'], -			'L_NAME'				=> $user->lang[$l_type . '_NAME'], -			'L_LOCATION'			=> ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '', -			'L_LOCATION_EXPLAIN'	=> ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '', - -			'ERROR_MSG'			=> (sizeof($error)) ? implode('<br />', $error) : '', -			'NAME'				=> $style_row[$mode . '_name'], -			'COPYRIGHT'			=> $style_row[$mode . '_copyright']) -		); - +		return $styles;  	}  	/** - -					$reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false; -					$reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false; -					$reqd_imageset = (isset($installcfg['required_imageset'])) ? $installcfg['required_imageset'] : false; - -					// Check to see if each element is already installed, if it is grab the id -					foreach ($element_ary as $element => $table) -					{ -						$style_row = array_merge($style_row, array( -							$element . '_id'			=> 0, -							$element . '_name'			=> '', -							$element . '_copyright'		=> '') -						); - -			 			$this->test_installed($element, $error, $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']); -	* Is this element installed? If not, grab its cfg details +	* Sort styles  	*/ -	function test_installed($element, &$error, $root_path, $reqd_name, &$id, &$name, &$copyright) +	public function sort_styles($style1, $style2)  	{ -		global $db, $user; - -		switch ($element) +		if ($style1['style_active'] != $style2['style_active'])  		{ -			case 'template': -				$sql_from = STYLES_TEMPLATE_TABLE; -			break; - -			case 'theme': -				$sql_from = STYLES_THEME_TABLE; -			break; - -			case 'imageset': -				$sql_from = STYLES_IMAGESET_TABLE; -			break; +			return ($style1['style_active']) ? -1 : 1;  		} - -		$l_element = strtoupper($element); - -		$chk_name = ($reqd_name !== false) ? $reqd_name : $name; - -		$sql = "SELECT {$element}_id, {$element}_name -			FROM $sql_from -			WHERE {$element}_name = '" . $db->sql_escape($chk_name) . "'"; -		$result = $db->sql_query($sql); - -		if ($row = $db->sql_fetchrow($result)) +		if (isset($style1['_available']) && $style1['_available'] != $style2['_available'])  		{ -			$name = $row[$element . '_name']; -			$id = $row[$element . '_id']; -		} -		else -		{ -			if (!($cfg = @file("$root_path$element/$element.cfg"))) -			{ -				$error[] = sprintf($user->lang['REQUIRES_' . $l_element], $reqd_name); -				return false; -			} - -			$cfg = parse_cfg_file("$root_path$element/$element.cfg", $cfg); - -			$name = $cfg['name']; -			$copyright = $cfg['copyright']; -			$id = 0; - -			unset($cfg); +			return ($style1['_available']) ? -1 : 1;  		} -		$db->sql_freeresult($result); +		return strcasecmp(isset($style1['style_name']) ? $style1['style_name'] : $style1['name'], isset($style2['style_name']) ? $style2['style_name'] : $style2['name']);  	}  	/** -	* Install/Add style +	* Read style configuration file +	* +	* @param string $dir style directory +	* @return array|bool Style data, false on error  	*/ -	function install_style(&$error, $action, $root_path, &$id, $name, $path, $copyright, $active, $default, &$style_row, $template_root_path = false, $template_path = false, $theme_root_path = false, $theme_path = false, $imageset_root_path = false, $imageset_path = false) +	protected function read_style_cfg($dir)  	{ -		global $config, $db, $user; - -		$element_ary = array('template', 'theme', 'imageset'); - -		if (!$name) -		{ -			$error[] = $user->lang['STYLE_ERR_STYLE_NAME']; -		} - -		// Check length settings -		if (utf8_strlen($name) > 30) -		{ -			$error[] = $user->lang['STYLE_ERR_NAME_LONG']; -		} - -		if (utf8_strlen($copyright) > 60) -		{ -			$error[] = $user->lang['STYLE_ERR_COPY_LONG']; -		} - -		// Check if the name already exist -		$sql = 'SELECT style_id -			FROM ' . STYLES_TABLE . " -			WHERE style_name = '" . $db->sql_escape($name) . "'"; -		$result = $db->sql_query($sql); -		$row = $db->sql_fetchrow($result); -		$db->sql_freeresult($result); - -		if ($row) -		{ -			$error[] = $user->lang['STYLE_ERR_NAME_EXIST']; -		} - -		if (sizeof($error)) -		{ -			return false; -		} +		static $required = array('name', 'phpbb_version', 'copyright'); +		$cfg = parse_cfg_file($this->styles_path . $dir . '/style.cfg'); -		foreach ($element_ary as $element) +		// Check if it is a valid file +		foreach ($required as $key)  		{ -			// Zero id value ... need to install element ... run usual checks -			// and do the install if necessary -			if (!$style_row[$element . '_id']) +			if (!isset($cfg[$key]))  			{ -				$this->install_element($element, $error, $action, (${$element . '_root_path'}) ? ${$element . '_root_path'} : $root_path, $style_row[$element . '_id'], $style_row[$element . '_name'], (${$element . '_path'}) ? ${$element . '_path'} : $path, $style_row[$element . '_copyright']); +				return false;  			}  		} -		if (!$style_row['template_id'] || !$style_row['theme_id'] || !$style_row['imageset_id']) +		// Check data +		if (!isset($cfg['parent']) || !is_string($cfg['parent']) || $cfg['parent'] == $cfg['name'])  		{ -			$error[] = $user->lang['STYLE_ERR_NO_IDS']; +			$cfg['parent'] = '';  		} - -		if (sizeof($error)) +		if (!isset($cfg['template_bitfield']))  		{ -			return false; +			$cfg['template_bitfield'] = $this->default_bitfield();  		} -		$db->sql_transaction('begin'); - -		$sql_ary = array( -			'style_name'		=> $name, -			'style_copyright'	=> $copyright, -			'style_active'		=> (int) $active, -			'template_id'		=> (int) $style_row['template_id'], -			'theme_id'			=> (int) $style_row['theme_id'], -			'imageset_id'		=> (int) $style_row['imageset_id'], -		); - -		$sql = 'INSERT INTO ' . STYLES_TABLE . ' -			' . $db->sql_build_array('INSERT', $sql_ary); -		$db->sql_query($sql); - -		$id = $db->sql_nextid(); - -		if ($default) -		{ -			$sql = 'UPDATE ' . USERS_TABLE . " -				SET user_style = $id -				WHERE user_style = " . $config['default_style']; -			$db->sql_query($sql); - -			set_config('default_style', $id); -		} - -		$db->sql_transaction('commit'); - -		add_log('admin', 'LOG_STYLE_ADD', $name); +		return $cfg;  	}  	/** -	* Install/add an element, doing various checks as we go +	* Install style +	* +	* @param array $style style data +	* @return int Style id  	*/ -	function install_element($mode, &$error, $action, $root_path, &$id, $name, $path, $copyright, $store_db = 0) +	protected function install_style($style)  	{ -		global $phpbb_root_path, $db, $user; - -		// we parse the cfg here (again) -		$cfg_data = parse_cfg_file("$root_path$mode/$mode.cfg"); - -		switch ($mode) -		{ -			case 'template': -				$sql_from = STYLES_TEMPLATE_TABLE; -			break; - -			case 'theme': -				$sql_from = STYLES_THEME_TABLE; -			break; - -			case 'imageset': -				$sql_from = STYLES_IMAGESET_TABLE; -			break; -		} - -		$l_type = strtoupper($mode); - -		if (!$name) -		{ -			$error[] = $user->lang[$l_type . '_ERR_STYLE_NAME']; -		} - -		// Check length settings -		if (utf8_strlen($name) > 30) -		{ -			$error[] = $user->lang[$l_type . '_ERR_NAME_LONG']; -		} - -		if (utf8_strlen($copyright) > 60) +		// Generate row +		$sql_ary = array(); +		foreach ($style as $key => $value)  		{ -			$error[] = $user->lang[$l_type . '_ERR_COPY_LONG']; -		} - -		// Check if the name already exist -		$sql = "SELECT {$mode}_id -			FROM $sql_from -			WHERE {$mode}_name = '" . $db->sql_escape($name) . "'"; -		$result = $db->sql_query($sql); -		$row = $db->sql_fetchrow($result); -		$db->sql_freeresult($result); - -		if ($row) -		{ -			// If it exist, we just use the style on installation -			if ($action == 'install') +			if ($key != 'style_id' && substr($key, 0, 1) != '_')  			{ -				$id = $row[$mode . '_id']; -				return false; +				$sql_ary[$key] = $value;  			} - -			$error[] = $user->lang[$l_type . '_ERR_NAME_EXIST']; -		} - -		if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from']) -		{ -			if ($mode === 'template') -			{ -				$select_bf = ', bbcode_bitfield'; -			} -			else -			{ -				$select_bf = ''; -			} - -			$sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path, {$mode}_storedb $select_bf -				FROM $sql_from -				WHERE {$mode}_name = '" . $db->sql_escape($cfg_data['inherit_from']) . "' -					AND {$mode}_inherits_id = 0"; -			$result = $db->sql_query($sql); -			$row = $db->sql_fetchrow($result); -			$db->sql_freeresult($result); -			if (!$row) -			{ -				$error[] = sprintf($user->lang[$l_type . '_ERR_REQUIRED_OR_INCOMPLETE'], $cfg_data['inherit_from']); -			} -			else -			{ -				$inherit_id = $row["{$mode}_id"]; -				$inherit_path = $row["{$mode}_path"]; -				$inherit_bf = ($mode === 'template') ? $row["bbcode_bitfield"] : false; -				$cfg_data['store_db'] = $row["{$mode}_storedb"]; -				$store_db = $row["{$mode}_storedb"]; -			} -		} -		else -		{ -			$inherit_id = 0; -			$inherit_path = ''; -			$inherit_bf = false; -		} - -		if (sizeof($error)) -		{ -			return false; -		} - -		$sql_ary = array( -			$mode . '_name'			=> $name, -			$mode . '_copyright'	=> $copyright, -			$mode . '_path'			=> $path, -		); - -		switch ($mode) -		{ -			case 'template': -				// We check if the template author defined a different bitfield -				if (!empty($cfg_data['template_bitfield'])) -				{ -					$sql_ary['bbcode_bitfield'] = $cfg_data['template_bitfield']; -				} -				else if ($inherit_bf) -				{ -					$sql_ary['bbcode_bitfield'] = $inherit_bf; -				} -				else -				{ -					$sql_ary['bbcode_bitfield'] = TEMPLATE_BITFIELD; -				} - -				// We set a pre-defined bitfield here which we may use further in 3.2 -				$sql_ary += array( -					'template_storedb'		=> $store_db, -				); -				if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from']) -				{ -					$sql_ary += array( -						'template_inherits_id'	=> $inherit_id, -						'template_inherit_path' => $inherit_path, -					); -				} -			break; - -			case 'theme': -				// We are only interested in the theme configuration for now - -				if (isset($cfg_data['parse_css_file']) && $cfg_data['parse_css_file']) -				{ -					$store_db = 1; -				} - -				$sql_ary += array( -					'theme_storedb'	=> $store_db, -					'theme_data'	=> ($store_db) ? $this->db_theme_data($sql_ary, false, $root_path) : '', -					'theme_mtime'	=> (int) filemtime("{$phpbb_root_path}styles/$path/theme/stylesheet.css") -				); -			break; - -			// all the heavy lifting is done later -			case 'imageset': -			break; -		} - -		$db->sql_transaction('begin'); - -		$sql = "INSERT INTO $sql_from -			" . $db->sql_build_array('INSERT', $sql_ary); -		$db->sql_query($sql); - -		$id = $db->sql_nextid(); - -		if ($mode == 'template' && $store_db) -		{ -			$filelist = filelist("{$root_path}template", '', 'html'); -			$this->store_templates('insert', $id, $path, $filelist);  		} -		else if ($mode == 'imageset') -		{ -			$cfg_data = parse_cfg_file("$root_path$mode/imageset.cfg"); -			$imageset_definitions = array(); -			foreach ($this->imageset_keys as $topic => $key_array) -			{ -				$imageset_definitions = array_merge($imageset_definitions, $key_array); -			} +		// Add to database +		$this->db->sql_transaction('begin'); -			foreach ($cfg_data as $key => $value) -			{ -				if (strpos($value, '*') !== false) -				{ -					if (substr($value, -1, 1) === '*') -					{ -						list($image_filename, $image_height) = explode('*', $value); -						$image_width = 0; -					} -					else -					{ -						list($image_filename, $image_height, $image_width) = explode('*', $value); -					} -				} -				else -				{ -					$image_filename = $value; -					$image_height = $image_width = 0; -				} - -				if (strpos($key, 'img_') === 0 && $image_filename) -				{ -					$key = substr($key, 4); -					if (in_array($key, $imageset_definitions)) -					{ -						$sql_ary = array( -							'image_name'		=> $key, -							'image_filename'	=> str_replace('{PATH}', "styles/$path/imageset/", trim($image_filename)), -							'image_height'		=> (int) $image_height, -							'image_width'		=> (int) $image_width, -							'imageset_id'		=> (int) $id, -							'image_lang'		=> '', -						); -						$db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); -					} -				} -			} -			unset($cfg_data); +		$sql = 'INSERT INTO ' . STYLES_TABLE . ' +			' . $this->db->sql_build_array('INSERT', $sql_ary); +		$this->db->sql_query($sql); -			$sql = 'SELECT lang_dir -				FROM ' . LANG_TABLE; -			$result = $db->sql_query($sql); +		$id = $this->db->sql_nextid(); -			while ($row = $db->sql_fetchrow($result)) -			{ -				if (@file_exists("$root_path$mode/{$row['lang_dir']}/imageset.cfg")) -				{ -					$cfg_data_imageset_data = parse_cfg_file("$root_path$mode/{$row['lang_dir']}/imageset.cfg"); -					foreach ($cfg_data_imageset_data as $image_name => $value) -					{ -						if (strpos($value, '*') !== false) -						{ -							if (substr($value, -1, 1) === '*') -							{ -								list($image_filename, $image_height) = explode('*', $value); -								$image_width = 0; -							} -							else -							{ -								list($image_filename, $image_height, $image_width) = explode('*', $value); -							} -						} -						else -						{ -							$image_filename = $value; -							$image_height = $image_width = 0; -						} +		$this->db->sql_transaction('commit'); -						if (strpos($image_name, 'img_') === 0 && $image_filename) -						{ -							$image_name = substr($image_name, 4); -							if (in_array($image_name, $imageset_definitions)) -							{ -								$sql_ary = array( -									'image_name'		=> $image_name, -									'image_filename'	=> $image_filename, -									'image_height'		=> (int) $image_height, -									'image_width'		=> (int) $image_width, -									'imageset_id'		=> (int) $id, -									'image_lang'		=> $row['lang_dir'], -								); -								$db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); -							} -						} -					} -					unset($cfg_data_imageset_data); -				} -			} -			$db->sql_freeresult($result); -		} +		add_log('admin', 'LOG_STYLE_ADD', $sql_ary['style_name']); -		$db->sql_transaction('commit'); - -		$log = ($store_db) ? 'LOG_' . $l_type . '_ADD_DB' : 'LOG_' . $l_type . '_ADD_FS'; -		add_log('admin', $log, $name); - -		// Return store_db in case it had to be altered -		return $store_db; +		return $id;  	}  	/** -	* Checks downwards dependencies +	* Lists all styles  	* -	* @access public -	* @param string $mode The element type to check - only template is supported -	* @param int $id The template id -	* @returns false if no component inherits, array with name, path and id for each subtemplate otherwise +	* @return array Rows with styles data  	*/ -	function check_inheritance($mode, $id) +	protected function get_styles()  	{ -		global $db; - -		$l_type = strtoupper($mode); - -		switch ($mode) -		{ -			case 'template': -				$sql_from = STYLES_TEMPLATE_TABLE; -			break; +		$sql = 'SELECT * +			FROM ' . STYLES_TABLE; +		$result = $this->db->sql_query($sql); -			case 'theme': -				$sql_from = STYLES_THEME_TABLE; -			break; +		$rows = $this->db->sql_fetchrowset($result); +		$this->db->sql_freeresult($result); -			case 'imageset': -				$sql_from = STYLES_IMAGESET_TABLE; -			break; -		} +		return $rows; +	} -		$sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path -			FROM $sql_from -			WHERE {$mode}_inherits_id = " . (int) $id; -		$result = $db->sql_query($sql); +	/** +	* Count users for each style +	* +	* @return array Styles in following format: [style_id] = number of users +	*/ +	protected function get_users() +	{ +		$sql = 'SELECT user_style, COUNT(user_style) AS style_count +			FROM ' . USERS_TABLE . ' +			GROUP BY user_style'; +		$result = $this->db->sql_query($sql); -		$names = array(); -		while ($row = $db->sql_fetchrow($result)) +		$style_count = array(); +		while ($row = $this->db->sql_fetchrow($result))  		{ - -			$names[$row["{$mode}_id"]] = array( -				"{$mode}_id" => $row["{$mode}_id"], -				"{$mode}_name" => $row["{$mode}_name"], -				"{$mode}_path" => $row["{$mode}_path"], -			); +			$style_count[$row['user_style']] = $row['style_count'];  		} -		$db->sql_freeresult($result); +		$this->db->sql_freeresult($result); -		if (sizeof($names)) -		{ -			return $names; -		} -		else -		{ -			return false; -		} +		return $style_count;  	}  	/** -	* Checks upwards dependencies +	* Uninstall style  	* -	* @access public -	* @param string $mode The element type to check - only template is supported -	* @param int $id The template id -	* @returns false if the component does not inherit, array with name, path and id otherwise +	* @param array $style Style data +	* @return bool|string True on success, error message on error  	*/ -	function get_super($mode, $id) +	protected function uninstall_style($style)  	{ -		global $db; - -		$l_type = strtoupper($mode); - -		switch ($mode) -		{ -			case 'template': -				$sql_from = STYLES_TEMPLATE_TABLE; -			break; +		$id = $style['style_id']; +		$path = $style['style_path']; -			case 'theme': -				$sql_from = STYLES_THEME_TABLE; -			break; - -			case 'imageset': -				$sql_from = STYLES_IMAGESET_TABLE; -			break; -		} +		// Check if style has child styles +		$sql = 'SELECT style_id +			FROM ' . STYLES_TABLE . ' +			WHERE style_parent_id = ' . (int) $id . " OR style_parent_tree = '" . $this->db->sql_escape($path) . "'"; +		$result = $this->db->sql_query($sql); -		$sql = "SELECT {$mode}_inherits_id -			FROM $sql_from -			WHERE {$mode}_id = " . (int) $id; -		$result = $db->sql_query_limit($sql, 1); +		$conflict = $this->db->sql_fetchrow($result); +		$this->db->sql_freeresult($result); -		if ($row = $db->sql_fetchrow($result)) -		{ -			$db->sql_freeresult($result); -		} -		else +		if ($conflict !== false)  		{ -			return false; +			return sprintf($this->user->lang['STYLE_UNINSTALL_DEPENDENT'], $style['style_name']);  		} -		$super_id = $row["{$mode}_inherits_id"]; - -		$sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path -			FROM $sql_from -			WHERE {$mode}_id = " . (int) $super_id; - -		$result = $db->sql_query_limit($sql, 1); -		if ($row = $db->sql_fetchrow($result)) -		{ -			$db->sql_freeresult($result); -			return $row; -		} +		// Change default style for users +		$sql = 'UPDATE ' . USERS_TABLE . ' +			SET user_style = 0 +			WHERE user_style = ' . $id; +		$this->db->sql_query($sql); -		return false; +		// Uninstall style +		$sql = 'DELETE FROM ' . STYLES_TABLE . ' +			WHERE style_id = ' . $id; +		$this->db->sql_query($sql); +		return true;  	}  	/** -	* Moves a template set and its subtemplates to the database +	* Delete all files in style directory  	* -	* @access public -	* @param string $mode The component to move - only template is supported -	* @param int $id The template id +	* @param string $path Style directory +	* @param string $dir Directory to remove inside style's directory +	* @return bool True on success, false on error  	*/ -	function store_in_db($mode, $id) +	protected function delete_style_files($path, $dir = '')  	{ -		global $db, $user; +		$dirname = $this->styles_path . $path . $dir; +		$result = true; -		$error = array(); -		$l_type = strtoupper($mode); -		if ($super = $this->get_super($mode, $id)) -		{ -			$error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name'])); -			return $error; -		} +		$dp = @opendir($dirname); -		$sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path -			FROM " . STYLES_TEMPLATE_TABLE . ' -			WHERE template_id = ' . (int) $id; - -		$result = $db->sql_query_limit($sql, 1); -		if ($row = $db->sql_fetchrow($result)) +		if ($dp)  		{ -			$db->sql_freeresult($result); -			$subs = $this->check_inheritance($mode, $id); - -			$this->_store_in_db($mode, $id, $row["{$mode}_path"]); -			if ($subs && sizeof($subs)) +			while (($file = readdir($dp)) !== false)  			{ -				foreach ($subs as $sub_id => $sub) +				if ($file == '.' || $file == '..') +				{ +					continue; +				} +				$filename = $dirname . '/' . $file; +				if (is_dir($filename)) +				{ +					if (!$this->delete_style_files($path, $dir . '/' . $file)) +					{ +						$result = false; +					} +				} +				else  				{ -					if ($err = $this->_store_in_db($mode, $sub["{$mode}_id"], $sub["{$mode}_path"])) +					if (!@unlink($filename))  					{ -						$error[] = $err; +						$result = false;  					}  				}  			} +			closedir($dp);  		} -		if (sizeof($error)) +		if (!@rmdir($dirname))  		{ -			return $error; +			return false;  		} -		return false; -	} - -	/** -	* Moves a template set to the database -	* -	* @access private -	* @param string $mode The component to move - only template is supported -	* @param int $id The template id -	* @param string $path TThe path to the template files -	*/ -	function _store_in_db($mode, $id, $path) -	{ -		global $phpbb_root_path, $db; - -		$filelist = filelist("{$phpbb_root_path}styles/{$path}/template", '', 'html'); -		$this->store_templates('insert', $id, $path, $filelist); - -		// Okay, we do the query here -shouldn't be triggered often. -		$sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . ' -						SET template_storedb = 1 -						WHERE template_id = ' . $id; -		$db->sql_query($sql); +		return $result;  	}  	/** -	* Moves a template set and its subtemplates to the filesystem +	* Get list of items from posted data  	* -	* @access public -	* @param string $mode The component to move - only template is supported -	* @param int $id The template id +	* @param string $name Variable name +	* @param string|int $default Default value for array +	* @param bool $error If true, error will be triggered if list is empty +	* @return array Items  	*/ -	function store_in_fs($mode, $id) +	protected function request_vars($name, $default, $error = false)  	{ -		global $db, $user; +		$item = $this->request->variable($name, $default); +		$items = $this->request->variable($name . 's', array($default)); -		$error = array(); -		$l_type = strtoupper($mode); -		if ($super = $this->get_super($mode, $id)) +		if (count($items) == 1 && $items[0] == $default)  		{ -			$error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name'])); -			return($error); +			$items = array();  		} -		$sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path -			FROM " . STYLES_TEMPLATE_TABLE . ' -			WHERE template_id = ' . (int) $id; - -		$result = $db->sql_query_limit($sql, 1); -		if ($row = $db->sql_fetchrow($result)) +		if ($item != $default && !count($items))  		{ -			$db->sql_freeresult($result); -			if (!sizeof($error)) -			{ -				$subs = $this->check_inheritance($mode, $id); - -				$this->_store_in_fs($mode, $id, $row["{$mode}_path"]); +			$items[] = $item; +		} -				if ($subs && sizeof($subs)) -				{ -					foreach ($subs as $sub_id => $sub) -					{ -						$this->_store_in_fs($mode, $sub["{$mode}_id"], $sub["{$mode}_path"]); -					} -				} -			} -			if (sizeof($error)) -			{ -				$this->store_in_db($id, $mode); -				return $error; -			} +		if ($error && !count($items)) +		{ +			trigger_error($this->user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);  		} -		return false; + +		return $items;  	}  	/** -	* Moves a template set to the filesystem +	* Generates default bitfield +	* +	* This bitfield decides which bbcodes are defined in a template.  	* -	* @access private -	* @param string $mode The component to move - only template is supported -	* @param int $id The template id -	* @param string $path The path to the template +	* @return string Bitfield  	*/ -	function _store_in_fs($mode, $id, $path) +	protected function default_bitfield()  	{ -		global $phpbb_root_path, $db, $user, $safe_mode; - -		$store_db = 0; -		$error = array(); -		if (!$safe_mode && phpbb_is_writable("{$phpbb_root_path}styles/{$path}/template")) +		static $value; +		if (isset($value))  		{ -			$sql = 'SELECT * -					FROM ' . STYLES_TEMPLATE_DATA_TABLE . " -					WHERE template_id = $id"; -			$result = $db->sql_query($sql); - -			while ($row = $db->sql_fetchrow($result)) -			{ -				if (!($fp = @fopen("{$phpbb_root_path}styles/{$path}/template/" . $row['template_filename'], 'wb'))) -				{ -					$store_db = 1; -					$error[] = $user->lang['EDIT_TEMPLATE_STORED_DB']; -					break; -				} - -				fwrite($fp, $row['template_data']); -				fclose($fp); -			} -			$db->sql_freeresult($result); - -			if (!$store_db) -			{ -				$sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . " -						WHERE template_id = $id"; -				$db->sql_query($sql); -			} +			return $value;  		} -		if (sizeof($error)) -		{ -			return $error; -		} -		$sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . ' -				SET template_storedb = 0 -				WHERE template_id = ' . $id; -		$db->sql_query($sql); -		return false; +		// Hardcoded template bitfield to add for new templates +		$bitfield = new bitfield(); +		$bitfield->set(0); +		$bitfield->set(1); +		$bitfield->set(2); +		$bitfield->set(3); +		$bitfield->set(4); +		$bitfield->set(8); +		$bitfield->set(9); +		$bitfield->set(11); +		$bitfield->set(12); +		$value = $bitfield->get_base64(); +		return $value;  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php index 5d3e9abcea..0167a06dbb 100644 --- a/phpBB/includes/acp/acp_update.php +++ b/phpBB/includes/acp/acp_update.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,75 +19,48 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_update  {  	var $u_action;  	function main($id, $mode)  	{ -		global $config, $db, $user, $auth, $template, $cache; -		global $phpbb_root_path, $phpbb_admin_path, $phpEx; +		global $config, $user, $template, $request; +		global $phpbb_root_path, $phpEx, $phpbb_container;  		$user->add_lang('install');  		$this->tpl_name = 'acp_update';  		$this->page_title = 'ACP_VERSION_CHECK'; -		// Get current and latest version -		$errstr = ''; -		$errno = 0; - -		$info = obtain_latest_version_info(request_var('versioncheck_force', false)); - -		if (empty($info)) +		$version_helper = $phpbb_container->get('version_helper'); +		try  		{ -			trigger_error('VERSIONCHECK_FAIL', E_USER_WARNING); +			$recheck = $request->variable('versioncheck_force', false); +			$updates_available = $version_helper->get_suggested_updates($recheck);  		} +		catch (\RuntimeException $e) +		{ +			$template->assign_var('S_VERSIONCHECK_FAIL', true); -		$info = explode("\n", $info); -		$latest_version = trim($info[0]); - -		$announcement_url = trim($info[1]); -		$announcement_url = (strpos($announcement_url, '&') === false) ? str_replace('&', '&', $announcement_url) : $announcement_url; -		$update_link = append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=update'); +			$updates_available = array(); +		} -		// next feature release -		$next_feature_version = $next_feature_announcement_url = false; -		if (isset($info[2]) && trim($info[2]) !== '') +		foreach ($updates_available as $branch => $version_data)  		{ -			$next_feature_version = trim($info[2]); -			$next_feature_announcement_url = trim($info[3]); +			$template->assign_block_vars('updates_available', $version_data);  		} -		// Determine automatic update... -		$sql = 'SELECT config_value -			FROM ' . CONFIG_TABLE . " -			WHERE config_name = 'version_update_from'"; -		$result = $db->sql_query($sql); -		$version_update_from = (string) $db->sql_fetchfield('config_value'); -		$db->sql_freeresult($result); - -		$current_version = (!empty($version_update_from)) ? $version_update_from : $config['version']; +		$update_link = append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=update');  		$template->assign_vars(array( -			'S_UP_TO_DATE'		=> phpbb_version_compare($latest_version, $config['version'], '<='), -			'S_UP_TO_DATE_AUTO'	=> phpbb_version_compare($latest_version, $current_version, '<='), -			'S_VERSION_CHECK'	=> true, -			'U_ACTION'			=> $this->u_action, -			'U_VERSIONCHECK_FORCE' => append_sid($this->u_action . '&versioncheck_force=1'), +			'S_UP_TO_DATE'			=> empty($updates_available), +			'U_ACTION'				=> $this->u_action, +			'U_VERSIONCHECK_FORCE'	=> append_sid($this->u_action . '&versioncheck_force=1'), -			'LATEST_VERSION'	=> $latest_version, -			'CURRENT_VERSION'	=> $config['version'], -			'AUTO_VERSION'		=> $version_update_from, -			'NEXT_FEATURE_VERSION'	=> $next_feature_version, +			'CURRENT_VERSION'		=> $config['version'], -			'UPDATE_INSTRUCTIONS'	=> sprintf($user->lang['UPDATE_INSTRUCTIONS'], $announcement_url, $update_link), -			'UPGRADE_INSTRUCTIONS'	=> $next_feature_version ? $user->lang('UPGRADE_INSTRUCTIONS', $next_feature_version, $next_feature_announcement_url) : false, +			'UPDATE_INSTRUCTIONS'	=> sprintf($user->lang['UPDATE_INSTRUCTIONS'], $update_link),  		));  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index b82be8887c..881e50dd5a 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -16,9 +19,6 @@ if (!defined('IN_PHPBB'))  	exit;  } -/** -* @package acp -*/  class acp_users  {  	var $u_action; @@ -33,10 +33,11 @@ class acp_users  	{  		global $config, $db, $user, $auth, $template, $cache;  		global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $file_uploads; +		global $phpbb_dispatcher, $request; +		global $phpbb_container;  		$user->add_lang(array('posting', 'ucp', 'acp/users'));  		$this->tpl_name = 'acp_users'; -		$this->page_title = 'ACP_USER_' . strtoupper($mode);  		$error		= array();  		$username	= utf8_normalize_nfc(request_var('username', '', true)); @@ -56,7 +57,7 @@ class acp_users  			$this->page_title = 'WHOIS';  			$this->tpl_name = 'simple_body'; -			$user_ip = request_var('user_ip', ''); +			$user_ip = phpbb_ip_normalise(request_var('user_ip', ''));  			$domain = gethostbyaddr($user_ip);  			$ipwhois = user_ipwhois($user_ip); @@ -120,7 +121,7 @@ class acp_users  		// Build modes dropdown list  		$sql = 'SELECT module_mode, module_auth  			FROM ' . MODULES_TABLE . " -			WHERE module_basename = 'users' +			WHERE module_basename = 'acp_users'  				AND module_enabled = 1  				AND module_class = 'acp'  			ORDER BY left_id, module_mode"; @@ -129,7 +130,7 @@ class acp_users  		$dropdown_modes = array();  		while ($row = $db->sql_fetchrow($result))  		{ -			if (!$this->p_master->module_auth($row['module_auth'])) +			if (!$this->p_master->module_auth_self($row['module_auth']))  			{  				continue;  			} @@ -158,6 +159,8 @@ class acp_users  			trigger_error($user->lang['NOT_MANAGE_FOUNDER'] . adm_back_link($this->u_action), E_USER_WARNING);  		} +		$this->page_title = $user_row['username'] . ' :: ' . $user->lang('ACP_USER_' . strtoupper($mode)); +  		switch ($mode)  		{  			case 'overview': @@ -170,6 +173,21 @@ class acp_users  				$delete_type	= request_var('delete_type', '');  				$ip				= request_var('ip', 'ip'); +				/** +				 * Run code at beginning of ACP users overview +				 * +				 * @event core.acp_users_overview_before +				 * @var	array   user_row    Current user data +				 * @var	string  mode        Active module +				 * @var	string  action      Module that should be run +				 * @var	bool    submit      Do we display the form only +				 *                          or did the user press submit +				 * @var	array   error       Array holding error messages +				 * @since 3.1.3-RC1 +				 */ +				$vars = array('user_row', 'mode', 'action', 'submit', 'error'); +				extract($phpbb_dispatcher->trigger_event('core.acp_users_overview_before', compact($vars))); +  				if ($submit)  				{  					if ($delete) @@ -351,7 +369,7 @@ class acp_users  								$messenger->template($email_template, $user_row['user_lang']); -								$messenger->to($user_row['user_email'], $user_row['username']); +								$messenger->set_addresses($user_row);  								$messenger->anti_abuse_headers($config, $user); @@ -400,13 +418,16 @@ class acp_users  							{  								if ($config['require_activation'] == USER_ACTIVATION_ADMIN)  								{ +									$phpbb_notifications = $phpbb_container->get('notification_manager'); +									$phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_row['user_id']); +  									include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);  									$messenger = new messenger(false);  									$messenger->template('admin_welcome_activated', $user_row['user_lang']); -									$messenger->to($user_row['user_email'], $user_row['username']); +									$messenger->set_addresses($user_row);  									$messenger->anti_abuse_headers($config, $user); @@ -459,23 +480,9 @@ class acp_users  								trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);  							} -							$sql_ary = array( -								'user_avatar'			=> '', -								'user_avatar_type'		=> 0, -								'user_avatar_width'		=> 0, -								'user_avatar_height'	=> 0, -							); - -							$sql = 'UPDATE ' . USERS_TABLE . ' -								SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " -								WHERE user_id = $user_id"; -							$db->sql_query($sql); -  							// Delete old avatar if present -							if ($user_row['user_avatar'] && $user_row['user_avatar_type'] != AVATAR_GALLERY) -							{ -								avatar_delete('user', $user_row); -							} +							$phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); +							$phpbb_avatar_manager->handle_avatar_delete($db, $user, $phpbb_avatar_manager->clean_row($user_row, 'user'), USERS_TABLE, 'user_');  							add_log('admin', 'LOG_USER_DEL_AVATAR', $user_row['username']);  							add_log('user', $user_id, 'LOG_USER_DEL_AVATAR_USER'); @@ -626,29 +633,32 @@ class acp_users  							$topic_id_ary = $move_topic_ary = $move_post_ary = $new_topic_id_ary = array();  							$forum_id_ary = array($new_forum_id); -							$sql = 'SELECT topic_id, COUNT(post_id) AS total_posts +							$sql = 'SELECT topic_id, post_visibility, COUNT(post_id) AS total_posts  								FROM ' . POSTS_TABLE . "  								WHERE poster_id = $user_id  									AND forum_id <> $new_forum_id -								GROUP BY topic_id"; +								GROUP BY topic_id, post_visibility";  							$result = $db->sql_query($sql);  							while ($row = $db->sql_fetchrow($result))  							{ -								$topic_id_ary[$row['topic_id']] = $row['total_posts']; +								$topic_id_ary[$row['topic_id']][$row['post_visibility']] = $row['total_posts'];  							}  							$db->sql_freeresult($result);  							if (sizeof($topic_id_ary))  							{ -								$sql = 'SELECT topic_id, forum_id, topic_title, topic_replies, topic_replies_real, topic_attachment +								$sql = 'SELECT topic_id, forum_id, topic_title, topic_posts_approved, topic_posts_unapproved, topic_posts_softdeleted, topic_attachment  									FROM ' . TOPICS_TABLE . '  									WHERE ' . $db->sql_in_set('topic_id', array_keys($topic_id_ary));  								$result = $db->sql_query($sql);  								while ($row = $db->sql_fetchrow($result))  								{ -									if (max($row['topic_replies'], $row['topic_replies_real']) + 1 == $topic_id_ary[$row['topic_id']]) +									if ($topic_id_ary[$row['topic_id']][ITEM_APPROVED] == $row['topic_posts_approved'] +										&& $topic_id_ary[$row['topic_id']][ITEM_UNAPPROVED] == $row['topic_posts_unapproved'] +										&& $topic_id_ary[$row['topic_id']][ITEM_REAPPROVE] == $row['topic_posts_unapproved'] +										&& $topic_id_ary[$row['topic_id']][ITEM_DELETED] == $row['topic_posts_softdeleted'])  									{  										$move_topic_ary[] = $row['topic_id'];  									} @@ -681,7 +691,7 @@ class acp_users  										'topic_time'				=> time(),  										'forum_id' 					=> $new_forum_id,  										'icon_id'					=> 0, -										'topic_approved'			=> 1, +										'topic_visibility'			=> ITEM_APPROVED,  										'topic_title' 				=> $post_ary['title'],  										'topic_first_poster_name'	=> $user_row['username'],  										'topic_type'				=> POST_NORMAL, @@ -726,7 +736,6 @@ class acp_users  								sync('forum', 'forum_id', $forum_id_ary, false, true);  							} -  							add_log('admin', 'LOG_USER_MOVE_POSTS', $user_row['username'], $forum_info['forum_name']);  							add_log('user', $user_id, 'LOG_USER_MOVE_POSTS_USER', $forum_info['forum_name']); @@ -755,6 +764,19 @@ class acp_users  							}  						break; + +						default: +							/** +							* Run custom quicktool code +							* +							* @event core.acp_users_overview_run_quicktool +							* @var	array	user_row	Current user data +							* @var	string	action		Quick tool that should be run +							* @since 3.1.0-a1 +							*/ +							$vars = array('action', 'user_row'); +							extract($phpbb_dispatcher->trigger_event('core.acp_users_overview_run_quicktool', compact($vars))); +						break;  					}  					// Handle registration info updates @@ -762,9 +784,8 @@ class acp_users  						'username'			=> utf8_normalize_nfc(request_var('user', $user_row['username'], true)),  						'user_founder'		=> request_var('user_founder', ($user_row['user_type'] == USER_FOUNDER) ? 1 : 0),  						'email'				=> strtolower(request_var('user_email', $user_row['user_email'])), -						'email_confirm'		=> strtolower(request_var('email_confirm', '')), -						'new_password'		=> request_var('new_password', '', true), -						'password_confirm'	=> request_var('password_confirm', '', true), +						'new_password'		=> $request->variable('new_password', '', true), +						'password_confirm'	=> $request->variable('password_confirm', '', true),  					);  					// Validation data - we do not check the password complexity setting here @@ -792,9 +813,8 @@ class acp_users  						$check_ary += array(  							'email'				=> array(  								array('string', false, 6, 60), -								array('email', $user_row['user_email']) +								array('user_email', $user_row['user_email']),  							), -							'email_confirm'		=> array('string', true, 6, 60)  						);  					} @@ -805,19 +825,17 @@ class acp_users  						$error[] = 'NEW_PASSWORD_ERROR';  					} -					if ($data['email'] != $user_row['user_email'] && $data['email_confirm'] != $data['email']) -					{ -						$error[] = 'NEW_EMAIL_ERROR'; -					} -  					if (!check_form_key($form_name))  					{  						$error[] = 'FORM_INVALID';  					} +					// Instantiate passwords manager +					$passwords_manager = $phpbb_container->get('passwords.manager'); +  					// Which updates do we need to do?  					$update_username = ($user_row['username'] != $data['username']) ? $data['username'] : false; -					$update_password = ($data['new_password'] && !phpbb_check_hash($data['new_password'], $user_row['user_password'])) ? true : false; +					$update_password = $data['new_password'] && !$passwords_manager->check($data['new_password'], $user_row['user_password']);  					$update_email = ($data['email'] != $user_row['user_email']) ? $data['email'] : false;  					if (!sizeof($error)) @@ -868,6 +886,18 @@ class acp_users  							}  						} +						/** +						* Modify user data before we update it +						* +						* @event core.acp_users_overview_modify_data +						* @var	array	user_row	Current user data +						* @var	array	data		Submitted user data +						* @var	array	sql_ary		User data we udpate +						* @since 3.1.0-a1 +						*/ +						$vars = array('user_row', 'data', 'sql_ary'); +						extract($phpbb_dispatcher->trigger_event('core.acp_users_overview_modify_data', compact($vars))); +  						if ($update_username !== false)  						{  							$sql_ary['username'] = $update_username; @@ -889,9 +919,8 @@ class acp_users  						if ($update_password)  						{  							$sql_ary += array( -								'user_password'		=> phpbb_hash($data['new_password']), +								'user_password'		=> $passwords_manager->hash($data['new_password']),  								'user_passchg'		=> time(), -								'user_pass_convert'	=> 0,  							);  							$user->reset_login_keys($user_id); @@ -920,7 +949,7 @@ class acp_users  					}  					// Replace "error" strings with their real, localised form -					$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); +					$error = array_map(array($user, 'lang'), $error);  				}  				if ($user_id == $user->data['user_id']) @@ -958,12 +987,6 @@ class acp_users  					}  				} -				$s_action_options = '<option class="sep" value="">' . $user->lang['SELECT_OPTION'] . '</option>'; -				foreach ($quick_tool_ary as $value => $lang) -				{ -					$s_action_options .= '<option value="' . $value . '">' . $user->lang['USER_ADMIN_' . $lang] . '</option>'; -				} -  				if ($config['load_onlinetrack'])  				{  					$sql = 'SELECT MAX(session_time) AS session_time, MIN(session_viewonline) AS session_viewonline @@ -978,7 +1001,24 @@ class acp_users  					unset($row);  				} -				$last_visit = (!empty($user_row['session_time'])) ? $user_row['session_time'] : $user_row['user_lastvisit']; +				/** +				* Add additional quick tool options and overwrite user data +				* +				* @event core.acp_users_display_overview +				* @var	array	user_row			Array with user data +				* @var	array	quick_tool_ary		Ouick tool options +				* @since 3.1.0-a1 +				*/ +				$vars = array('user_row', 'quick_tool_ary'); +				extract($phpbb_dispatcher->trigger_event('core.acp_users_display_overview', compact($vars))); + +				$s_action_options = '<option class="sep" value="">' . $user->lang['SELECT_OPTION'] . '</option>'; +				foreach ($quick_tool_ary as $value => $lang) +				{ +					$s_action_options .= '<option value="' . $value . '">' . $user->lang['USER_ADMIN_' . $lang] . '</option>'; +				} + +				$last_active = (!empty($user_row['session_time'])) ? $user_row['session_time'] : $user_row['user_lastvisit'];  				$inactive_reason = '';  				if ($user_row['user_type'] == USER_INACTIVE) @@ -1009,7 +1049,7 @@ class acp_users  				$sql = 'SELECT COUNT(post_id) as posts_in_queue  					FROM ' . POSTS_TABLE . '  					WHERE poster_id = ' . $user_id . ' -						AND post_approved = 0'; +						AND ' . $db->sql_in_set('post_visibility', array(ITEM_UNAPPROVED, ITEM_REAPPROVE));  				$result = $db->sql_query($sql);  				$user_row['posts_in_queue'] = (int) $db->sql_fetchfield('posts_in_queue');  				$db->sql_freeresult($result); @@ -1022,8 +1062,8 @@ class acp_users  				$db->sql_freeresult($result);  				$template->assign_vars(array( -					'L_NAME_CHARS_EXPLAIN'		=> sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), -					'L_CHANGE_PASSWORD_EXPLAIN'	=> sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), +					'L_NAME_CHARS_EXPLAIN'		=> $user->lang($config['allow_name_chars'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_name_chars']), $user->lang('CHARACTERS', (int) $config['max_name_chars'])), +					'L_CHANGE_PASSWORD_EXPLAIN'	=> $user->lang($config['pass_complex'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_pass_chars']), $user->lang('CHARACTERS', (int) $config['max_pass_chars'])),  					'L_POSTS_IN_QUEUE'			=> $user->lang('NUM_POSTS_IN_QUEUE', $user_row['posts_in_queue']),  					'S_FOUNDER'					=> ($user->data['user_type'] == USER_FOUNDER) ? true : false, @@ -1045,7 +1085,7 @@ class acp_users  					'USER'				=> $user_row['username'],  					'USER_REGISTERED'	=> $user->format_date($user_row['user_regdate']),  					'REGISTERED_IP'		=> ($ip == 'hostname') ? gethostbyaddr($user_row['user_ip']) : $user_row['user_ip'], -					'USER_LASTACTIVE'	=> ($last_visit) ? $user->format_date($last_visit) : ' - ', +					'USER_LASTACTIVE'	=> ($last_active) ? $user->format_date($last_active) : ' - ',  					'USER_EMAIL'		=> $user_row['user_email'],  					'USER_WARNINGS'		=> $user_row['user_warnings'],  					'USER_POSTS'		=> $user_row['user_posts'], @@ -1065,6 +1105,7 @@ class acp_users  				$deleteall	= (isset($_POST['delall'])) ? true : false;  				$marked		= request_var('mark', array(0));  				$message	= utf8_normalize_nfc(request_var('message', '', true)); +				$pagination = $phpbb_container->get('pagination');  				// Sort keys  				$sort_days	= request_var('st', 0); @@ -1134,10 +1175,11 @@ class acp_users  				$log_count = 0;  				$start = view_log('user', $log_data, $log_count, $config['topics_per_page'], $start, 0, 0, $user_id, $sql_where, $sql_sort); +				$base_url = $this->u_action . "&u=$user_id&$u_sort_param"; +				$pagination->generate_template_pagination($base_url, 'pagination', 'start', $log_count, $config['topics_per_page'], $start); +  				$template->assign_vars(array(  					'S_FEEDBACK'	=> true, -					'S_ON_PAGE'		=> on_page($log_count, $config['topics_per_page'], $start), -					'PAGINATION'	=> generate_pagination($this->u_action . "&u=$user_id&$u_sort_param", $log_count, $config['topics_per_page'], $start, true),  					'S_LIMIT_DAYS'	=> $s_limit_days,  					'S_SORT_KEY'	=> $s_sort_key, @@ -1210,17 +1252,13 @@ class acp_users  								WHERE user_id = $user_id";  							$db->sql_query($sql); -							switch ($log_warnings) +							if ($log_warnings)  							{ -								case 2: -									add_log('admin', 'LOG_WARNINGS_DELETED', $user_row['username'], $num_warnings); -								break; -								case 1: -									add_log('admin', 'LOG_WARNING_DELETED', $user_row['username']); -								break; -								default: -									add_log('admin', 'LOG_WARNINGS_DELETED_ALL', $user_row['username']); -								break; +								add_log('admin', 'LOG_WARNINGS_DELETED', $user_row['username'], $num_warnings); +							} +							else +							{ +								add_log('admin', 'LOG_WARNINGS_DELETED_ALL', $user_row['username']);  							}  						}  					} @@ -1290,7 +1328,6 @@ class acp_users  						}  					} -  					$template->assign_block_vars('warn', array(  						'ID'		=> $row['warning_id'],  						'USERNAME'	=> ($row['log_operation']) ? get_username_string('full', $row['mod_user_id'], $row['mod_username'], $row['mod_user_colour']) : '-', @@ -1309,9 +1346,8 @@ class acp_users  			case 'profile':  				include($phpbb_root_path . 'includes/functions_user.' . $phpEx); -				include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx); -				$cp = new custom_profile(); +				$cp = $phpbb_container->get('profilefields.manager');  				$cp_data = $cp_error = array(); @@ -1325,15 +1361,7 @@ class acp_users  				$user_row['iso_lang_id'] = $row['lang_id'];  				$data = array( -					'icq'			=> request_var('icq', $user_row['user_icq']), -					'aim'			=> request_var('aim', $user_row['user_aim']), -					'msn'			=> request_var('msn', $user_row['user_msnm']), -					'yim'			=> request_var('yim', $user_row['user_yim']),  					'jabber'		=> utf8_normalize_nfc(request_var('jabber', $user_row['user_jabber'], true)), -					'website'		=> request_var('website', $user_row['user_website']), -					'location'		=> utf8_normalize_nfc(request_var('location', $user_row['user_from'], true)), -					'occupation'	=> utf8_normalize_nfc(request_var('occupation', $user_row['user_occ'], true)), -					'interests'		=> utf8_normalize_nfc(request_var('interests', $user_row['user_interests'], true)),  					'bday_day'		=> 0,  					'bday_month'	=> 0,  					'bday_year'		=> 0, @@ -1349,25 +1377,12 @@ class acp_users  				$data['bday_year']		= request_var('bday_year', $data['bday_year']);  				$data['user_birthday']	= sprintf('%2d-%2d-%4d', $data['bday_day'], $data['bday_month'], $data['bday_year']); -  				if ($submit)  				{  					$error = validate_data($data, array( -						'icq'			=> array( -							array('string', true, 3, 15), -							array('match', true, '#^[0-9]+$#i')), -						'aim'			=> array('string', true, 3, 255), -						'msn'			=> array('string', true, 5, 255),  						'jabber'		=> array(  							array('string', true, 5, 255),  							array('jabber')), -						'yim'			=> array('string', true, 5, 255), -						'website'		=> array( -							array('string', true, 12, 255), -							array('match', true, '#^http[s]?://(.*?\.)*?[a-z0-9\-]+\.[a-z]{2,4}#i')), -						'location'		=> array('string', true, 2, 100), -						'occupation'	=> array('string', true, 2, 500), -						'interests'		=> array('string', true, 2, 500),  						'bday_day'		=> array('num', true, 1, 31),  						'bday_month'	=> array('num', true, 1, 12),  						'bday_year'		=> array('num', true, 1901, gmdate('Y', time())), @@ -1389,15 +1404,7 @@ class acp_users  					if (!sizeof($error))  					{  						$sql_ary = array( -							'user_icq'		=> $data['icq'], -							'user_aim'		=> $data['aim'], -							'user_msnm'		=> $data['msn'], -							'user_yim'		=> $data['yim'],  							'user_jabber'	=> $data['jabber'], -							'user_website'	=> $data['website'], -							'user_from'		=> $data['location'], -							'user_occ'		=> $data['occupation'], -							'user_interests'=> $data['interests'],  							'user_birthday'	=> $data['user_birthday'],  						); @@ -1413,7 +1420,7 @@ class acp_users  					}  					// Replace "error" strings with their real, localised form -					$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); +					$error = array_map(array($user, 'lang'), $error);  				}  				$s_birthday_day_options = '<option value="0"' . ((!$data['bday_day']) ? ' selected="selected"' : '') . '>--</option>'; @@ -1441,16 +1448,7 @@ class acp_users  				unset($now);  				$template->assign_vars(array( -					'ICQ'			=> $data['icq'], -					'YIM'			=> $data['yim'], -					'AIM'			=> $data['aim'], -					'MSN'			=> $data['msn'],  					'JABBER'		=> $data['jabber'], -					'WEBSITE'		=> $data['website'], -					'LOCATION'		=> $data['location'], -					'OCCUPATION'	=> $data['occupation'], -					'INTERESTS'		=> $data['interests'], -  					'S_BIRTHDAY_DAY_OPTIONS'	=> $s_birthday_day_options,  					'S_BIRTHDAY_MONTH_OPTIONS'	=> $s_birthday_month_options,  					'S_BIRTHDAY_YEAR_OPTIONS'	=> $s_birthday_year_options, @@ -1472,15 +1470,13 @@ class acp_users  				$data = array(  					'dateformat'		=> utf8_normalize_nfc(request_var('dateformat', $user_row['user_dateformat'], true)),  					'lang'				=> basename(request_var('lang', $user_row['user_lang'])), -					'tz'				=> request_var('tz', (float) $user_row['user_timezone']), +					'tz'				=> request_var('tz', $user_row['user_timezone']),  					'style'				=> request_var('style', $user_row['user_style']), -					'dst'				=> request_var('dst', $user_row['user_dst']),  					'viewemail'			=> request_var('viewemail', $user_row['user_allow_viewemail']),  					'massemail'			=> request_var('massemail', $user_row['user_allow_massemail']),  					'hideonline'		=> request_var('hideonline', !$user_row['user_allow_viewonline']),  					'notifymethod'		=> request_var('notifymethod', $user_row['user_notify_type']),  					'notifypm'			=> request_var('notifypm', $user_row['user_notify_pm']), -					'popuppm'			=> request_var('popuppm', $this->optionget($user_row, 'popuppm')),  					'allowpm'			=> request_var('allowpm', $user_row['user_allow_pm']),  					'topic_sk'			=> request_var('topic_sk', ($user_row['user_topic_sortby_type']) ? $user_row['user_topic_sortby_type'] : 't'), @@ -1504,12 +1500,23 @@ class acp_users  					'notify'	=> request_var('notify', $user_row['user_notify']),  				); +				/** +				* Modify users preferences data +				* +				* @event core.acp_users_prefs_modify_data +				* @var	array	data			Array with users preferences data +				* @var	array	user_row		Array with user data +				* @since 3.1.0-b3 +				*/ +				$vars = array('data', 'user_row'); +				extract($phpbb_dispatcher->trigger_event('core.acp_users_prefs_modify_data', compact($vars))); +  				if ($submit)  				{  					$error = validate_data($data, array(  						'dateformat'	=> array('string', false, 1, 30),  						'lang'			=> array('match', false, '#^[a-z_\-]{2,}$#i'), -						'tz'			=> array('num', false, -14, 14), +						'tz'			=> array('timezone'),  						'topic_sk'		=> array('string', false, 1, 1),  						'topic_sd'		=> array('string', false, 1, 1), @@ -1524,7 +1531,6 @@ class acp_users  					if (!sizeof($error))  					{ -						$this->optionset($user_row, 'popuppm', $data['popuppm']);  						$this->optionset($user_row, 'viewimg', $data['view_images']);  						$this->optionset($user_row, 'viewflash', $data['view_flash']);  						$this->optionset($user_row, 'viewsmilies', $data['view_smilies']); @@ -1545,7 +1551,6 @@ class acp_users  							'user_notify_type'		=> $data['notifymethod'],  							'user_notify_pm'		=> $data['notifypm'], -							'user_dst'				=> $data['dst'],  							'user_dateformat'		=> $data['dateformat'],  							'user_lang'				=> $data['lang'],  							'user_timezone'			=> $data['tz'], @@ -1562,41 +1567,57 @@ class acp_users  							'user_notify'	=> $data['notify'],  						); -						$sql = 'UPDATE ' . USERS_TABLE . ' -							SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " -							WHERE user_id = $user_id"; -						$db->sql_query($sql); - -						// Check if user has an active session -						if ($user_row['session_id']) +						/** +						* Modify SQL query before users preferences are updated +						* +						* @event core.acp_users_prefs_modify_sql +						* @var	array	data			Array with users preferences data +						* @var	array	user_row		Array with user data +						* @var	array	sql_ary			SQL array with users preferences data to update +						* @var	array	error			Array with errors data +						* @since 3.1.0-b3 +						*/ +						$vars = array('data', 'user_row', 'sql_ary', 'error'); +						extract($phpbb_dispatcher->trigger_event('core.acp_users_prefs_modify_sql', compact($vars))); + +						if (!sizeof($error))  						{ -							// We'll update the session if user_allow_viewonline has changed and the user is a bot -							// Or if it's a regular user and the admin set it to hide the session -							if ($user_row['user_allow_viewonline'] != $sql_ary['user_allow_viewonline'] && $user_row['user_type'] == USER_IGNORE -								|| $user_row['user_allow_viewonline'] && !$sql_ary['user_allow_viewonline']) +							$sql = 'UPDATE ' . USERS_TABLE . ' +								SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " +								WHERE user_id = $user_id"; +							$db->sql_query($sql); + +							// Check if user has an active session +							if ($user_row['session_id'])  							{ -								// We also need to check if the user has the permission to cloak. -								$user_auth = new auth(); -								$user_auth->acl($user_row); +								// We'll update the session if user_allow_viewonline has changed and the user is a bot +								// Or if it's a regular user and the admin set it to hide the session +								if ($user_row['user_allow_viewonline'] != $sql_ary['user_allow_viewonline'] && $user_row['user_type'] == USER_IGNORE +									|| $user_row['user_allow_viewonline'] && !$sql_ary['user_allow_viewonline']) +								{ +									// We also need to check if the user has the permission to cloak. +									$user_auth = new \phpbb\auth\auth(); +									$user_auth->acl($user_row); -								$session_sql_ary = array( -									'session_viewonline'	=> ($user_auth->acl_get('u_hideonline')) ? $sql_ary['user_allow_viewonline'] : true, -								); +									$session_sql_ary = array( +										'session_viewonline'	=> ($user_auth->acl_get('u_hideonline')) ? $sql_ary['user_allow_viewonline'] : true, +									); -								$sql = 'UPDATE ' . SESSIONS_TABLE . ' -									SET ' . $db->sql_build_array('UPDATE', $session_sql_ary) . " -									WHERE session_user_id = $user_id"; -								$db->sql_query($sql); +									$sql = 'UPDATE ' . SESSIONS_TABLE . ' +										SET ' . $db->sql_build_array('UPDATE', $session_sql_ary) . " +										WHERE session_user_id = $user_id"; +									$db->sql_query($sql); -								unset($user_auth); +									unset($user_auth); +								}  							} -						} -						trigger_error($user->lang['USER_PREFS_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); +							trigger_error($user->lang['USER_PREFS_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); +						}  					}  					// Replace "error" strings with their real, localised form -					$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); +					$error = array_map(array($user, 'lang'), $error);  				}  				$dateformat_options = ''; @@ -1655,7 +1676,8 @@ class acp_users  					${'s_sort_' . $sort_option . '_dir'} .= '</select>';  				} -				$template->assign_vars(array( +				phpbb_timezone_select($template, $user, $data['tz'], true); +				$user_prefs_data = array(  					'S_PREFS'			=> true,  					'S_JABBER_DISABLED'	=> ($config['jab_enable'] && $user_row['user_jabber'] && @extension_loaded('xml')) ? false : true, @@ -1667,8 +1689,6 @@ class acp_users  					'NOTIFY_IM'			=> ($data['notifymethod'] == NOTIFY_IM) ? true : false,  					'NOTIFY_BOTH'		=> ($data['notifymethod'] == NOTIFY_BOTH) ? true : false,  					'NOTIFY_PM'			=> $data['notifypm'], -					'POPUP_PM'			=> $data['popuppm'], -					'DST'				=> $data['dst'],  					'BBCODE'			=> $data['bbcode'],  					'SMILIES'			=> $data['smilies'],  					'ATTACH_SIG'		=> $data['sig'], @@ -1695,75 +1715,136 @@ class acp_users  					'S_LANG_OPTIONS'	=> language_select($data['lang']),  					'S_STYLE_OPTIONS'	=> style_select($data['style']), -					'S_TZ_OPTIONS'		=> tz_select($data['tz'], true), -					)  				); +				/** +				* Modify users preferences data before assigning it to the template +				* +				* @event core.acp_users_prefs_modify_template_data +				* @var	array	data				Array with users preferences data +				* @var	array	user_row			Array with user data +				* @var	array	user_prefs_data		Array with users preferences data to be assigned to the template +				* @since 3.1.0-b3 +				*/ +				$vars = array('data', 'user_row', 'user_prefs_data'); +				extract($phpbb_dispatcher->trigger_event('core.acp_users_prefs_modify_template_data', compact($vars))); + +				$template->assign_vars($user_prefs_data); +  			break;  			case 'avatar':  				include($phpbb_root_path . 'includes/functions_display.' . $phpEx); -				include($phpbb_root_path . 'includes/functions_user.' . $phpEx); -				$can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && phpbb_is_writable($phpbb_root_path . $config['avatar_path']) && $file_uploads) ? true : false; +				$avatars_enabled = false; -				if ($submit) +				if ($config['allow_avatar'])  				{ +					$phpbb_avatar_manager = $phpbb_container->get('avatar.manager'); +					$avatar_drivers = $phpbb_avatar_manager->get_enabled_drivers(); -					if (!check_form_key($form_name)) +					// This is normalised data, without the user_ prefix +					$avatar_data = \phpbb\avatar\manager::clean_row($user_row, 'user'); + +					if ($submit)  					{ +						if (check_form_key($form_name)) +						{ +							$driver_name = $phpbb_avatar_manager->clean_driver_name($request->variable('avatar_driver', '')); + +							if (in_array($driver_name, $avatar_drivers) && !$request->is_set_post('avatar_delete')) +							{ +								$driver = $phpbb_avatar_manager->get_driver($driver_name); +								$result = $driver->process_form($request, $template, $user, $avatar_data, $error); + +								if ($result && empty($error)) +								{ +									// Success! Lets save the result in the database +									$result = array( +										'user_avatar_type' => $driver_name, +										'user_avatar' => $result['avatar'], +										'user_avatar_width' => $result['avatar_width'], +										'user_avatar_height' => $result['avatar_height'], +									); + +									$sql = 'UPDATE ' . USERS_TABLE . ' +										SET ' . $db->sql_build_array('UPDATE', $result) . ' +										WHERE user_id = ' . (int) $user_id; + +									$db->sql_query($sql); +									trigger_error($user->lang['USER_AVATAR_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); +								} +							} +						} +						else +						{  							trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); +						}  					} -					if (avatar_process_user($error, $user_row, $can_upload)) +					// Handle deletion of avatars +					if ($request->is_set_post('avatar_delete'))  					{ -						trigger_error($user->lang['USER_AVATAR_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_row['user_id'])); +						if (!confirm_box(true)) +						{ +							confirm_box(false, $user->lang('CONFIRM_AVATAR_DELETE'), build_hidden_fields(array( +									'avatar_delete'     => true)) +							); +						} +						else +						{ +							$phpbb_avatar_manager->handle_avatar_delete($db, $user, $avatar_data, USERS_TABLE, 'user_'); + +							trigger_error($user->lang['USER_AVATAR_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); +						}  					} -					// Replace "error" strings with their real, localised form -					$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); -				} +					$selected_driver = $phpbb_avatar_manager->clean_driver_name($request->variable('avatar_driver', $user_row['user_avatar_type'])); -				if (!$config['allow_avatar'] && $user_row['user_avatar_type']) -				{ -					$error[] = $user->lang['USER_AVATAR_NOT_ALLOWED']; -				} -				else if ((($user_row['user_avatar_type'] == AVATAR_UPLOAD) && !$config['allow_avatar_upload']) || -				 (($user_row['user_avatar_type'] == AVATAR_REMOTE) && !$config['allow_avatar_remote']) || -				 (($user_row['user_avatar_type'] == AVATAR_GALLERY) && !$config['allow_avatar_local'])) -				{ -					$error[] = $user->lang['USER_AVATAR_TYPE_NOT_ALLOWED']; -				} +					foreach ($avatar_drivers as $current_driver) +					{ +						$driver = $phpbb_avatar_manager->get_driver($current_driver); -				// Generate users avatar -				$avatar_img = ($user_row['user_avatar']) ? get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height'], 'USER_AVATAR', true) : '<img src="' . $phpbb_admin_path . 'images/no_avatar.gif" alt="" />'; +						$avatars_enabled = true; +						$config_name = $phpbb_avatar_manager->get_driver_config_name($driver); +						$template->set_filenames(array( +							'avatar' => "acp_avatar_options_{$config_name}.html", +						)); -				$display_gallery = (isset($_POST['display_gallery'])) ? true : false; -				$avatar_select = basename(request_var('avatar_select', '')); -				$category = basename(request_var('category', '')); +						if ($driver->prepare_form($request, $template, $user, $avatar_data, $error)) +						{ +							$driver_name = $phpbb_avatar_manager->prepare_driver_name($current_driver); +							$driver_upper = strtoupper($driver_name); -				if ($config['allow_avatar_local'] && $display_gallery) -				{ -					avatar_gallery($category, $avatar_select, 4); +							$template->assign_block_vars('avatar_drivers', array( +								'L_TITLE' => $user->lang($driver_upper . '_TITLE'), +								'L_EXPLAIN' => $user->lang($driver_upper . '_EXPLAIN'), + +								'DRIVER' => $driver_name, +								'SELECTED' => $current_driver == $selected_driver, +								'OUTPUT' => $template->assign_display('avatar'), +							)); +						} +					}  				} +				// Replace "error" strings with their real, localised form +				$error = $phpbb_avatar_manager->localize_errors($user, $error); + +				$avatar = phpbb_get_user_avatar($user_row, 'USER_AVATAR', true); +  				$template->assign_vars(array( -					'S_AVATAR'			=> true, -					'S_CAN_UPLOAD'		=> $can_upload, -					'S_UPLOAD_FILE'		=> ($config['allow_avatar'] && $can_upload && $config['allow_avatar_upload']) ? true : false, -					'S_REMOTE_UPLOAD'	=> ($config['allow_avatar'] && $can_upload && $config['allow_avatar_remote_upload']) ? true : false, -					'S_ALLOW_REMOTE'	=> ($config['allow_avatar'] && $config['allow_avatar_remote']) ? true : false, -					'S_DISPLAY_GALLERY'	=> ($config['allow_avatar'] && $config['allow_avatar_local'] && !$display_gallery) ? true : false, -					'S_IN_GALLERY'		=> ($config['allow_avatar'] && $config['allow_avatar_local'] && $display_gallery) ? true : false, - -					'AVATAR_IMAGE'			=> $avatar_img, -					'AVATAR_MAX_FILESIZE'	=> $config['avatar_filesize'], -					'USER_AVATAR_WIDTH'		=> $user_row['user_avatar_width'], -					'USER_AVATAR_HEIGHT'	=> $user_row['user_avatar_height'], - -					'L_AVATAR_EXPLAIN'	=> sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], round($config['avatar_filesize'] / 1024))) -				); +					'S_AVATAR'	=> true, +					'ERROR'			=> (!empty($error)) ? implode('<br />', $error) : '', +					'AVATAR'		=> (empty($avatar) ? '<img src="' . $phpbb_admin_path . 'images/no_avatar.gif" alt="" />' : $avatar), + +					'S_FORM_ENCTYPE'	=> ' enctype="multipart/form-data"', + +					'L_AVATAR_EXPLAIN'	=> sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], $config['avatar_filesize'] / 1024), + +					'S_AVATARS_ENABLED'		=> ($config['allow_avatar'] && $avatars_enabled), +				));  			break; @@ -1865,7 +1946,7 @@ class acp_users  					}  					// Replace "error" strings with their real, localised form -					$error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); +					$error = array_map(array($user, 'lang'), $error);  				}  				$signature_preview = ''; @@ -1895,7 +1976,7 @@ class acp_users  					'FLASH_STATUS'			=> ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'],  					'URL_STATUS'			=> ($config['allow_sig_links']) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], -					'L_SIGNATURE_EXPLAIN'	=> sprintf($user->lang['SIGNATURE_EXPLAIN'], $config['max_sig_chars']), +					'L_SIGNATURE_EXPLAIN'	=> $user->lang('SIGNATURE_EXPLAIN', (int) $config['max_sig_chars']),  					'S_BBCODE_ALLOWED'		=> $config['allow_sig_bbcode'],  					'S_SMILIES_ALLOWED'		=> $config['allow_sig_smilies'], @@ -1914,6 +1995,7 @@ class acp_users  				$start		= request_var('start', 0);  				$deletemark = (isset($_POST['delmarked'])) ? true : false;  				$marked		= request_var('mark', array(0)); +				$pagination = $phpbb_container->get('pagination');  				// Sort keys  				$sort_key	= request_var('sk', 'a'); @@ -1956,7 +2038,7 @@ class acp_users  						$message = (sizeof($log_attachments) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED']; -						add_log('admin', 'LOG_ATTACHMENTS_DELETED', implode(', ', $log_attachments)); +						add_log('admin', 'LOG_ATTACHMENTS_DELETED', implode($user->lang['COMMA_SEPARATOR'], $log_attachments));  						trigger_error($message . adm_back_link($this->u_action . '&u=' . $user_id));  					}  					else @@ -2049,14 +2131,14 @@ class acp_users  				}  				$db->sql_freeresult($result); +				$base_url = $this->u_action . "&u=$user_id&sk=$sort_key&sd=$sort_dir"; +				$pagination->generate_template_pagination($base_url, 'pagination', 'start', $num_attachments, $config['topics_per_page'], $start); +  				$template->assign_vars(array(  					'S_ATTACHMENTS'		=> true, -					'S_ON_PAGE'			=> on_page($num_attachments, $config['topics_per_page'], $start),  					'S_SORT_KEY'		=> $s_sort_key,  					'S_SORT_DIR'		=> $s_sort_dir, - -					'PAGINATION'		=> generate_pagination($this->u_action . "&u=$user_id&sk=$sort_key&sd=$sort_dir", $num_attachments, $config['topics_per_page'], $start, true)) -				); +				));  			break; @@ -2190,7 +2272,6 @@ class acp_users  					$error = array();  				} -  				$sql = 'SELECT ug.*, g.*  					FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . " ug  					WHERE ug.user_id = $user_id @@ -2294,7 +2375,7 @@ class acp_users  					// Select auth options  					$sql = 'SELECT auth_option, is_local, is_global  						FROM ' . ACL_OPTIONS_TABLE . ' -						WHERE auth_option ' . $db->sql_like_expression($db->any_char . '_') . ' +						WHERE auth_option ' . $db->sql_like_expression($db->get_any_char() . '_') . '  							AND is_global = 1  						ORDER BY auth_option';  					$result = $db->sql_query($sql); @@ -2314,7 +2395,7 @@ class acp_users  				{  					$sql = 'SELECT auth_option, is_local, is_global  						FROM ' . ACL_OPTIONS_TABLE . " -						WHERE auth_option " . $db->sql_like_expression($db->any_char . '_') . " +						WHERE auth_option " . $db->sql_like_expression($db->get_any_char() . '_') . "  							AND is_local = 1  						ORDER BY is_global DESC, auth_option";  					$result = $db->sql_query($sql); @@ -2411,5 +2492,3 @@ class acp_users  		return phpbb_optionget($user->keyoptions[$key], $var);  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php index 88c5bbe592..272d38bcc8 100644 --- a/phpBB/includes/acp/acp_words.php +++ b/phpBB/includes/acp/acp_words.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -18,7 +21,6 @@ if (!defined('IN_PHPBB'))  /**  * @todo [words] check regular expressions for special char replacements (stored specialchared in db) -* @package acp  */  class acp_words  { @@ -102,7 +104,7 @@ class acp_words  					'word'			=> $word,  					'replacement'	=> $replacement  				); -				 +  				if ($word_id)  				{  					$db->sql_query('UPDATE ' . WORDS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE word_id = ' . $word_id); @@ -163,7 +165,6 @@ class acp_words  			break;  		} -  		$template->assign_vars(array(  			'U_ACTION'			=> $this->u_action,  			'S_HIDDEN_FIELDS'	=> $s_hidden_fields) @@ -186,5 +187,3 @@ class acp_words  		$db->sql_freeresult($result);  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index 10d7973da6..905e981cdc 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -1,10 +1,13 @@  <?php  /**  * -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ @@ -18,9 +21,8 @@ if (!defined('IN_PHPBB'))  /**  * ACP Permission/Auth class -* @package phpBB3  */ -class auth_admin extends auth +class auth_admin extends \phpbb\auth\auth  {  	/**  	* Init auth settings @@ -131,7 +133,7 @@ class auth_admin extends auth  			{  				if ($user->data['user_id'] != $userdata['user_id'])  				{ -					$auth2 = new auth(); +					$auth2 = new \phpbb\auth\auth();  					$auth2->acl($userdata);  				}  				else @@ -140,7 +142,6 @@ class auth_admin extends auth  					$auth2 = &$auth;  				} -  				$hold_ary[$userdata['user_id']] = array();  				foreach ($forum_ids as $f_id)  				{ @@ -182,7 +183,10 @@ class auth_admin extends auth  		}  		// Defining the user-function here to save some memory -		$return_acl_fill = create_function('$value', 'return ' . $acl_fill . ';'); +		$return_acl_fill = function () use ($acl_fill) +		{ +			return $acl_fill; +		};  		// Actually fill the gaps  		if (sizeof($hold_ary)) @@ -262,7 +266,8 @@ class auth_admin extends auth  	*/  	function display_mask($mode, $permission_type, &$hold_ary, $user_mode = 'user', $local = false, $group_display = true)  	{ -		global $template, $user, $db, $phpbb_root_path, $phpEx; +		global $template, $user, $db, $phpbb_root_path, $phpEx, $phpbb_container; +		$phpbb_permissions = $phpbb_container->get('acl.permissions');  		// Define names for template loops, might be able to be set  		$tpl_pmask = 'p_mask'; @@ -270,7 +275,7 @@ class auth_admin extends auth  		$tpl_category = 'category';  		$tpl_mask = 'mask'; -		$l_acl_type = (isset($user->lang['ACL_TYPE_' . (($local) ? 'LOCAL' : 'GLOBAL') . '_' . strtoupper($permission_type)])) ? $user->lang['ACL_TYPE_' . (($local) ? 'LOCAL' : 'GLOBAL') . '_' . strtoupper($permission_type)] : 'ACL_TYPE_' . (($local) ? 'LOCAL' : 'GLOBAL') . '_' . strtoupper($permission_type); +		$l_acl_type = $phpbb_permissions->get_type_lang($permission_type, (($local) ? 'local' : 'global'));  		// Allow trace for viewing permissions and in user mode  		$show_trace = ($mode == 'view' && $user_mode == 'user') ? true : false; @@ -506,7 +511,7 @@ class auth_admin extends auth  						'FORUM_ID'			=> $forum_id)  					); -					$this->assign_cat_array($ug_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, $show_trace, ($mode == 'view')); +					$this->assign_cat_array($ug_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, ($mode == 'view'), $show_trace);  					unset($content_array[$ug_id]);  				} @@ -530,8 +535,8 @@ class auth_admin extends auth  					'NAME'			=> $ug_name,  					'CATEGORIES'	=> implode('</th><th>', $categories), -					'USER_GROUPS_DEFAULT'	=> ($user_mode == 'user' && isset($user_groups_default[$ug_id]) && sizeof($user_groups_default[$ug_id])) ? implode(', ', $user_groups_default[$ug_id]) : '', -					'USER_GROUPS_CUSTOM'	=> ($user_mode == 'user' && isset($user_groups_custom[$ug_id]) && sizeof($user_groups_custom[$ug_id])) ? implode(', ', $user_groups_custom[$ug_id]) : '', +					'USER_GROUPS_DEFAULT'	=> ($user_mode == 'user' && isset($user_groups_default[$ug_id]) && sizeof($user_groups_default[$ug_id])) ? implode($user->lang['COMMA_SEPARATOR'], $user_groups_default[$ug_id]) : '', +					'USER_GROUPS_CUSTOM'	=> ($user_mode == 'user' && isset($user_groups_custom[$ug_id]) && sizeof($user_groups_custom[$ug_id])) ? implode($user->lang['COMMA_SEPARATOR'], $user_groups_custom[$ug_id]) : '',  					'L_ACL_TYPE'			=> $l_acl_type,  					'S_LOCAL'		=> ($local) ? true : false, @@ -593,7 +598,7 @@ class auth_admin extends auth  						'FORUM_ID'			=> $forum_id)  					); -					$this->assign_cat_array($forum_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, $show_trace, ($mode == 'view')); +					$this->assign_cat_array($forum_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, ($mode == 'view'), $show_trace);  				}  				unset($hold_ary[$ug_id], $ug_names_ary[$ug_id]); @@ -649,9 +654,9 @@ class auth_admin extends auth  				{  					$template->assign_block_vars('role_mask.users', array(  						'USER_ID'		=> $row['user_id'], -						'USERNAME'		=> $row['username'], -						'U_PROFILE'		=> append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=viewprofile&u={$row['user_id']}")) -					); +						'USERNAME'		=> get_username_string('username', $row['user_id'], $row['username']), +						'U_PROFILE'		=> get_username_string('profile', $row['user_id'], $row['username']), +					));  				}  				$db->sql_freeresult($result);  			} @@ -833,7 +838,7 @@ class auth_admin extends auth  		}  		// Remove current auth options... -		$auth_option_ids = array((int)$any_option_id); +		$auth_option_ids = array((int) $any_option_id);  		foreach ($auth as $auth_option => $auth_setting)  		{  			$auth_option_ids[] = (int) $this->acl_options['id'][$auth_option]; @@ -1022,7 +1027,7 @@ class auth_admin extends auth  			// Get permission type  			$sql = 'SELECT auth_option, auth_option_id  				FROM ' . ACL_OPTIONS_TABLE . " -				WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char); +				WHERE auth_option " . $db->sql_like_expression($permission_type . $db->get_any_char());  			$result = $db->sql_query($sql);  			$auth_id_ary = array(); @@ -1099,9 +1104,11 @@ class auth_admin extends auth  	* Assign category to template  	* used by display_mask()  	*/ -	function assign_cat_array(&$category_array, $tpl_cat, $tpl_mask, $ug_id, $forum_id, $show_trace = false, $s_view) +	function assign_cat_array(&$category_array, $tpl_cat, $tpl_mask, $ug_id, $forum_id, $s_view, $show_trace = false)  	{ -		global $template, $user, $phpbb_admin_path, $phpEx; +		global $template, $user, $phpbb_admin_path, $phpEx, $phpbb_container; + +		$phpbb_permissions = $phpbb_container->get('acl.permissions');  		@reset($category_array);  		while (list($cat, $cat_array) = each($category_array)) @@ -1111,8 +1118,8 @@ class auth_admin extends auth  				'S_NEVER'	=> ($cat_array['S_NEVER'] && !$cat_array['S_YES'] && !$cat_array['S_NO']) ? true : false,  				'S_NO'		=> ($cat_array['S_NO'] && !$cat_array['S_NEVER'] && !$cat_array['S_YES']) ? true : false, -				'CAT_NAME'	=> $user->lang['permission_cat'][$cat]) -			); +				'CAT_NAME'	=> $phpbb_permissions->get_category_lang($cat), +			));  			/*	Sort permissions by name (more naturaly and user friendly than sorting by a primary key)  			*	Commented out due to it's memory consumption and time needed @@ -1146,8 +1153,8 @@ class auth_admin extends auth  						'U_TRACE'		=> ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission") : '',  						'UA_TRACE'		=> ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission", false) : '', -						'PERMISSION'	=> $user->lang['acl_' . $permission]['lang']) -					); +						'PERMISSION'	=> $phpbb_permissions->get_permission_lang($permission), +					));  				}  				else  				{ @@ -1164,8 +1171,8 @@ class auth_admin extends auth  						'U_TRACE'		=> ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission") : '',  						'UA_TRACE'		=> ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission", false) : '', -						'PERMISSION'	=> $user->lang['acl_' . $permission]['lang']) -					); +						'PERMISSION'	=> $phpbb_permissions->get_permission_lang($permission), +					));  				}  			}  		} @@ -1177,7 +1184,9 @@ class auth_admin extends auth  	*/  	function build_permission_array(&$permission_row, &$content_array, &$categories, $key_sort_array)  	{ -		global $user; +		global $user, $phpbb_container; + +		$phpbb_permissions = $phpbb_container->get('acl.permissions');  		foreach ($key_sort_array as $forum_id)  		{ @@ -1192,20 +1201,12 @@ class auth_admin extends auth  			@reset($permissions);  			while (list($permission, $auth_setting) = each($permissions))  			{ -				if (!isset($user->lang['acl_' . $permission])) -				{ -					$user->lang['acl_' . $permission] = array( -						'cat'	=> 'misc', -						'lang'	=> '{ acl_' . $permission . ' }' -					); -				} - -				$cat = $user->lang['acl_' . $permission]['cat']; +				$cat = $phpbb_permissions->get_permission_category($permission);  				// Build our categories array  				if (!isset($categories[$cat]))  				{ -					$categories[$cat] = $user->lang['permission_cat'][$cat]; +					$categories[$cat] = $phpbb_permissions->get_category_lang($cat);  				}  				// Build our content array @@ -1281,5 +1282,3 @@ class auth_admin extends auth  		return true;  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_attachments.php b/phpBB/includes/acp/info/acp_attachments.php index b77785801f..ff6e342f77 100644 --- a/phpBB/includes/acp/info/acp_attachments.php +++ b/phpBB/includes/acp/info/acp_attachments.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_attachments_info  {  	function module() @@ -23,7 +23,8 @@ class acp_attachments_info  				'attach'		=> array('title' => 'ACP_ATTACHMENT_SETTINGS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_BOARD_CONFIGURATION', 'ACP_ATTACHMENTS')),  				'extensions'	=> array('title' => 'ACP_MANAGE_EXTENSIONS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')),  				'ext_groups'	=> array('title' => 'ACP_EXTENSION_GROUPS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')), -				'orphan'		=> array('title' => 'ACP_ORPHAN_ATTACHMENTS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')) +				'orphan'		=> array('title' => 'ACP_ORPHAN_ATTACHMENTS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')), +				'manage'		=> array('title' => 'ACP_MANAGE_ATTACHMENTS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')),  			),  		);  	} @@ -36,5 +37,3 @@ class acp_attachments_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_ban.php b/phpBB/includes/acp/info/acp_ban.php index df51011ec6..4959f4da41 100644 --- a/phpBB/includes/acp/info/acp_ban.php +++ b/phpBB/includes/acp/info/acp_ban.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_ban_info  {  	function module() @@ -35,5 +35,3 @@ class acp_ban_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_bbcodes.php b/phpBB/includes/acp/info/acp_bbcodes.php index c0206432d6..2bca319cc3 100644 --- a/phpBB/includes/acp/info/acp_bbcodes.php +++ b/phpBB/includes/acp/info/acp_bbcodes.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_bbcodes_info  {  	function module() @@ -33,5 +33,3 @@ class acp_bbcodes_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_board.php b/phpBB/includes/acp/info/acp_board.php index 3e18f55940..6838b4f8ba 100644 --- a/phpBB/includes/acp/info/acp_board.php +++ b/phpBB/includes/acp/info/acp_board.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_board_info  {  	function module() @@ -48,5 +48,3 @@ class acp_board_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_bots.php b/phpBB/includes/acp/info/acp_bots.php index 45087f9225..9aa24927af 100644 --- a/phpBB/includes/acp/info/acp_bots.php +++ b/phpBB/includes/acp/info/acp_bots.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_bots_info  {  	function module() @@ -33,6 +33,3 @@ class acp_bots_info  	{  	}  } - - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_captcha.php b/phpBB/includes/acp/info/acp_captcha.php index b2541c252c..99dc5ce0e5 100644 --- a/phpBB/includes/acp/info/acp_captcha.php +++ b/phpBB/includes/acp/info/acp_captcha.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_captcha_info  {  	function module() @@ -34,5 +34,3 @@ class acp_captcha_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_contact.php b/phpBB/includes/acp/info/acp_contact.php new file mode 100644 index 0000000000..548eb52816 --- /dev/null +++ b/phpBB/includes/acp/info/acp_contact.php @@ -0,0 +1,30 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* @package module_install +*/ +class acp_contact_info +{ +	public function module() +	{ +		return array( +			'filename'	=> 'acp_contact', +			'title'		=> 'ACP_CONTACT', +			'version'	=> '1.0.0', +			'modes'		=> array( +				'contact'	=> array('title' => 'ACP_CONTACT_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), +			), +		); +	} +} diff --git a/phpBB/includes/acp/info/acp_database.php b/phpBB/includes/acp/info/acp_database.php index 85c3c8b21c..5cf9da24fb 100644 --- a/phpBB/includes/acp/info/acp_database.php +++ b/phpBB/includes/acp/info/acp_database.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_database_info  {  	function module() @@ -34,5 +34,3 @@ class acp_database_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_disallow.php b/phpBB/includes/acp/info/acp_disallow.php index 41315eb716..ebd44b515c 100644 --- a/phpBB/includes/acp/info/acp_disallow.php +++ b/phpBB/includes/acp/info/acp_disallow.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_disallow_info  {  	function module() @@ -33,6 +33,3 @@ class acp_disallow_info  	{  	}  } - - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_email.php b/phpBB/includes/acp/info/acp_email.php index 4ad7bca58b..2f77fc617c 100644 --- a/phpBB/includes/acp/info/acp_email.php +++ b/phpBB/includes/acp/info/acp_email.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_email_info  {  	function module() @@ -33,6 +33,3 @@ class acp_email_info  	{  	}  } - - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_extensions.php b/phpBB/includes/acp/info/acp_extensions.php new file mode 100644 index 0000000000..d4cf1b0ed5 --- /dev/null +++ b/phpBB/includes/acp/info/acp_extensions.php @@ -0,0 +1,35 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +class acp_extensions_info +{ +	function module() +	{ +		return array( +			'filename'	=> 'acp_extensions', +			'title'		=> 'ACP_EXTENSION_MANAGEMENT', +			'version'	=> '1.0.0', +			'modes'		=> array( +				'main'		=> array('title' => 'ACP_EXTENSIONS', 'auth' => 'acl_a_extensions', 'cat' => array('ACP_EXTENSION_MANAGEMENT')), +			), +		); +	} + +	function install() +	{ +	} + +	function uninstall() +	{ +	} +} diff --git a/phpBB/includes/acp/info/acp_forums.php b/phpBB/includes/acp/info/acp_forums.php index 8d82eaf42d..647090c8c3 100644 --- a/phpBB/includes/acp/info/acp_forums.php +++ b/phpBB/includes/acp/info/acp_forums.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_forums_info  {  	function module() @@ -33,5 +33,3 @@ class acp_forums_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_groups.php b/phpBB/includes/acp/info/acp_groups.php index 3910c24e6b..6c5ad70d97 100644 --- a/phpBB/includes/acp/info/acp_groups.php +++ b/phpBB/includes/acp/info/acp_groups.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_groups_info  {  	function module() @@ -21,6 +21,7 @@ class acp_groups_info  			'version'	=> '1.0.0',  			'modes'		=> array(  				'manage'		=> array('title' => 'ACP_GROUPS_MANAGE', 'auth' => 'acl_a_group', 'cat' => array('ACP_GROUPS')), +				'position'		=> array('title' => 'ACP_GROUPS_POSITION', 'auth' => 'acl_a_group', 'cat' => array('ACP_GROUPS')),  			),  		);  	} @@ -33,5 +34,3 @@ class acp_groups_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_icons.php b/phpBB/includes/acp/info/acp_icons.php index 16bf753940..001d6cb402 100644 --- a/phpBB/includes/acp/info/acp_icons.php +++ b/phpBB/includes/acp/info/acp_icons.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_icons_info  {  	function module() @@ -34,5 +34,3 @@ class acp_icons_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_inactive.php b/phpBB/includes/acp/info/acp_inactive.php index e17fbda9dd..442eb13c30 100644 --- a/phpBB/includes/acp/info/acp_inactive.php +++ b/phpBB/includes/acp/info/acp_inactive.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_inactive_info  {  	function module() @@ -33,5 +33,3 @@ class acp_inactive_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_jabber.php b/phpBB/includes/acp/info/acp_jabber.php index 7bcf7744e1..c1dfb2aca7 100644 --- a/phpBB/includes/acp/info/acp_jabber.php +++ b/phpBB/includes/acp/info/acp_jabber.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_jabber_info  {  	function module() @@ -33,4 +33,3 @@ class acp_jabber_info  	{  	}  } -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_language.php b/phpBB/includes/acp/info/acp_language.php index f7606631fe..b9efbbbd9a 100644 --- a/phpBB/includes/acp/info/acp_language.php +++ b/phpBB/includes/acp/info/acp_language.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_language_info  {  	function module() @@ -20,7 +20,7 @@ class acp_language_info  			'title'		=> 'ACP_LANGUAGE',  			'version'	=> '1.0.0',  			'modes'		=> array( -				'lang_packs'		=> array('title' => 'ACP_LANGUAGE_PACKS', 'auth' => 'acl_a_language', 'cat' => array('ACP_GENERAL_TASKS')), +				'lang_packs'		=> array('title' => 'ACP_LANGUAGE_PACKS', 'auth' => 'acl_a_language', 'cat' => array('ACP_LANGUAGE')),  			),  		);  	} @@ -33,5 +33,3 @@ class acp_language_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_logs.php b/phpBB/includes/acp/info/acp_logs.php index f119e10b83..e9e6034cd4 100644 --- a/phpBB/includes/acp/info/acp_logs.php +++ b/phpBB/includes/acp/info/acp_logs.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_logs_info  {  	function module() @@ -36,5 +36,3 @@ class acp_logs_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_main.php b/phpBB/includes/acp/info/acp_main.php index 5574cc40d1..51259e3bd9 100644 --- a/phpBB/includes/acp/info/acp_main.php +++ b/phpBB/includes/acp/info/acp_main.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_main_info  {  	function module() @@ -33,5 +33,3 @@ class acp_main_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_modules.php b/phpBB/includes/acp/info/acp_modules.php index 886f17d628..a47cd4ad83 100644 --- a/phpBB/includes/acp/info/acp_modules.php +++ b/phpBB/includes/acp/info/acp_modules.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_modules_info  {  	function module() @@ -35,5 +35,3 @@ class acp_modules_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_permission_roles.php b/phpBB/includes/acp/info/acp_permission_roles.php index 3ab2fecd53..e8aa13375d 100644 --- a/phpBB/includes/acp/info/acp_permission_roles.php +++ b/phpBB/includes/acp/info/acp_permission_roles.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_permission_roles_info  {  	function module() @@ -36,5 +36,3 @@ class acp_permission_roles_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_permissions.php b/phpBB/includes/acp/info/acp_permissions.php index 6f341742f3..3ec592a300 100644 --- a/phpBB/includes/acp/info/acp_permissions.php +++ b/phpBB/includes/acp/info/acp_permissions.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_permissions_info  {  	function module() @@ -50,5 +50,3 @@ class acp_permissions_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_php_info.php b/phpBB/includes/acp/info/acp_php_info.php index 7d716b0f83..af978e0daa 100644 --- a/phpBB/includes/acp/info/acp_php_info.php +++ b/phpBB/includes/acp/info/acp_php_info.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_php_info_info  {  	function module() @@ -33,5 +33,3 @@ class acp_php_info_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_profile.php b/phpBB/includes/acp/info/acp_profile.php index 8590226038..307e711eee 100644 --- a/phpBB/includes/acp/info/acp_profile.php +++ b/phpBB/includes/acp/info/acp_profile.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_profile_info  {  	function module() @@ -33,5 +33,3 @@ class acp_profile_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_prune.php b/phpBB/includes/acp/info/acp_prune.php index 46565c4f16..58cb1ba9ab 100644 --- a/phpBB/includes/acp/info/acp_prune.php +++ b/phpBB/includes/acp/info/acp_prune.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_prune_info  {  	function module() @@ -21,7 +21,7 @@ class acp_prune_info  			'version'	=> '1.0.0',  			'modes'		=> array(  				'forums'	=> array('title' => 'ACP_PRUNE_FORUMS', 'auth' => 'acl_a_prune', 'cat' => array('ACP_MANAGE_FORUMS')), -				'users'		=> array('title' => 'ACP_PRUNE_USERS', 'auth' => 'acl_a_userdel', 'cat' => array('ACP_USER_SECURITY')), +				'users'		=> array('title' => 'ACP_PRUNE_USERS', 'auth' => 'acl_a_userdel', 'cat' => array('ACP_CAT_USERS')),  			),  		);  	} @@ -34,5 +34,3 @@ class acp_prune_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_ranks.php b/phpBB/includes/acp/info/acp_ranks.php index 06b9c6d284..3cc9b4a428 100644 --- a/phpBB/includes/acp/info/acp_ranks.php +++ b/phpBB/includes/acp/info/acp_ranks.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_ranks_info  {  	function module() @@ -33,5 +33,3 @@ class acp_ranks_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_reasons.php b/phpBB/includes/acp/info/acp_reasons.php index 65d805ee18..c48fd1aacd 100644 --- a/phpBB/includes/acp/info/acp_reasons.php +++ b/phpBB/includes/acp/info/acp_reasons.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_reasons_info  {  	function module() @@ -33,5 +33,3 @@ class acp_reasons_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_search.php b/phpBB/includes/acp/info/acp_search.php index 4afd6c6994..5d681a7174 100644 --- a/phpBB/includes/acp/info/acp_search.php +++ b/phpBB/includes/acp/info/acp_search.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_search_info  {  	function module() @@ -34,5 +34,3 @@ class acp_search_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_send_statistics.php b/phpBB/includes/acp/info/acp_send_statistics.php index de5dcdb8ad..a4f2ddc420 100644 --- a/phpBB/includes/acp/info/acp_send_statistics.php +++ b/phpBB/includes/acp/info/acp_send_statistics.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_send_statistics_info  {  	function module() @@ -33,5 +33,3 @@ class acp_send_statistics_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_styles.php b/phpBB/includes/acp/info/acp_styles.php index db67167e39..c0ab005502 100644 --- a/phpBB/includes/acp/info/acp_styles.php +++ b/phpBB/includes/acp/info/acp_styles.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_styles_info  {  	function module() @@ -18,12 +18,10 @@ class acp_styles_info  		return array(  			'filename'	=> 'acp_styles',  			'title'		=> 'ACP_CAT_STYLES', -			'version'	=> '1.0.0', +			'version'	=> '2.0.0',  			'modes'		=> array(  				'style'		=> array('title' => 'ACP_STYLES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')), -				'template'	=> array('title' => 'ACP_TEMPLATES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), -				'theme'		=> array('title' => 'ACP_THEMES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), -				'imageset'	=> array('title' => 'ACP_IMAGESETS', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), +				'install'	=> array('title' => 'ACP_STYLES_INSTALL', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')),  			),  		);  	} @@ -36,5 +34,3 @@ class acp_styles_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_update.php b/phpBB/includes/acp/info/acp_update.php index 886cdc94d5..ca00f6d305 100644 --- a/phpBB/includes/acp/info/acp_update.php +++ b/phpBB/includes/acp/info/acp_update.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_update_info  {  	function module() @@ -33,5 +33,3 @@ class acp_update_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_users.php b/phpBB/includes/acp/info/acp_users.php index 10081ac870..ab69523cde 100644 --- a/phpBB/includes/acp/info/acp_users.php +++ b/phpBB/includes/acp/info/acp_users.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_users_info  {  	function module() @@ -43,5 +43,3 @@ class acp_users_info  	{  	}  } - -?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_words.php b/phpBB/includes/acp/info/acp_words.php index a2417f8a7f..3c8c79f25f 100644 --- a/phpBB/includes/acp/info/acp_words.php +++ b/phpBB/includes/acp/info/acp_words.php @@ -1,16 +1,16 @@  <?php  /**  * -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file.  *  */ -/** -* @package module_install -*/  class acp_words_info  {  	function module() @@ -33,5 +33,3 @@ class acp_words_info  	{  	}  } - -?>
\ No newline at end of file  | 
